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