1 package org.bouncycastle.asn1; 2 3 import java.io.IOException; 4 5 /** 6 * A BIT STRING with DER encoding - the first byte contains the count of padding bits included in the byte array's last byte. 7 */ 8 public class DERBitString 9 extends ASN1BitString 10 { 11 /** 12 * return a Bit String from the passed in object 13 * 14 * @param obj a DERBitString or an object that can be converted into one. 15 * @exception IllegalArgumentException if the object cannot be converted. 16 * @return a DERBitString instance, or null. 17 */ getInstance( Object obj)18 public static DERBitString getInstance( 19 Object obj) 20 { 21 if (obj == null || obj instanceof DERBitString) 22 { 23 return (DERBitString)obj; 24 } 25 if (obj instanceof DLBitString) 26 { 27 return new DERBitString(((DLBitString)obj).data, ((DLBitString)obj).padBits); 28 } 29 if (obj instanceof byte[]) 30 { 31 try 32 { 33 return (DERBitString)fromByteArray((byte[])obj); 34 } 35 catch (Exception e) 36 { 37 throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); 38 } 39 } 40 41 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 42 } 43 44 /** 45 * return a Bit String from a tagged object. 46 * 47 * @param obj the tagged object holding the object we want 48 * @param explicit true if the object is meant to be explicitly 49 * tagged false otherwise. 50 * @exception IllegalArgumentException if the tagged object cannot 51 * be converted. 52 * @return a DERBitString instance, or null. 53 */ getInstance( ASN1TaggedObject obj, boolean explicit)54 public static DERBitString getInstance( 55 ASN1TaggedObject obj, 56 boolean explicit) 57 { 58 ASN1Primitive o = obj.getObject(); 59 60 if (explicit || o instanceof DERBitString) 61 { 62 return getInstance(o); 63 } 64 else 65 { 66 return fromOctetString(ASN1OctetString.getInstance(o).getOctets()); 67 } 68 } 69 DERBitString(byte data, int padBits)70 protected DERBitString(byte data, int padBits) 71 { 72 super(data, padBits); 73 } 74 75 /** 76 * @param data the octets making up the bit string. 77 * @param padBits the number of extra bits at the end of the string. 78 */ DERBitString( byte[] data, int padBits)79 public DERBitString( 80 byte[] data, 81 int padBits) 82 { 83 super(data, padBits); 84 } 85 DERBitString( byte[] data)86 public DERBitString( 87 byte[] data) 88 { 89 this(data, 0); 90 } 91 DERBitString( int value)92 public DERBitString( 93 int value) 94 { 95 super(getBytes(value), getPadBits(value)); 96 } 97 DERBitString( ASN1Encodable obj)98 public DERBitString( 99 ASN1Encodable obj) 100 throws IOException 101 { 102 super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); 103 } 104 isConstructed()105 boolean isConstructed() 106 { 107 return false; 108 } 109 encodedLength()110 int encodedLength() 111 { 112 return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1; 113 } 114 encode(ASN1OutputStream out, boolean withTag)115 void encode(ASN1OutputStream out, boolean withTag) throws IOException 116 { 117 int len = data.length; 118 if (0 == len 119 || 0 == padBits 120 || (data[len - 1] == (byte)(data[len - 1] & (0xFF << padBits)))) 121 { 122 out.writeEncoded(withTag, BERTags.BIT_STRING, (byte)padBits, data); 123 } 124 else 125 { 126 byte der = (byte)(data[len - 1] & (0xFF << padBits)); 127 out.writeEncoded(withTag, BERTags.BIT_STRING, (byte)padBits, data, 0, len - 1, der); 128 } 129 } 130 toDERObject()131 ASN1Primitive toDERObject() 132 { 133 return this; 134 } 135 toDLObject()136 ASN1Primitive toDLObject() 137 { 138 return this; 139 } 140 fromOctetString(byte[] bytes)141 static DERBitString fromOctetString(byte[] bytes) 142 { 143 if (bytes.length < 1) 144 { 145 throw new IllegalArgumentException("truncated BIT STRING detected"); 146 } 147 148 int padBits = bytes[0]; 149 byte[] data = new byte[bytes.length - 1]; 150 151 if (data.length != 0) 152 { 153 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 154 } 155 156 return new DERBitString(data, padBits); 157 } 158 } 159