View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
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 }