001package org.apache.commons.ssl.org.bouncycastle.asn1; 002 003import java.io.ByteArrayInputStream; 004import java.io.IOException; 005import java.io.InputStream; 006 007import org.bouncycastle.util.Arrays; 008import org.bouncycastle.util.encoders.Hex; 009 010/** 011 * Abstract base for the ASN.1 OCTET STRING data type 012 * <p> 013 * This supports BER, and DER forms of the data. 014 * </p><p> 015 * DER form is always primitive single OCTET STRING, while 016 * BER support includes the constructed forms. 017 * </p> 018 * <hr> 019 * <p><b>X.690</b></p> 020 * <p><b>8: Basic encoding rules</b></p> 021 * <p><b>8.7 Encoding of an octetstring value</b></p> 022 * <p> 023 * <b>8.7.1</b> The encoding of an octetstring value shall be 024 * either primitive or constructed at the option of the sender. 025 * <blockquote> 026 * NOTE — Where it is necessary to transfer part of an octet string 027 * before the entire OCTET STRING is available, the constructed encoding 028 * is used. 029 * </blockquote> 030 * <p> 031 * <b>8.7.2</b> The primitive encoding contains zero, 032 * one or more contents octets equal in value to the octets 033 * in the data value, in the order they appear in the data value, 034 * and with the most significant bit of an octet of the data value 035 * aligned with the most significant bit of an octet of the contents octets. 036 * </p> 037 * <p> 038 * <b>8.7.3</b> The contents octets for the constructed encoding shall consist 039 * of zero, one, or more encodings. 040 * <blockquote> 041 * NOTE — Each such encoding includes identifier, length, and contents octets, 042 * and may include end-of-contents octets if it is constructed. 043 * </blockquote> 044 * </p> 045 * <p> 046 * <b>8.7.3.1</b> To encode an octetstring value in this way, 047 * it is segmented. Each segment shall consist of a series of 048 * consecutive octets of the value. There shall be no significance 049 * placed on the segment boundaries. 050 * <blockquote> 051 * NOTE — A segment may be of size zero, i.e. contain no octets. 052 * </blockquote> 053 * </p> 054 * <p> 055 * <b>8.7.3.2</b> Each encoding in the contents octets shall represent 056 * a segment of the overall octetstring, the encoding arising from 057 * a recursive application of this subclause. 058 * In this recursive application, each segment is treated as if it were 059 * a octetstring value. The encodings of the segments shall appear in the contents 060 * octets in the order in which their octets appear in the overall value. 061 * <blockquote> 062 * NOTE 1 — As a consequence of this recursion, 063 * each encoding in the contents octets may itself 064 * be primitive or constructed. 065 * However, such encodings will usually be primitive. 066 * </p><p> 067 * NOTE 2 — In particular, the tags in the contents octets are always universal class, number 4. 068 * </blockquote> 069 * </p> 070 * <p><b>9: Canonical encoding rules</b></p> 071 * <p><b>9.1 Length forms</b></p> 072 * <p> 073 * If the encoding is constructed, it shall employ the indefinite length form. 074 * If the encoding is primitive, it shall include the fewest length octets necessary. 075 * [Contrast with 8.1.3.2 b).] 076 * </p> 077 * <p><b>9.2 String encoding forms</b></p> 078 * <p> 079 * BIT STRING, OCTET STRING,and restricted character string 080 * values shall be encoded with a primitive encoding if they would 081 * require no more than 1000 contents octets, and as a constructed 082 * encoding otherwise. The string fragments contained in 083 * the constructed encoding shall be encoded with a primitive encoding. 084 * The encoding of each fragment, except possibly 085 * the last, shall have 1000 contents octets. (Contrast with 8.21.6.) 086 * </p> 087 * <b>10: Distinguished encoding rules</b> 088 * </p><p> 089 * <b>10.1 Length forms</b> 090 * The definite form of length encoding shall be used, 091 * encoded in the minimum number of octets. 092 * [Contrast with 8.1.3.2 b).] 093 * </p><p> 094 * <b>10.2 String encoding forms</b> 095 * For BIT STRING, OCTET STRING and restricted character string types, 096 * the constructed form of encoding shall not be used. 097 * (Contrast with 8.21.6.) 098 * </p> 099 */ 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}