blob: bedd2daf21c3cc6d2521a85397730b3476357a33 [file] [log] [blame]
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();
}
}