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