1package org.bouncycastle.asn1.x509;
2
3import org.bouncycastle.asn1.ASN1Encodable;
4import org.bouncycastle.asn1.ASN1EncodableVector;
5import org.bouncycastle.asn1.ASN1OctetString;
6import org.bouncycastle.asn1.ASN1Sequence;
7import org.bouncycastle.asn1.ASN1TaggedObject;
8import org.bouncycastle.asn1.DERInteger;
9import org.bouncycastle.asn1.DERObject;
10import org.bouncycastle.asn1.DEROctetString;
11import org.bouncycastle.asn1.DERSequence;
12import org.bouncycastle.asn1.DERTaggedObject;
13import org.bouncycastle.crypto.Digest;
14import org.bouncycastle.crypto.digests.SHA1Digest;
15
16import java.math.BigInteger;
17import java.util.Enumeration;
18
19/**
20 * The AuthorityKeyIdentifier object.
21 * <pre>
22 * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
23 *
24 *   AuthorityKeyIdentifier ::= SEQUENCE {
25 *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
26 *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
27 *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
28 *
29 *   KeyIdentifier ::= OCTET STRING
30 * </pre>
31 *
32 */
33public class AuthorityKeyIdentifier
34    extends ASN1Encodable
35{
36    ASN1OctetString keyidentifier=null;
37    GeneralNames certissuer=null;
38    DERInteger certserno=null;
39
40    public static AuthorityKeyIdentifier getInstance(
41        ASN1TaggedObject obj,
42        boolean          explicit)
43    {
44        return getInstance(ASN1Sequence.getInstance(obj, explicit));
45    }
46
47    public static AuthorityKeyIdentifier getInstance(
48        Object  obj)
49    {
50        if (obj instanceof AuthorityKeyIdentifier)
51        {
52            return (AuthorityKeyIdentifier)obj;
53        }
54        if (obj instanceof ASN1Sequence)
55        {
56            return new AuthorityKeyIdentifier((ASN1Sequence)obj);
57        }
58        if (obj instanceof X509Extension)
59        {
60            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
61        }
62
63        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
64    }
65
66    public AuthorityKeyIdentifier(
67        ASN1Sequence   seq)
68    {
69        Enumeration     e = seq.getObjects();
70
71        while (e.hasMoreElements())
72        {
73            ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
74
75            switch (o.getTagNo())
76            {
77            case 0:
78                this.keyidentifier = ASN1OctetString.getInstance(o, false);
79                break;
80            case 1:
81                this.certissuer = GeneralNames.getInstance(o, false);
82                break;
83            case 2:
84                this.certserno = DERInteger.getInstance(o, false);
85                break;
86            default:
87                throw new IllegalArgumentException("illegal tag");
88            }
89        }
90    }
91
92    /**
93     *
94     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
95     * from SubjectPublicKeyInfo as defined in RFC2459.
96     *
97     * Example of making a AuthorityKeyIdentifier:
98     * <pre>
99     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
100     *       publicKey.getEncoded()).readObject());
101     *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
102     * </pre>
103     *
104     **/
105    public AuthorityKeyIdentifier(
106        SubjectPublicKeyInfo    spki)
107    {
108        Digest  digest = new SHA1Digest();
109        byte[]  resBuf = new byte[digest.getDigestSize()];
110
111        byte[] bytes = spki.getPublicKeyData().getBytes();
112        digest.update(bytes, 0, bytes.length);
113        digest.doFinal(resBuf, 0);
114        this.keyidentifier = new DEROctetString(resBuf);
115    }
116
117    /**
118     * create an AuthorityKeyIdentifier with the GeneralNames tag and
119     * the serial number provided as well.
120     */
121    public AuthorityKeyIdentifier(
122        SubjectPublicKeyInfo    spki,
123        GeneralNames            name,
124        BigInteger              serialNumber)
125    {
126        Digest  digest = new SHA1Digest();
127        byte[]  resBuf = new byte[digest.getDigestSize()];
128
129        byte[] bytes = spki.getPublicKeyData().getBytes();
130        digest.update(bytes, 0, bytes.length);
131        digest.doFinal(resBuf, 0);
132
133        this.keyidentifier = new DEROctetString(resBuf);
134        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
135        this.certserno = new DERInteger(serialNumber);
136    }
137
138    /**
139     * create an AuthorityKeyIdentifier with the GeneralNames tag and
140     * the serial number provided.
141     */
142    public AuthorityKeyIdentifier(
143        GeneralNames            name,
144        BigInteger              serialNumber)
145    {
146        this.keyidentifier = null;
147        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
148        this.certserno = new DERInteger(serialNumber);
149    }
150
151    /**
152      * create an AuthorityKeyIdentifier with a precomupted key identifier
153      */
154     public AuthorityKeyIdentifier(
155         byte[]                  keyIdentifier)
156     {
157         this.keyidentifier = new DEROctetString(keyIdentifier);
158         this.certissuer = null;
159         this.certserno = null;
160     }
161
162    /**
163     * create an AuthorityKeyIdentifier with a precomupted key identifier
164     * and the GeneralNames tag and the serial number provided as well.
165     */
166    public AuthorityKeyIdentifier(
167        byte[]                  keyIdentifier,
168        GeneralNames            name,
169        BigInteger              serialNumber)
170    {
171        this.keyidentifier = new DEROctetString(keyIdentifier);
172        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
173        this.certserno = new DERInteger(serialNumber);
174    }
175
176    public byte[] getKeyIdentifier()
177    {
178        if (keyidentifier != null)
179        {
180            return keyidentifier.getOctets();
181        }
182
183        return null;
184    }
185
186    public GeneralNames getAuthorityCertIssuer()
187    {
188        return certissuer;
189    }
190
191    public BigInteger getAuthorityCertSerialNumber()
192    {
193        if (certserno != null)
194        {
195            return certserno.getValue();
196        }
197
198        return null;
199    }
200
201    /**
202     * Produce an object suitable for an ASN1OutputStream.
203     */
204    public DERObject toASN1Object()
205    {
206        ASN1EncodableVector  v = new ASN1EncodableVector();
207
208        if (keyidentifier != null)
209        {
210            v.add(new DERTaggedObject(false, 0, keyidentifier));
211        }
212
213        if (certissuer != null)
214        {
215            v.add(new DERTaggedObject(false, 1, certissuer));
216        }
217
218        if (certserno != null)
219        {
220            v.add(new DERTaggedObject(false, 2, certserno));
221        }
222
223
224        return new DERSequence(v);
225    }
226
227    public String toString()
228    {
229        return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
230    }
231}
232