1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.asn1.ber.primitives ;
18
19
20 /***
21 * Utilities for decoding and encoding primitive constructs.
22 *
23 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
24 * @version $Rev: 157644 $
25 */
26 public class PrimitiveUtils
27 {
28 private static final int ONE_BYTE_MAX = (1<<7)-1;
29 private static final int ONE_BYTE_MIN = -(1<<7);
30 private static final int TWO_BYTE_MAX = (1<<15)-1;
31 private static final int TWO_BYTE_MIN = -(1<<15);
32 private static final int THREE_BYTE_MAX = (1<<23)-1;
33 private static final int THREE_BYTE_MIN = -(1<<23);
34 private static final int FOUR_BYTE_MAX = Integer.MAX_VALUE;
35 private static final int FOUR_BYTE_MIN = Integer.MIN_VALUE;
36 private static final byte[] TRUE_ARRAY = new byte[] { ( byte ) 0xFF };
37 private static final byte[] FALSE_ARRAY = new byte[] { ( byte ) 0x00 };
38
39
40
41 public static boolean berDecodeBoolean( byte value )
42 {
43 if ( value == 0 )
44 {
45 return false ;
46 }
47
48 return true ;
49 }
50
51
52 /***
53 * Encodes a boolean as a byte following the stricter CER and DER
54 * requirements where true must be a value of 0xFF and false is 0x00.
55 *
56 * @param bool the boolean to encode
57 * @return 0xFF if bool is true, 0x00 if the bool is false
58 */
59 public static byte encodeBooleanAsByte( boolean bool )
60 {
61 return bool ? ( byte ) 0xFF : ( byte ) 0;
62 }
63
64
65 /***
66 * Encodes a boolean as a byte[] with one byte following the stricter CER
67 * and DER requirements where true must be a value of 0xFF and false is
68 * 0x00. Although there is alway one byte returned we return a byte [] as
69 * a convenience since most of the time a byte[] is expected after encoding
70 * a primitive type.
71 *
72 * @param bool the boolean to encode
73 * @return a byte array of length 1 where the single byte is 0xFF if bool
74 * is true, 0x00 if the bool is false
75 */
76 public static byte[] encodeBoolean( boolean bool )
77 {
78 return bool ? TRUE_ARRAY : FALSE_ARRAY ;
79 }
80
81
82 public static boolean derCerDecodeBoolean( byte value )
83 {
84 if ( value == 0 )
85 {
86 return false ;
87 }
88 else if ( value == 0xFF )
89 {
90 return true ;
91 }
92 else
93 {
94 String msg = "For DER and CER encodings of boolean values the only "
95 + " permisable values are 0x00 for false and 0xFF for true."
96 + " A value of " + value + " is not allowed!" ;
97 throw new IllegalArgumentException( msg ) ;
98 }
99 }
100
101
102 public static byte[] encodeInt( int source )
103 {
104 byte[] encoded = null;
105
106 if ( source >= ONE_BYTE_MIN && source <= ONE_BYTE_MAX )
107 {
108 encoded = new byte[1];
109 encoded[0] = ( byte ) source;
110 }
111 else if ( source >= TWO_BYTE_MIN && source <= TWO_BYTE_MAX )
112 {
113 encoded = new byte[2];
114 encoded[1] = ( byte ) source;
115 encoded[0] = ( byte ) ( source >> 8 );
116 }
117 else if ( source >= THREE_BYTE_MIN && source <= THREE_BYTE_MAX )
118 {
119 encoded = new byte[3];
120 encoded[2] = ( byte ) source;
121 encoded[1] = ( byte ) ( source >> 8 );
122 encoded[0] = ( byte ) ( source >> 16 );
123 }
124 else if ( source >= FOUR_BYTE_MIN && source <= FOUR_BYTE_MAX )
125 {
126 encoded = new byte[4];
127 encoded[3] = ( byte ) source;
128 encoded[2] = ( byte ) ( source >> 8 );
129 encoded[1] = ( byte ) ( source >> 16 );
130 encoded[0] = ( byte ) ( source >> 24 );
131 }
132
133 return encoded;
134 }
135
136
137 /***
138 * Decodes a BER encoded ASN.1 INTEGER into a Java primitive int.
139 *
140 * @param bites the bytes containing the encoded ASN.1 INTEGER
141 * @param offset the offset from zero where the bytes begin
142 * @param length the length of the bytes to read from the offset
143 * @return the decoded primitive int or zero if the length is 0
144 * @throws IllegalArgumentException if the length is not within
145 * range [0-4]
146 * @throws IndexOutOfBoundsException if offset is less than 0 or
147 * it is greater than bites.length - length
148 */
149 public static int decodeInt( byte[] bites, int offset, int length )
150 {
151 int value = 0 ;
152
153 if ( length == 0 )
154 {
155 return 0 ;
156 }
157
158 switch( length )
159 {
160 case( 1 ):
161 if ( ( bites[offset+0] & 0x80 ) == 0x80 )
162 {
163 value |= bites[offset+0] | 0xffffff00 ;
164 }
165 else
166 {
167 value |= bites[offset+0] & 0x000000ff ;
168 }
169
170 break ;
171 case( 2 ):
172 if ( ( bites[offset+0] & 0x80 ) == 0x80 )
173 {
174 value |= ( bites[offset+0] << 8 ) | 0xffff0000 ;
175 }
176 else
177 {
178 value |= ( bites[offset+0] << 8 ) ;
179 }
180
181 value |= ( bites[offset+1] & 0x000000ff );
182 break ;
183 case( 3 ):
184 if ( ( bites[offset+0] & 0x80 ) == 0x80 )
185 {
186 value |= ( bites[offset+0] << 16 ) | 0xff000000 ;
187 }
188 else
189 {
190 value |= ( bites[offset+0] << 16 ) ;
191 }
192
193 value |= ( bites[offset+1] << 8 ) & 0x0000ff00;
194 value |= bites[offset+2] & 0x000000ff;
195 break ;
196 case( 4 ):
197 value |= ( bites[offset+0] << 24 ) & 0xff000000;
198 value |= ( bites[offset+1] << 16 ) & 0x00ff0000;
199 value |= ( bites[offset+2] << 8 ) & 0x0000ff00;
200 value |= bites[offset+3] & 0x000000ff;
201 break ;
202 default:
203 throw new IllegalArgumentException(
204 "Length should be in range [0-4]" ) ;
205 }
206
207 return value ;
208 }
209 }