001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import java.math.BigInteger;
004import java.util.Enumeration;
005
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
013import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
014import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
015import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
016import org.bouncycastle.crypto.Digest;
017import org.bouncycastle.crypto.digests.SHA1Digest;
018
019/**
020 * The AuthorityKeyIdentifier object.
021 * <pre>
022 * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
023 *
024 *   AuthorityKeyIdentifier ::= SEQUENCE {
025 *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
026 *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
027 *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
028 *
029 *   KeyIdentifier ::= OCTET STRING
030 * </pre>
031 *
032 */
033public class AuthorityKeyIdentifier
034    extends ASN1Object
035{
036    ASN1OctetString keyidentifier=null;
037    GeneralNames certissuer=null;
038    ASN1Integer certserno=null;
039
040    public static AuthorityKeyIdentifier getInstance(
041        ASN1TaggedObject obj,
042        boolean          explicit)
043    {
044        return getInstance(ASN1Sequence.getInstance(obj, explicit));
045    }
046
047    public static AuthorityKeyIdentifier getInstance(
048        Object  obj)
049    {
050        if (obj instanceof AuthorityKeyIdentifier)
051        {
052            return (AuthorityKeyIdentifier)obj;
053        }
054        if (obj != null)
055        {
056            return new AuthorityKeyIdentifier(ASN1Sequence.getInstance(obj));
057        }
058
059        return null;
060    }
061
062    public static AuthorityKeyIdentifier fromExtensions(Extensions extensions)
063    {
064         return AuthorityKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.authorityKeyIdentifier));
065    }
066
067    protected AuthorityKeyIdentifier(
068        ASN1Sequence   seq)
069    {
070        Enumeration     e = seq.getObjects();
071
072        while (e.hasMoreElements())
073        {
074            ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
075
076            switch (o.getTagNo())
077            {
078            case 0:
079                this.keyidentifier = ASN1OctetString.getInstance(o, false);
080                break;
081            case 1:
082                this.certissuer = GeneralNames.getInstance(o, false);
083                break;
084            case 2:
085                this.certserno = ASN1Integer.getInstance(o, false);
086                break;
087            default:
088                throw new IllegalArgumentException("illegal tag");
089            }
090        }
091    }
092
093    /**
094     *
095     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
096     * from SubjectPublicKeyInfo as defined in RFC2459.
097     *
098     * Example of making a AuthorityKeyIdentifier:
099     * <pre>
100     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
101     *       publicKey.getEncoded()).readObject());
102     *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
103     * </pre>
104     * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
105     **/
106    public AuthorityKeyIdentifier(
107        SubjectPublicKeyInfo    spki)
108    {
109        Digest  digest = new SHA1Digest();
110        byte[]  resBuf = new byte[digest.getDigestSize()];
111
112        byte[] bytes = spki.getPublicKeyData().getBytes();
113        digest.update(bytes, 0, bytes.length);
114        digest.doFinal(resBuf, 0);
115        this.keyidentifier = new DEROctetString(resBuf);
116    }
117
118    /**
119     * create an AuthorityKeyIdentifier with the GeneralNames tag and
120     * the serial number provided as well.
121     * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
122     */
123    public AuthorityKeyIdentifier(
124        SubjectPublicKeyInfo    spki,
125        GeneralNames            name,
126        BigInteger              serialNumber)
127    {
128        Digest  digest = new SHA1Digest();
129        byte[]  resBuf = new byte[digest.getDigestSize()];
130
131        byte[] bytes = spki.getPublicKeyData().getBytes();
132        digest.update(bytes, 0, bytes.length);
133        digest.doFinal(resBuf, 0);
134
135        this.keyidentifier = new DEROctetString(resBuf);
136        this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
137        this.certserno = new ASN1Integer(serialNumber);
138    }
139
140    /**
141     * create an AuthorityKeyIdentifier with the GeneralNames tag and
142     * the serial number provided.
143     */
144    public AuthorityKeyIdentifier(
145        GeneralNames            name,
146        BigInteger              serialNumber)
147    {
148        this((byte[])null, name, serialNumber);
149    }
150
151    /**
152      * create an AuthorityKeyIdentifier with a precomputed key identifier
153      */
154     public AuthorityKeyIdentifier(
155         byte[]                  keyIdentifier)
156     {
157         this(keyIdentifier, null, null);
158     }
159
160    /**
161     * create an AuthorityKeyIdentifier with a precomputed key identifier
162     * and the GeneralNames tag and the serial number provided as well.
163     */
164    public AuthorityKeyIdentifier(
165        byte[]                  keyIdentifier,
166        GeneralNames            name,
167        BigInteger              serialNumber)
168    {
169        this.keyidentifier = (keyIdentifier != null) ? new DEROctetString(keyIdentifier) : null;
170        this.certissuer = name;
171        this.certserno = (serialNumber != null) ? new ASN1Integer(serialNumber) : null;
172    }
173    
174    public byte[] getKeyIdentifier()
175    {
176        if (keyidentifier != null)
177        {
178            return keyidentifier.getOctets();
179        }
180
181        return null;
182    }
183
184    public GeneralNames getAuthorityCertIssuer()
185    {
186        return certissuer;
187    }
188    
189    public BigInteger getAuthorityCertSerialNumber()
190    {
191        if (certserno != null)
192        {
193            return certserno.getValue();
194        }
195        
196        return null;
197    }
198    
199    /**
200     * Produce an object suitable for an ASN1OutputStream.
201     */
202    public ASN1Primitive toASN1Primitive()
203    {
204        ASN1EncodableVector  v = new ASN1EncodableVector();
205
206        if (keyidentifier != null)
207        {
208            v.add(new DERTaggedObject(false, 0, keyidentifier));
209        }
210
211        if (certissuer != null)
212        {
213            v.add(new DERTaggedObject(false, 1, certissuer));
214        }
215
216        if (certserno != null)
217        {
218            v.add(new DERTaggedObject(false, 2, certserno));
219        }
220
221
222        return new DERSequence(v);
223    }
224
225    public String toString()
226    {
227        return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
228    }
229}