]> WPIA git - gigi.git/blob - src/org/cacert/gigi/crypto/SPKAC.java
Add class for parsing (and writing) SPKAC. With testcase.
[gigi.git] / src / org / cacert / gigi / crypto / SPKAC.java
1 package org.cacert.gigi.crypto;
2
3 import java.io.IOException;
4 import java.security.GeneralSecurityException;
5 import java.security.Signature;
6 import java.security.SignatureException;
7 import sun.security.util.DerInputStream;
8 import sun.security.util.DerOutputStream;
9 import sun.security.util.DerValue;
10 import sun.security.x509.AlgorithmId;
11 import sun.security.x509.X509Key;
12
13 /**
14  * This class handles a SPKAC. A SPKAC has the following structure;
15  * 
16  * <pre>
17  * PublicKeyAndChallenge ::= SEQUENCE {
18  *     spki SubjectPublicKeyInfo,
19  *     challenge IA5STRING
20  * }
21  * 
22  * SignedPublicKeyAndChallenge ::= SEQUENCE {
23  *     publicKeyAndChallenge PublicKeyAndChallenge,
24  *     signatureAlgorithm AlgorithmIdentifier,
25  *     signature BIT STRING
26  * }
27  * </pre>
28  */
29 public class SPKAC {
30
31     private X509Key pubkey;
32
33     private String challenge;
34
35     public SPKAC(byte[] data) throws IOException, GeneralSecurityException {
36         DerInputStream derIn = new DerInputStream(data);
37
38         DerValue derSPKACContent[] = derIn.getSequence(3);
39         if (derIn.available() != 0) {
40             throw new IllegalArgumentException("Additional data after SPKAC.");
41         }
42
43         AlgorithmId id = AlgorithmId.parse(derSPKACContent[1]);
44
45         derIn = derSPKACContent[0].toDerInputStream();
46
47         pubkey = (X509Key) X509Key.parse(derIn.getDerValue());
48
49         DerValue derChallenge = derIn.getDerValue();
50         if (derIn.available() != 0) {
51             throw new IllegalArgumentException("Additional data after SPKAC.");
52         }
53         if (derChallenge.length() != 0) {
54             challenge = derChallenge.getIA5String();
55         }
56
57         Signature s = Signature.getInstance(id.getName());
58         s.initVerify(pubkey);
59         s.update(derSPKACContent[0].toByteArray());
60         byte[] signature = derSPKACContent[2].getBitString();
61         if ( !s.verify(signature)) {
62             throw new SignatureException();
63         }
64
65     }
66
67     public String getChallenge() {
68         return challenge;
69     }
70
71     public X509Key getPubkey() {
72         return pubkey;
73     }
74
75     public SPKAC(X509Key pubkey, String challange) {
76         this.pubkey = pubkey;
77         challenge = challange;
78     }
79
80     public byte[] getEncoded(Signature sign) throws GeneralSecurityException, IOException {
81         DerOutputStream SPKAC = new DerOutputStream();
82         DerOutputStream SPKI = new DerOutputStream();
83
84         pubkey.encode(SPKI);
85         SPKI.putIA5String(challenge);
86
87         SPKAC.write(DerValue.tag_Sequence, SPKI);
88         byte[] toSign = SPKAC.toByteArray();
89         SPKI.close();
90
91         AlgorithmId aid = AlgorithmId.get(sign.getAlgorithm());
92         aid.encode(SPKAC);
93         sign.update(toSign);
94         SPKAC.putBitString(sign.sign());
95
96         DerOutputStream res = new DerOutputStream();
97         res.write(DerValue.tag_Sequence, SPKAC);
98         SPKAC.close();
99         byte[] result = res.toByteArray();
100         res.close();
101         return result;
102     }
103 }