001: package org.bouncycastle.mozilla;
002:
003: import java.io.ByteArrayInputStream;
004:
005: import java.security.PublicKey;
006: import java.security.Signature;
007: import java.security.SignatureException;
008: import java.security.NoSuchAlgorithmException;
009: import java.security.KeyFactory;
010: import java.security.InvalidKeyException;
011: import java.security.NoSuchProviderException;
012: import java.security.spec.InvalidKeySpecException;
013: import java.security.spec.X509EncodedKeySpec;
014:
015: import org.bouncycastle.asn1.ASN1Encodable;
016: import org.bouncycastle.asn1.ASN1InputStream;
017: import org.bouncycastle.asn1.DERObject;
018: import org.bouncycastle.asn1.ASN1Sequence;
019: import org.bouncycastle.asn1.DERBitString;
020: import org.bouncycastle.asn1.mozilla.PublicKeyAndChallenge;
021: import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
022: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
023:
024: /**
025: * This is designed to parse the SignedPublicKeyAndChallenge created by the
026: * KEYGEN tag included by Mozilla based browsers.
027: * <pre>
028: * PublicKeyAndChallenge ::= SEQUENCE {
029: * spki SubjectPublicKeyInfo,
030: * challenge IA5STRING
031: * }
032: *
033: * SignedPublicKeyAndChallenge ::= SEQUENCE {
034: * publicKeyAndChallenge PublicKeyAndChallenge,
035: * signatureAlgorithm AlgorithmIdentifier,
036: * signature BIT STRING
037: * }
038: * </pre>
039: */
040: public class SignedPublicKeyAndChallenge extends ASN1Encodable {
041: private static ASN1Sequence toDERSequence(byte[] bytes) {
042: try {
043: ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
044: ASN1InputStream aIn = new ASN1InputStream(bIn);
045:
046: return (ASN1Sequence) aIn.readObject();
047: } catch (Exception e) {
048: throw new IllegalArgumentException("badly encoded request");
049: }
050: }
051:
052: private ASN1Sequence spkacSeq;
053: private PublicKeyAndChallenge pkac;
054: private AlgorithmIdentifier signatureAlgorithm;
055: private DERBitString signature;
056:
057: public SignedPublicKeyAndChallenge(byte[] bytes) {
058: spkacSeq = toDERSequence(bytes);
059: pkac = PublicKeyAndChallenge.getInstance(spkacSeq
060: .getObjectAt(0));
061: signatureAlgorithm = AlgorithmIdentifier.getInstance(spkacSeq
062: .getObjectAt(1));
063: signature = (DERBitString) spkacSeq.getObjectAt(2);
064: }
065:
066: public DERObject toASN1Object() {
067: return spkacSeq;
068: }
069:
070: public PublicKeyAndChallenge getPublicKeyAndChallenge() {
071: return pkac;
072: }
073:
074: public boolean verify(String provider)
075: throws NoSuchAlgorithmException, SignatureException,
076: NoSuchProviderException, InvalidKeyException {
077: Signature sig = null;
078: sig = Signature.getInstance(signatureAlgorithm.getObjectId()
079: .getId(), provider);
080: PublicKey pubKey = this .getPublicKey(provider);
081: sig.initVerify(pubKey);
082: DERBitString pkBytes = new DERBitString(pkac);
083: sig.update(pkBytes.getBytes());
084:
085: return sig.verify(signature.getBytes());
086: }
087:
088: public PublicKey getPublicKey(String provider)
089: throws NoSuchAlgorithmException, NoSuchProviderException,
090: InvalidKeyException {
091: SubjectPublicKeyInfo subjectPKInfo = pkac
092: .getSubjectPublicKeyInfo();
093: try {
094: DERBitString bStr = new DERBitString(subjectPKInfo);
095: X509EncodedKeySpec xspec = new X509EncodedKeySpec(bStr
096: .getBytes());
097:
098: AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithmId();
099:
100: KeyFactory factory = KeyFactory.getInstance(keyAlg
101: .getObjectId().getId(), provider);
102:
103: return factory.generatePublic(xspec);
104:
105: } catch (InvalidKeySpecException e) {
106: throw new InvalidKeyException("error encoding public key");
107: }
108: }
109: }
|