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