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