- [Issue 3694] ASN.1 package does incorrect BER encoding/decoding for negative integers.
| | |
| | | */ |
| | | public static byte[] encodeValue(int intValue) |
| | | { |
| | | if (intValue < 0) |
| | | { |
| | | if ((intValue & 0xFFFFFF80) == 0xFFFFFF80) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) (intValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((intValue & 0xFFFF8000) == 0xFFFF8000) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((intValue >> 8) & 0xFF), |
| | | (byte) (intValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((intValue & 0xFF800000) == 0xFF800000) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((intValue >> 16) & 0xFF), |
| | | (byte) ((intValue >> 8) & 0xFF), |
| | | (byte) (intValue & 0xFF) |
| | | }; |
| | | } |
| | | else |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((intValue >> 24) & 0xFF), |
| | | (byte) ((intValue >> 16) & 0xFF), |
| | | (byte) ((intValue >> 8) & 0xFF), |
| | | (byte) (intValue & 0xFF) |
| | | }; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if ((intValue & 0x0000007F) == intValue) |
| | | { |
| | | return new byte[] |
| | |
| | | }; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | public static byte[] encodeLongValue(long longValue) |
| | | { |
| | | if (longValue < 0) |
| | | { |
| | | if ((longValue & 0xFFFFFFFFFFFFFF80L) == 0xFFFFFFFFFFFFFF80L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 24) & 0xFF), |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 32) & 0xFF), |
| | | (byte) ((longValue >> 24) & 0xFF), |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 40) & 0xFF), |
| | | (byte) ((longValue >> 32) & 0xFF), |
| | | (byte) ((longValue >> 24) & 0xFF), |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else if ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L) |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 48) & 0xFF), |
| | | (byte) ((longValue >> 40) & 0xFF), |
| | | (byte) ((longValue >> 32) & 0xFF), |
| | | (byte) ((longValue >> 24) & 0xFF), |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | else |
| | | { |
| | | return new byte[] |
| | | { |
| | | (byte) ((longValue >> 56) & 0xFF), |
| | | (byte) ((longValue >> 48) & 0xFF), |
| | | (byte) ((longValue >> 40) & 0xFF), |
| | | (byte) ((longValue >> 32) & 0xFF), |
| | | (byte) ((longValue >> 24) & 0xFF), |
| | | (byte) ((longValue >> 16) & 0xFF), |
| | | (byte) ((longValue >> 8) & 0xFF), |
| | | (byte) (longValue & 0xFF) |
| | | }; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if ((longValue & 0x000000000000007FL) == longValue) |
| | | { |
| | | return new byte[] |
| | |
| | | }; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | * object will be considered equal if it is an ASN.1 element (or a |
| | | * subclass) with the same type and encoded value. |
| | | */ |
| | | @Override |
| | | public final boolean equals(Object o) |
| | | { |
| | | if (this == o) |
| | |
| | | * |
| | | * @return The hash code for this ASN.1 element. |
| | | */ |
| | | @Override |
| | | public final int hashCode() |
| | | { |
| | | int hashCode = type; |
| | |
| | | * |
| | | * @return A string representation of this ASN.1 element. |
| | | */ |
| | | @Override |
| | | public final String toString() |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | |
| | | * @throws ASN1Exception If the provided array is null or is not between one |
| | | * and four bytes in length. |
| | | */ |
| | | @Override |
| | | public void setValue(byte[] value) |
| | | throws ASN1Exception |
| | | { |
| | |
| | | } |
| | | |
| | | int intValue = 0; |
| | | |
| | | if (value[0] < 0) |
| | | { |
| | | intValue = 0xFFFFFFFF; |
| | | } |
| | | |
| | | for (byte b : value) |
| | | { |
| | | intValue = (intValue << 8) | (b & 0xFF); |
| | |
| | | System.arraycopy(encodedElement, valueStartPos, value, 0, length); |
| | | |
| | | int intValue = 0; |
| | | |
| | | if (value[0] < 0) |
| | | { |
| | | intValue = 0xFFFFFFFF; |
| | | } |
| | | |
| | | for (byte b : value) |
| | | { |
| | | intValue = (intValue << 8) | (b & 0xFF); |
| | |
| | | * |
| | | * @param buffer The buffer to which the information should be appended. |
| | | */ |
| | | @Override |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("ASN1Integer(type="); |
| | |
| | | * @param indent The number of spaces that should be used to indent the |
| | | * resulting string representation. |
| | | */ |
| | | @Override |
| | | public void toString(StringBuilder buffer, int indent) |
| | | { |
| | | StringBuilder indentBuf = new StringBuilder(indent); |
| | |
| | | * @throws ASN1Exception If the provided array is null or is not between one |
| | | * and four bytes in length. |
| | | */ |
| | | @Override |
| | | public void setValue(byte[] value) |
| | | throws ASN1Exception |
| | | { |
| | |
| | | } |
| | | |
| | | long longValue = 0; |
| | | |
| | | if (value[0] < 0) |
| | | { |
| | | longValue = 0xFFFFFFFFFFFFFFFFL; |
| | | } |
| | | |
| | | for (byte b : value) |
| | | { |
| | | longValue = (longValue << 8) | (b & 0xFF); |
| | |
| | | System.arraycopy(encodedElement, valueStartPos, value, 0, length); |
| | | |
| | | long longValue = 0; |
| | | |
| | | if (value[0] < 0) |
| | | { |
| | | longValue = 0xFFFFFFFFFFFFFFFFL; |
| | | } |
| | | |
| | | for (byte b : value) |
| | | { |
| | | longValue = (longValue << 8) | (b & 0xFF); |
| | |
| | | * |
| | | * @param buffer The buffer to which the information should be appended. |
| | | */ |
| | | @Override |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("ASN1Long(type="); |
| | |
| | | * @param indent The number of spaces that should be used to indent the |
| | | * resulting string representation. |
| | | */ |
| | | @Override |
| | | public void toString(StringBuilder buffer, int indent) |
| | | { |
| | | StringBuilder indentBuf = new StringBuilder(indent); |
| | |
| | | |
| | | |
| | | /** |
| | | * Tests that negative integers are encoded according |
| | | * to ASN.1 BER specification. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testNegativeIntEncoding() |
| | | throws Exception |
| | | { |
| | | byte[] value = null; |
| | | // Some negative integers of interest |
| | | // to test specific ranges/boundaries. |
| | | value = ASN1Integer.encodeValue(-1); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | value = ASN1Integer.encodeValue(-2); |
| | | assertEquals(value[0], (byte) 0xFE); |
| | | value = ASN1Integer.encodeValue(-127); |
| | | assertEquals(value[0], (byte) 0x81); |
| | | value = ASN1Integer.encodeValue(-128); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | value = ASN1Integer.encodeValue(-255); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x01); |
| | | value = ASN1Integer.encodeValue(-256); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | value = ASN1Integer.encodeValue(-65535); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x01); |
| | | value = ASN1Integer.encodeValue(-65536); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | value = ASN1Integer.encodeValue(-2147483647); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | assertEquals(value[3], (byte) 0x01); |
| | | value = ASN1Integer.encodeValue(-2147483648); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | assertEquals(value[3], (byte) 0x00); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the <CODE>setValue</CODE> method that takes an int argument. |
| | | * |
| | | * @param i The integer value to use for the test. |
| | |
| | | |
| | | |
| | | /** |
| | | * Tests that negative integers are encoded according |
| | | * to ASN.1 BER specification. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testNegativeLongEncoding() |
| | | throws Exception |
| | | { |
| | | byte[] value = null; |
| | | // Some negative integers of interest |
| | | // to test specific ranges/boundaries. |
| | | value = ASN1Long.encodeLongValue(-1L); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | value = ASN1Long.encodeLongValue(-2L); |
| | | assertEquals(value[0], (byte) 0xFE); |
| | | value = ASN1Long.encodeLongValue(-127L); |
| | | assertEquals(value[0], (byte) 0x81); |
| | | value = ASN1Long.encodeLongValue(-128L); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | value = ASN1Long.encodeLongValue(-255L); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x01); |
| | | value = ASN1Long.encodeLongValue(-256L); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | value = ASN1Long.encodeLongValue(-65535L); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x01); |
| | | value = ASN1Long.encodeLongValue(-65536L); |
| | | assertEquals(value[0], (byte) 0xFF); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | value = ASN1Long.encodeLongValue(-2147483647L); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | assertEquals(value[3], (byte) 0x01); |
| | | value = ASN1Long.encodeLongValue(-2147483648L); |
| | | assertEquals(value[0], (byte) 0x80); |
| | | assertEquals(value[1], (byte) 0x00); |
| | | assertEquals(value[2], (byte) 0x00); |
| | | assertEquals(value[3], (byte) 0x00); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the <CODE>setValue</CODE> method that takes a long argument. |
| | | * |
| | | * @param l The long value to use for the test. |