| package org.bouncycastle.mozilla; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.security.InvalidKeyException; |
| import java.security.KeyFactory; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.PublicKey; |
| import java.security.Signature; |
| import java.security.SignatureException; |
| import java.security.spec.X509EncodedKeySpec; |
| |
| import org.bouncycastle.asn1.ASN1Primitive; |
| import org.bouncycastle.asn1.DERBitString; |
| import org.bouncycastle.asn1.DEROutputStream; |
| import org.bouncycastle.asn1.mozilla.PublicKeyAndChallenge; |
| import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
| import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; |
| import org.bouncycastle.operator.ContentVerifier; |
| import org.bouncycastle.operator.ContentVerifierProvider; |
| import org.bouncycastle.operator.OperatorCreationException; |
| import org.bouncycastle.util.Encodable; |
| |
| /** |
| * This is designed to parse the SignedPublicKeyAndChallenge created by the |
| * KEYGEN tag included by Mozilla based browsers. |
| * <pre> |
| * PublicKeyAndChallenge ::= SEQUENCE { |
| * spki SubjectPublicKeyInfo, |
| * challenge IA5STRING |
| * } |
| * |
| * SignedPublicKeyAndChallenge ::= SEQUENCE { |
| * publicKeyAndChallenge PublicKeyAndChallenge, |
| * signatureAlgorithm AlgorithmIdentifier, |
| * signature BIT STRING |
| * } |
| * </pre> |
| */ |
| public class SignedPublicKeyAndChallenge |
| implements Encodable |
| { |
| protected final org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge spkacSeq; |
| |
| public SignedPublicKeyAndChallenge(byte[] bytes) |
| { |
| spkacSeq = org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge.getInstance(bytes); |
| } |
| |
| protected SignedPublicKeyAndChallenge(org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge struct) |
| { |
| this.spkacSeq = struct; |
| } |
| |
| /** |
| * Return the underlying ASN.1 structure for this challenge. |
| * |
| * @return a SignedPublicKeyAndChallenge object. |
| */ |
| public org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge toASN1Structure() |
| { |
| return spkacSeq; |
| } |
| |
| /** |
| * @deprecated use toASN1Structure |
| */ |
| public ASN1Primitive toASN1Primitive() |
| { |
| return spkacSeq.toASN1Primitive(); |
| } |
| |
| public PublicKeyAndChallenge getPublicKeyAndChallenge() |
| { |
| return spkacSeq.getPublicKeyAndChallenge(); |
| } |
| |
| public boolean isSignatureValid(ContentVerifierProvider verifierProvider) |
| throws OperatorCreationException, IOException |
| { |
| ContentVerifier verifier = verifierProvider.get(spkacSeq.getSignatureAlgorithm()); |
| |
| OutputStream sOut = verifier.getOutputStream(); |
| DEROutputStream dOut = new DEROutputStream(sOut); |
| |
| dOut.writeObject(spkacSeq.getPublicKeyAndChallenge()); |
| |
| sOut.close(); |
| |
| return verifier.verify(spkacSeq.getSignature().getOctets()); |
| } |
| |
| /** |
| * @deprecated use ContentVerifierProvider method |
| */ |
| public boolean verify() |
| throws NoSuchAlgorithmException, SignatureException, |
| NoSuchProviderException, InvalidKeyException |
| { |
| return verify((String)null); |
| } |
| |
| /** |
| * @deprecated use ContentVerifierProvider method |
| */ |
| public boolean verify(String provider) |
| throws NoSuchAlgorithmException, SignatureException, |
| NoSuchProviderException, InvalidKeyException |
| { |
| Signature sig = null; |
| if (provider == null) |
| { |
| sig = Signature.getInstance(spkacSeq.getSignatureAlgorithm().getAlgorithm().getId()); |
| } |
| else |
| { |
| sig = Signature.getInstance(spkacSeq.getSignatureAlgorithm().getAlgorithm().getId(), provider); |
| } |
| PublicKey pubKey = this.getPublicKey(provider); |
| sig.initVerify(pubKey); |
| try |
| { |
| sig.update(spkacSeq.getPublicKeyAndChallenge().getEncoded()); |
| |
| return sig.verify(spkacSeq.getSignature().getBytes()); |
| } |
| catch (Exception e) |
| { |
| throw new InvalidKeyException("error encoding public key"); |
| } |
| } |
| |
| public SubjectPublicKeyInfo getSubjectPublicKeyInfo() |
| { |
| return spkacSeq.getPublicKeyAndChallenge().getSubjectPublicKeyInfo(); |
| } |
| |
| public String getChallenge() |
| { |
| return spkacSeq.getPublicKeyAndChallenge().getChallenge().getString(); |
| } |
| |
| /** |
| * @deprecated use JcaSignedPublicKeyAndChallenge.getPublicKey() |
| */ |
| public PublicKey getPublicKey(String provider) |
| throws NoSuchAlgorithmException, NoSuchProviderException, |
| InvalidKeyException |
| { |
| SubjectPublicKeyInfo subjectPKInfo = spkacSeq.getPublicKeyAndChallenge().getSubjectPublicKeyInfo(); |
| try |
| { |
| DERBitString bStr = new DERBitString(subjectPKInfo); |
| X509EncodedKeySpec xspec = new X509EncodedKeySpec(bStr.getOctets()); |
| |
| |
| AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithm(); |
| |
| KeyFactory factory = |
| KeyFactory.getInstance(keyAlg.getAlgorithm().getId(),provider); |
| |
| return factory.generatePublic(xspec); |
| |
| } |
| catch (Exception e) |
| { |
| throw new InvalidKeyException("error encoding public key"); |
| } |
| } |
| |
| public byte[] getEncoded() |
| throws IOException |
| { |
| return toASN1Structure().getEncoded(); |
| } |
| } |