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.
 PublicKeyAndChallenge ::= SEQUENCE {
   spki SubjectPublicKeyInfo,
   challenge IA5STRING
 }
 SignedPublicKeyAndChallenge ::= SEQUENCE {
   publicKeyAndChallenge PublicKeyAndChallenge,
   signatureAlgorithm AlgorithmIdentifier,
   signature BIT STRING
 }
 
/** * 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.
Returns:a SignedPublicKeyAndChallenge object.
/** * 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
/** * @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
/** * @deprecated use ContentVerifierProvider method */
public boolean verify() throws NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException { return verify((String)null); }
Deprecated:use ContentVerifierProvider method
/** * @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()
/** * @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(); } }