--- /dev/null
+package org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import java.util.Enumeration;
+
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.asn1.*;
+
+/**
+ * <pre>
+ * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ *
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ *
+ */
+public class AuthorityKeyIdentifier
+ implements DEREncodable
+{
+ DEROctetString keyidentifier=null;
+ GeneralNames certissuer=null;
+ DERInteger certserno=null;
+
+ public AuthorityKeyIdentifier(
+ DERConstructedSequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ this.keyidentifier= (DEROctetString)o.getObject();
+ break;
+
+ case 1:
+ if (o.getObject() instanceof DERConstructedSequence)
+ {
+ this.certissuer = new GeneralNames((DERConstructedSequence)o.getObject());
+ }
+ else
+ {
+ // as it's implicitly tagged we can loose the"sequence"
+ // if there is only one object.
+ //
+ DERConstructedSequence s = new DERConstructedSequence();
+
+ s.addObject(o.getObject());
+
+ this.certissuer = new GeneralNames(s);
+ }
+ break;
+ case 2:
+ //
+ // implicit tagging again...
+ //
+ DEROctetString oct = (DEROctetString)o.getObject();
+
+ this.certserno = new DERInteger(new BigInteger(oct.getOctets()));
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ /**
+ *
+ * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC2459.
+ *
+ * Example of making a AuthorityKeyIdentifier:
+ * <pre>
+ * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((DERConstructedSequence)new DERInputStream(
+ * new ByteArrayInputStream(publicKey.getEncoded())).readObject());
+ * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+ * </pre>
+ *
+ **/
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ DERBitString derpk = new DERBitString(spki.getPublicKey());
+ byte[] bytes = derpk.getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ this.keyidentifier=new DEROctetString(resBuf);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ DERBitString derpk = new DERBitString(spki.getPublicKey());
+ byte[] bytes = derpk.getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+
+ this.keyidentifier = new DEROctetString(resBuf);
+ this.certissuer = name;
+ this.certserno = new DERInteger(serialNumber);
+ }
+
+ public byte[] getKeyIdentifier()
+ {
+ if (keyidentifier != null)
+ {
+ return keyidentifier.getOctets();
+ }
+
+ return null;
+ }
+
+ /**
+ * <pre>
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
+ public DERObject getDERObject()
+ {
+ DERConstructedSequence seq = new DERConstructedSequence();
+
+ if (keyidentifier != null)
+ {
+ seq.addObject(new DERTaggedObject(false, 0, keyidentifier));
+ }
+
+ if (certissuer != null)
+ {
+ seq.addObject(new DERTaggedObject(false, 1, certissuer));
+ }
+
+ if (certserno != null)
+ {
+ seq.addObject(new DERTaggedObject(false, 2, certserno));
+ }
+
+
+ return seq;
+ }
+
+ public String toString()
+ {
+ return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
+ }
+}