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