1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 package com.android.org.bouncycastle.jce.netscape;
3 
4 import java.io.ByteArrayInputStream;
5 import java.io.ByteArrayOutputStream;
6 import java.io.IOException;
7 import java.security.InvalidKeyException;
8 import java.security.KeyFactory;
9 import java.security.NoSuchAlgorithmException;
10 import java.security.NoSuchProviderException;
11 import java.security.PrivateKey;
12 import java.security.PublicKey;
13 import java.security.SecureRandom;
14 import java.security.Signature;
15 import java.security.SignatureException;
16 import java.security.spec.InvalidKeySpecException;
17 import java.security.spec.X509EncodedKeySpec;
18 
19 import com.android.org.bouncycastle.asn1.ASN1EncodableVector;
20 import com.android.org.bouncycastle.asn1.ASN1Encoding;
21 import com.android.org.bouncycastle.asn1.ASN1InputStream;
22 import com.android.org.bouncycastle.asn1.ASN1Object;
23 import com.android.org.bouncycastle.asn1.ASN1Primitive;
24 import com.android.org.bouncycastle.asn1.ASN1Sequence;
25 import com.android.org.bouncycastle.asn1.DERBitString;
26 import com.android.org.bouncycastle.asn1.DERIA5String;
27 import com.android.org.bouncycastle.asn1.DERSequence;
28 import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
29 import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
30 
31 /**
32  *
33  *
34  * Handles NetScape certificate request (KEYGEN), these are constructed as:
35  * <pre>
36  *   SignedPublicKeyAndChallenge ::= SEQUENCE {
37  *     publicKeyAndChallenge    PublicKeyAndChallenge,
38  *     signatureAlgorithm       AlgorithmIdentifier,
39  *     signature                BIT STRING
40  *   }
41  * </pre>
42  *
43  * PublicKey's encoded-format has to be X.509.
44  * @hide This class is not part of the Android public SDK API
45  *
46  **/
47 public class NetscapeCertRequest
48     extends ASN1Object
49 {
50     AlgorithmIdentifier    sigAlg;
51     AlgorithmIdentifier    keyAlg;
52     byte        sigBits [];
53     String challenge;
54     DERBitString content;
55     PublicKey pubkey ;
56 
getReq( byte[] r)57     private static ASN1Sequence getReq(
58         byte[]  r)
59         throws IOException
60     {
61         ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(r));
62 
63         return ASN1Sequence.getInstance(aIn.readObject());
64     }
65 
NetscapeCertRequest( byte[] req)66     public NetscapeCertRequest(
67         byte[]  req)
68         throws IOException
69     {
70         this(getReq(req));
71     }
72 
NetscapeCertRequest(ASN1Sequence spkac)73     public NetscapeCertRequest (ASN1Sequence spkac)
74     {
75         try
76         {
77 
78             //
79             // SignedPublicKeyAndChallenge ::= SEQUENCE {
80             //    publicKeyAndChallenge    PublicKeyAndChallenge,
81             //    signatureAlgorithm    AlgorithmIdentifier,
82             //    signature        BIT STRING
83             // }
84             //
85             if (spkac.size() != 3)
86             {
87                 throw new IllegalArgumentException("invalid SPKAC (size):"
88                         + spkac.size());
89             }
90 
91             sigAlg = AlgorithmIdentifier.getInstance(spkac.getObjectAt(1));
92             sigBits = ((DERBitString)spkac.getObjectAt(2)).getOctets();
93 
94             //
95             // PublicKeyAndChallenge ::= SEQUENCE {
96             //    spki            SubjectPublicKeyInfo,
97             //    challenge        IA5STRING
98             // }
99             //
100             ASN1Sequence pkac = (ASN1Sequence)spkac.getObjectAt(0);
101 
102             if (pkac.size() != 2)
103             {
104                 throw new IllegalArgumentException("invalid PKAC (len): "
105                         + pkac.size());
106             }
107 
108             challenge = ((DERIA5String)pkac.getObjectAt(1)).getString();
109 
110             //this could be dangerous, as ASN.1 decoding/encoding
111             //could potentially alter the bytes
112             content = new DERBitString(pkac);
113 
114             SubjectPublicKeyInfo pubkeyinfo = SubjectPublicKeyInfo.getInstance(pkac.getObjectAt(0));
115 
116             X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(
117                     pubkeyinfo).getBytes());
118 
119             keyAlg = pubkeyinfo.getAlgorithm();
120             pubkey = KeyFactory.getInstance(keyAlg.getAlgorithm().getId(), "BC")
121                     .generatePublic(xspec);
122 
123         }
124         catch (Exception e)
125         {
126             throw new IllegalArgumentException(e.toString());
127         }
128     }
129 
NetscapeCertRequest( String challenge, AlgorithmIdentifier signing_alg, PublicKey pub_key)130     public NetscapeCertRequest(
131         String challenge,
132         AlgorithmIdentifier signing_alg,
133         PublicKey pub_key) throws NoSuchAlgorithmException,
134             InvalidKeySpecException, NoSuchProviderException
135     {
136 
137         this.challenge = challenge;
138         sigAlg = signing_alg;
139         pubkey = pub_key;
140 
141         ASN1EncodableVector content_der = new ASN1EncodableVector();
142         content_der.add(getKeySpec());
143         //content_der.add(new SubjectPublicKeyInfo(sigAlg, new RSAPublicKeyStructure(pubkey.getModulus(), pubkey.getPublicExponent()).getDERObject()));
144         content_der.add(new DERIA5String(challenge));
145 
146         try
147         {
148             content = new DERBitString(new DERSequence(content_der));
149         }
150         catch (IOException e)
151         {
152             throw new InvalidKeySpecException("exception encoding key: " + e.toString());
153         }
154     }
155 
getChallenge()156     public String getChallenge()
157     {
158         return challenge;
159     }
160 
setChallenge(String value)161     public void setChallenge(String value)
162     {
163         challenge = value;
164     }
165 
getSigningAlgorithm()166     public AlgorithmIdentifier getSigningAlgorithm()
167     {
168         return sigAlg;
169     }
170 
setSigningAlgorithm(AlgorithmIdentifier value)171     public void setSigningAlgorithm(AlgorithmIdentifier value)
172     {
173         sigAlg = value;
174     }
175 
getKeyAlgorithm()176     public AlgorithmIdentifier getKeyAlgorithm()
177     {
178         return keyAlg;
179     }
180 
setKeyAlgorithm(AlgorithmIdentifier value)181     public void setKeyAlgorithm(AlgorithmIdentifier value)
182     {
183         keyAlg = value;
184     }
185 
getPublicKey()186     public PublicKey getPublicKey()
187     {
188         return pubkey;
189     }
190 
setPublicKey(PublicKey value)191     public void setPublicKey(PublicKey value)
192     {
193         pubkey = value;
194     }
195 
verify(String challenge)196     public boolean verify(String challenge) throws NoSuchAlgorithmException,
197             InvalidKeyException, SignatureException, NoSuchProviderException
198     {
199         if (!challenge.equals(this.challenge))
200         {
201             return false;
202         }
203 
204         //
205         // Verify the signature .. shows the response was generated
206         // by someone who knew the associated private key
207         //
208         Signature sig = Signature.getInstance(sigAlg.getAlgorithm().getId(),
209                 "BC");
210         sig.initVerify(pubkey);
211         sig.update(content.getBytes());
212 
213         return sig.verify(sigBits);
214     }
215 
sign(PrivateKey priv_key)216     public void sign(PrivateKey priv_key) throws NoSuchAlgorithmException,
217             InvalidKeyException, SignatureException, NoSuchProviderException,
218             InvalidKeySpecException
219     {
220         sign(priv_key, null);
221     }
222 
sign(PrivateKey priv_key, SecureRandom rand)223     public void sign(PrivateKey priv_key, SecureRandom rand)
224             throws NoSuchAlgorithmException, InvalidKeyException,
225             SignatureException, NoSuchProviderException,
226             InvalidKeySpecException
227     {
228         Signature sig = Signature.getInstance(sigAlg.getAlgorithm().getId(),
229                 "BC");
230 
231         if (rand != null)
232         {
233             sig.initSign(priv_key, rand);
234         }
235         else
236         {
237             sig.initSign(priv_key);
238         }
239 
240         ASN1EncodableVector pkac = new ASN1EncodableVector();
241 
242         pkac.add(getKeySpec());
243         pkac.add(new DERIA5String(challenge));
244 
245         try
246         {
247             sig.update(new DERSequence(pkac).getEncoded(ASN1Encoding.DER));
248         }
249         catch (IOException ioe)
250         {
251             throw new SignatureException(ioe.getMessage());
252         }
253 
254         sigBits = sig.sign();
255     }
256 
getKeySpec()257     private ASN1Primitive getKeySpec() throws NoSuchAlgorithmException,
258             InvalidKeySpecException, NoSuchProviderException
259     {
260         ByteArrayOutputStream baos = new ByteArrayOutputStream();
261 
262         ASN1Primitive obj = null;
263         try
264         {
265 
266             baos.write(pubkey.getEncoded());
267             baos.close();
268 
269             ASN1InputStream derin = new ASN1InputStream(
270                     new ByteArrayInputStream(baos.toByteArray()));
271 
272             obj = derin.readObject();
273         }
274         catch (IOException ioe)
275         {
276             throw new InvalidKeySpecException(ioe.getMessage());
277         }
278         return obj;
279     }
280 
toASN1Primitive()281     public ASN1Primitive toASN1Primitive()
282     {
283         ASN1EncodableVector spkac = new ASN1EncodableVector();
284         ASN1EncodableVector pkac = new ASN1EncodableVector();
285 
286         try
287         {
288             pkac.add(getKeySpec());
289         }
290         catch (Exception e)
291         {
292             //ignore
293         }
294 
295         pkac.add(new DERIA5String(challenge));
296 
297         spkac.add(new DERSequence(pkac));
298         spkac.add(sigAlg);
299         spkac.add(new DERBitString(sigBits));
300 
301         return new DERSequence(spkac);
302     }
303 }
304