1package org.bouncycastle.asn1; 2 3import java.io.ByteArrayInputStream; 4import java.io.IOException; 5import java.io.InputStream; 6 7import org.bouncycastle.util.Arrays; 8import org.bouncycastle.util.encoders.Hex; 9 10/** 11 * Abstract base for the ASN.1 OCTET STRING data type 12 * <p> 13 * This supports BER, and DER forms of the data. 14 * </p><p> 15 * DER form is always primitive single OCTET STRING, while 16 * BER support includes the constructed forms. 17 * </p> 18 * <hr> 19 * <p><b>X.690</b></p> 20 * <p><b>8: Basic encoding rules</b></p> 21 * <p><b>8.7 Encoding of an octetstring value</b></p> 22 * <p> 23 * <b>8.7.1</b> The encoding of an octetstring value shall be 24 * either primitive or constructed at the option of the sender. 25 * <blockquote> 26 * NOTE — Where it is necessary to transfer part of an octet string 27 * before the entire OCTET STRING is available, the constructed encoding 28 * is used. 29 * </blockquote> 30 * <p> 31 * <b>8.7.2</b> The primitive encoding contains zero, 32 * one or more contents octets equal in value to the octets 33 * in the data value, in the order they appear in the data value, 34 * and with the most significant bit of an octet of the data value 35 * aligned with the most significant bit of an octet of the contents octets. 36 * </p> 37 * <p> 38 * <b>8.7.3</b> The contents octets for the constructed encoding shall consist 39 * of zero, one, or more encodings. 40 * <blockquote> 41 * NOTE — Each such encoding includes identifier, length, and contents octets, 42 * and may include end-of-contents octets if it is constructed. 43 * </blockquote> 44 * </p> 45 * <p> 46 * <b>8.7.3.1</b> To encode an octetstring value in this way, 47 * it is segmented. Each segment shall consist of a series of 48 * consecutive octets of the value. There shall be no significance 49 * placed on the segment boundaries. 50 * <blockquote> 51 * NOTE — A segment may be of size zero, i.e. contain no octets. 52 * </blockquote> 53 * </p> 54 * <p> 55 * <b>8.7.3.2</b> Each encoding in the contents octets shall represent 56 * a segment of the overall octetstring, the encoding arising from 57 * a recursive application of this subclause. 58 * In this recursive application, each segment is treated as if it were 59 * a octetstring value. The encodings of the segments shall appear in the contents 60 * octets in the order in which their octets appear in the overall value. 61 * <blockquote> 62 * NOTE 1 — As a consequence of this recursion, 63 * each encoding in the contents octets may itself 64 * be primitive or constructed. 65 * However, such encodings will usually be primitive. 66 * </p><p> 67 * NOTE 2 — In particular, the tags in the contents octets are always universal class, number 4. 68 * </blockquote> 69 * </p> 70 * <p><b>9: Canonical encoding rules</b></p> 71 * <p><b>9.1 Length forms</b></p> 72 * <p> 73 * If the encoding is constructed, it shall employ the indefinite length form. 74 * If the encoding is primitive, it shall include the fewest length octets necessary. 75 * [Contrast with 8.1.3.2 b).] 76 * </p> 77 * <p><b>9.2 String encoding forms</b></p> 78 * <p> 79 * BIT STRING, OCTET STRING,and restricted character string 80 * values shall be encoded with a primitive encoding if they would 81 * require no more than 1000 contents octets, and as a constructed 82 * encoding otherwise. The string fragments contained in 83 * the constructed encoding shall be encoded with a primitive encoding. 84 * The encoding of each fragment, except possibly 85 * the last, shall have 1000 contents octets. (Contrast with 8.21.6.) 86 * </p> 87 * <b>10: Distinguished encoding rules</b> 88 * </p><p> 89 * <b>10.1 Length forms</b> 90 * The definite form of length encoding shall be used, 91 * encoded in the minimum number of octets. 92 * [Contrast with 8.1.3.2 b).] 93 * </p><p> 94 * <b>10.2 String encoding forms</b> 95 * For BIT STRING, OCTET STRING and restricted character string types, 96 * the constructed form of encoding shall not be used. 97 * (Contrast with 8.21.6.) 98 * </p> 99 */ 100public abstract class ASN1OctetString 101 extends ASN1Primitive 102 implements ASN1OctetStringParser 103{ 104 byte[] string; 105 106 /** 107 * return an Octet String from a tagged object. 108 * 109 * @param obj the tagged object holding the object we want. 110 * @param explicit true if the object is meant to be explicitly 111 * tagged false otherwise. 112 * @exception IllegalArgumentException if the tagged object cannot 113 * be converted. 114 */ 115 public static ASN1OctetString getInstance( 116 ASN1TaggedObject obj, 117 boolean explicit) 118 { 119 ASN1Primitive o = obj.getObject(); 120 121 if (explicit || o instanceof ASN1OctetString) 122 { 123 return getInstance(o); 124 } 125 else 126 { 127 return BEROctetString.fromSequence(ASN1Sequence.getInstance(o)); 128 } 129 } 130 131 /** 132 * return an Octet String from the given object. 133 * 134 * @param obj the object we want converted. 135 * @exception IllegalArgumentException if the object cannot be converted. 136 */ 137 public static ASN1OctetString getInstance( 138 Object obj) 139 { 140 if (obj == null || obj instanceof ASN1OctetString) 141 { 142 return (ASN1OctetString)obj; 143 } 144 else if (obj instanceof byte[]) 145 { 146 try 147 { 148 return ASN1OctetString.getInstance(ASN1Primitive.fromByteArray((byte[])obj)); 149 } 150 catch (IOException e) 151 { 152 throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage()); 153 } 154 } 155 else if (obj instanceof ASN1Encodable) 156 { 157 ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive(); 158 159 if (primitive instanceof ASN1OctetString) 160 { 161 return (ASN1OctetString)primitive; 162 } 163 } 164 165 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 166 } 167 168 /** 169 * @param string the octets making up the octet string. 170 */ 171 public ASN1OctetString( 172 byte[] string) 173 { 174 if (string == null) 175 { 176 throw new NullPointerException("string cannot be null"); 177 } 178 this.string = string; 179 } 180 181 /** 182 * Return the content of the OCTET STRING as an InputStream. 183 * 184 * @return an InputStream representing the OCTET STRING's content. 185 */ 186 public InputStream getOctetStream() 187 { 188 return new ByteArrayInputStream(string); 189 } 190 191 /** 192 * Return the parser associated with this object. 193 * 194 * @return a parser based on this OCTET STRING 195 */ 196 public ASN1OctetStringParser parser() 197 { 198 return this; 199 } 200 201 /** 202 * Return the content of the OCTET STRING as a byte array. 203 * 204 * @return the byte[] representing the OCTET STRING's content. 205 */ 206 public byte[] getOctets() 207 { 208 return string; 209 } 210 211 public int hashCode() 212 { 213 return Arrays.hashCode(this.getOctets()); 214 } 215 216 boolean asn1Equals( 217 ASN1Primitive o) 218 { 219 if (!(o instanceof ASN1OctetString)) 220 { 221 return false; 222 } 223 224 ASN1OctetString other = (ASN1OctetString)o; 225 226 return Arrays.areEqual(string, other.string); 227 } 228 229 public ASN1Primitive getLoadedObject() 230 { 231 return this.toASN1Primitive(); 232 } 233 234 ASN1Primitive toDERObject() 235 { 236 return new DEROctetString(string); 237 } 238 239 ASN1Primitive toDLObject() 240 { 241 return new DEROctetString(string); 242 } 243 244 abstract void encode(ASN1OutputStream out) 245 throws IOException; 246 247 public String toString() 248 { 249 return "#"+new String(Hex.encode(string)); 250 } 251} 252