DERBitString.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.asn1;
2
3import java.io.ByteArrayOutputStream;
4import java.io.EOFException;
5import java.io.IOException;
6import java.io.InputStream;
7
8import org.bouncycastle.util.Arrays;
9import org.bouncycastle.util.io.Streams;
10
11public class DERBitString
12    extends ASN1Primitive
13    implements ASN1String
14{
15    private static final char[]  table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
16
17    protected byte[]      data;
18    protected int         padBits;
19
20    /**
21     * return the correct number of pad bits for a bit string defined in
22     * a 32 bit constant
23     */
24    static protected int getPadBits(
25        int bitString)
26    {
27        int val = 0;
28        for (int i = 3; i >= 0; i--)
29        {
30            //
31            // this may look a little odd, but if it isn't done like this pre jdk1.2
32            // JVM's break!
33            //
34            if (i != 0)
35            {
36                if ((bitString >> (i * 8)) != 0)
37                {
38                    val = (bitString >> (i * 8)) & 0xFF;
39                    break;
40                }
41            }
42            else
43            {
44                if (bitString != 0)
45                {
46                    val = bitString & 0xFF;
47                    break;
48                }
49            }
50        }
51
52        if (val == 0)
53        {
54            return 7;
55        }
56
57
58        int bits = 1;
59
60        while (((val <<= 1) & 0xFF) != 0)
61        {
62            bits++;
63        }
64
65        return 8 - bits;
66    }
67
68    /**
69     * return the correct number of bytes for a bit string defined in
70     * a 32 bit constant
71     */
72    static protected byte[] getBytes(int bitString)
73    {
74        int bytes = 4;
75        for (int i = 3; i >= 1; i--)
76        {
77            if ((bitString & (0xFF << (i * 8))) != 0)
78            {
79                break;
80            }
81            bytes--;
82        }
83
84        byte[] result = new byte[bytes];
85        for (int i = 0; i < bytes; i++)
86        {
87            result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
88        }
89
90        return result;
91    }
92
93    /**
94     * return a Bit String from the passed in object
95     *
96     * @exception IllegalArgumentException if the object cannot be converted.
97     */
98    public static DERBitString getInstance(
99        Object  obj)
100    {
101        if (obj == null || obj instanceof DERBitString)
102        {
103            return (DERBitString)obj;
104        }
105
106        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
107    }
108
109    /**
110     * return a Bit String from a tagged object.
111     *
112     * @param obj the tagged object holding the object we want
113     * @param explicit true if the object is meant to be explicitly
114     *              tagged false otherwise.
115     * @exception IllegalArgumentException if the tagged object cannot
116     *               be converted.
117     */
118    public static DERBitString getInstance(
119        ASN1TaggedObject obj,
120        boolean          explicit)
121    {
122        ASN1Primitive o = obj.getObject();
123
124        if (explicit || o instanceof DERBitString)
125        {
126            return getInstance(o);
127        }
128        else
129        {
130            return fromOctetString(((ASN1OctetString)o).getOctets());
131        }
132    }
133
134    protected DERBitString(
135        byte    data,
136        int     padBits)
137    {
138        this.data = new byte[1];
139        this.data[0] = data;
140        this.padBits = padBits;
141    }
142
143    /**
144     * @param data the octets making up the bit string.
145     * @param padBits the number of extra bits at the end of the string.
146     */
147    public DERBitString(
148        byte[]  data,
149        int     padBits)
150    {
151        this.data = data;
152        this.padBits = padBits;
153    }
154
155    public DERBitString(
156        byte[]  data)
157    {
158        this(data, 0);
159    }
160
161    public DERBitString(
162        ASN1Encodable  obj)
163    {
164        try
165        {
166            this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
167            this.padBits = 0;
168        }
169        catch (IOException e)
170        {
171            throw new IllegalArgumentException("Error processing object : " + e.toString());
172        }
173    }
174
175    public byte[] getBytes()
176    {
177        return data;
178    }
179
180    public int getPadBits()
181    {
182        return padBits;
183    }
184
185
186    /**
187     * @return the value of the bit string as an int (truncating if necessary)
188     */
189    public int intValue()
190    {
191        int value = 0;
192
193        for (int i = 0; i != data.length && i != 4; i++)
194        {
195            value |= (data[i] & 0xff) << (8 * i);
196        }
197
198        return value;
199    }
200
201    boolean isConstructed()
202    {
203        return false;
204    }
205
206    int encodedLength()
207    {
208        return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
209    }
210
211    void encode(
212        ASN1OutputStream  out)
213        throws IOException
214    {
215        byte[]  bytes = new byte[getBytes().length + 1];
216
217        bytes[0] = (byte)getPadBits();
218        System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
219
220        out.writeEncoded(BERTags.BIT_STRING, bytes);
221    }
222
223    public int hashCode()
224    {
225        return padBits ^ Arrays.hashCode(data);
226    }
227
228    protected boolean asn1Equals(
229        ASN1Primitive  o)
230    {
231        if (!(o instanceof DERBitString))
232        {
233            return false;
234        }
235
236        DERBitString other = (DERBitString)o;
237
238        return this.padBits == other.padBits
239            && Arrays.areEqual(this.data, other.data);
240    }
241
242    public String getString()
243    {
244        StringBuffer          buf = new StringBuffer("#");
245        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
246        ASN1OutputStream      aOut = new ASN1OutputStream(bOut);
247
248        try
249        {
250            aOut.writeObject(this);
251        }
252        catch (IOException e)
253        {
254           throw new RuntimeException("internal error encoding BitString");
255        }
256
257        byte[]    string = bOut.toByteArray();
258
259        for (int i = 0; i != string.length; i++)
260        {
261            buf.append(table[(string[i] >>> 4) & 0xf]);
262            buf.append(table[string[i] & 0xf]);
263        }
264
265        return buf.toString();
266    }
267
268    public String toString()
269    {
270        return getString();
271    }
272
273    static DERBitString fromOctetString(byte[] bytes)
274    {
275        if (bytes.length < 1)
276        {
277            throw new IllegalArgumentException("truncated BIT STRING detected");
278        }
279
280        int padBits = bytes[0];
281        byte[] data = new byte[bytes.length - 1];
282
283        if (data.length != 0)
284        {
285            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
286        }
287
288        return new DERBitString(data, padBits);
289    }
290
291    static DERBitString fromInputStream(int length, InputStream stream)
292        throws IOException
293    {
294        if (length < 1)
295        {
296            throw new IllegalArgumentException("truncated BIT STRING detected");
297        }
298
299        int padBits = stream.read();
300        byte[] data = new byte[length - 1];
301
302        if (data.length != 0)
303        {
304            if (Streams.readFully(stream, data) != data.length)
305            {
306                throw new EOFException("EOF encountered in middle of BIT STRING");
307            }
308        }
309
310        return new DERBitString(data, padBits);
311    }
312}
313