1    package org.bouncycastle.asn1.x509;
2    
3    import java.math.BigInteger;
4    
5    import java.util.Enumeration;
6    
7    import org.bouncycastle.crypto.Digest;
8    import org.bouncycastle.crypto.digests.SHA1Digest;
9    import org.bouncycastle.asn1.*;
10   
11   /**
12    * <pre>
13    * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
14    *
15    *   AuthorityKeyIdentifier ::= SEQUENCE {
16    *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
17    *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
18    *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
19    *
20    *   KeyIdentifier ::= OCTET STRING
21    * </pre>
22    *
23    */
24   public class AuthorityKeyIdentifier
25       implements DEREncodable, DERTags
26   {
27       ASN1OctetString keyidentifier=null;
28       GeneralNames certissuer=null;
29       DERInteger certserno=null;
30   
31       public static AuthorityKeyIdentifier getInstance(
32           ASN1TaggedObject obj,
33           boolean          explicit)
34       {
35           return getInstance(ASN1Sequence.getInstance(obj, explicit));
36       }
37   
38       public static AuthorityKeyIdentifier getInstance(
39           Object  obj)
40       {
41           if (obj instanceof AuthorityKeyIdentifier)
42           {
43               return (AuthorityKeyIdentifier)obj;
44           }
45           else if (obj instanceof ASN1Sequence)
46           {
47               return new AuthorityKeyIdentifier((ASN1Sequence)obj);
48           }
49   
50           throw new IllegalArgumentException("unknown object in factory");
51       }
52           
53       public AuthorityKeyIdentifier(
54           ASN1Sequence   seq)
55       {
56           Enumeration     e = seq.getObjects();
57   
58           while (e.hasMoreElements())
59           {
60               DERTaggedObject o = (DERTaggedObject)e.nextElement();
61   
62               switch (o.getTagNo())
63               {
64               case 0:
65                   this.keyidentifier = ASN1OctetString.getInstance(o, false);
66                   break;
67               case 1:
68                   this.certissuer = GeneralNames.getInstance(o, false);
69                   break;
70               case 2:
71                   this.certserno = DERInteger.getInstance(o, false);
72                   break;
73               default:
74                   throw new IllegalArgumentException("illegal tag");
75               }
76           }
77       }
78   
79       /**
80        *
81        * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
82        * from SubjectPublicKeyInfo as defined in RFC2459.
83        *
84        * Example of making a AuthorityKeyIdentifier:
85        * <pre>
86        *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((DERConstructedSequence)new DERInputStream(
87        *       new ByteArrayInputStream(publicKey.getEncoded())).readObject());
88        *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
89        * </pre>
90        *
91        **/
92       public AuthorityKeyIdentifier(
93           SubjectPublicKeyInfo    spki)
94       {
95           Digest  digest = new SHA1Digest();
96           byte[]  resBuf = new byte[digest.getDigestSize()];
97   
98           byte[] bytes = spki.getPublicKeyData().getBytes();
99           digest.update(bytes, 0, bytes.length);
100          digest.doFinal(resBuf, 0);
101          this.keyidentifier = new DEROctetString(resBuf);
102      }
103  
104      /**
105       * create an AuthorityKeyIdentifier with the GeneralNames tag and
106       * the serial number provided as well.
107       */
108      public AuthorityKeyIdentifier(
109          SubjectPublicKeyInfo    spki,
110          GeneralNames            name,
111          BigInteger              serialNumber)
112      {
113          Digest  digest = new SHA1Digest();
114          byte[]  resBuf = new byte[digest.getDigestSize()];
115  
116          byte[] bytes = spki.getPublicKeyData().getBytes();
117          digest.update(bytes, 0, bytes.length);
118          digest.doFinal(resBuf, 0);
119  
120          this.keyidentifier = new DEROctetString(resBuf);
121          this.certissuer = name;
122          this.certserno = new DERInteger(serialNumber);
123      }
124  
125      public byte[] getKeyIdentifier()
126      {
127          if (keyidentifier != null)
128          {
129              return keyidentifier.getOctets();
130          }
131  
132          return null;
133      }
134  
135       /**
136       * <pre>
137       *   AuthorityKeyIdentifier ::= SEQUENCE {
138       *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
139       *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
140       *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
141       *
142       *   KeyIdentifier ::= OCTET STRING
143       * </pre>
144       */
145      public DERObject getDERObject()
146      {
147          DERConstructedSequence  seq = new DERConstructedSequence();
148  
149          if (keyidentifier != null)
150          {
151              seq.addObject(new DERTaggedObject(false, 0, keyidentifier));
152          }
153  
154          if (certissuer != null)
155          {
156              seq.addObject(new DERTaggedObject(false, 1, certissuer));
157          }
158  
159          if (certserno != null)
160          {
161              seq.addObject(new DERTaggedObject(false, 2, certserno));
162          }
163  
164  
165          return seq;
166      }
167  
168      public String toString()
169      {
170          return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
171      }
172  }
173