1package org.bouncycastle.asn1; 2 3import java.io.IOException; 4 5/** 6 * A BIT STRING with DER encoding. 7 */ 8public 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 */ 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 */ 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)o).getOctets()); 67 } 68 } 69 70 protected DERBitString( 71 byte data, 72 int padBits) 73 { 74 this(toByteArray(data), padBits); 75 } 76 77 private static byte[] toByteArray(byte data) 78 { 79 byte[] rv = new byte[1]; 80 81 rv[0] = data; 82 83 return rv; 84 } 85 86 /** 87 * @param data the octets making up the bit string. 88 * @param padBits the number of extra bits at the end of the string. 89 */ 90 public DERBitString( 91 byte[] data, 92 int padBits) 93 { 94 super(data, padBits); 95 } 96 97 public DERBitString( 98 byte[] data) 99 { 100 this(data, 0); 101 } 102 103 public DERBitString( 104 int value) 105 { 106 super(getBytes(value), getPadBits(value)); 107 } 108 109 public DERBitString( 110 ASN1Encodable obj) 111 throws IOException 112 { 113 super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); 114 } 115 116 boolean isConstructed() 117 { 118 return false; 119 } 120 121 int encodedLength() 122 { 123 return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1; 124 } 125 126 void encode( 127 ASN1OutputStream out) 128 throws IOException 129 { 130 byte[] string = derForm(data, padBits); 131 byte[] bytes = new byte[string.length + 1]; 132 133 bytes[0] = (byte)getPadBits(); 134 System.arraycopy(string, 0, bytes, 1, bytes.length - 1); 135 136 out.writeEncoded(BERTags.BIT_STRING, bytes); 137 } 138 139 static DERBitString fromOctetString(byte[] bytes) 140 { 141 if (bytes.length < 1) 142 { 143 throw new IllegalArgumentException("truncated BIT STRING detected"); 144 } 145 146 int padBits = bytes[0]; 147 byte[] data = new byte[bytes.length - 1]; 148 149 if (data.length != 0) 150 { 151 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 152 } 153 154 return new DERBitString(data, padBits); 155 } 156} 157