org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsRSAVerifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of impersonator Show documentation
Show all versions of impersonator Show documentation
Spoof TLS/JA3/JA4 and HTTP/2 fingerprints in Java
package org.bouncycastle.tls.crypto.impl.jcajce;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.Signature;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.tls.DigitallySigned;
import org.bouncycastle.tls.SignatureAlgorithm;
import org.bouncycastle.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.tls.TlsUtils;
import org.bouncycastle.tls.crypto.TlsStreamVerifier;
import org.bouncycastle.tls.crypto.TlsVerifier;
/**
* Operator supporting the verification of RSASSA-PKCS1-v1_5 signatures.
*/
public class JcaTlsRSAVerifier
implements TlsVerifier
{
private final JcaTlsCrypto crypto;
private final PublicKey publicKey;
private Signature rawVerifier = null;
public JcaTlsRSAVerifier(JcaTlsCrypto crypto, PublicKey publicKey)
{
if (null == crypto)
{
throw new NullPointerException("crypto");
}
if (null == publicKey)
{
throw new NullPointerException("publicKey");
}
this.crypto = crypto;
this.publicKey = publicKey;
}
public TlsStreamVerifier getStreamVerifier(DigitallySigned digitallySigned) throws IOException
{
SignatureAndHashAlgorithm algorithm = digitallySigned.getAlgorithm();
/*
* NOTE: The SunMSCAPI provider's "NoneWithRSA" can't produce/verify RSA signatures in the correct format for TLS 1.2
*/
if (algorithm != null
&& algorithm.getSignature() == SignatureAlgorithm.rsa
&& JcaUtils.isSunMSCAPIProviderActive()
&& isSunMSCAPIRawVerifier())
{
return crypto.createStreamVerifier(digitallySigned, publicKey);
}
return null;
}
public boolean verifyRawSignature(DigitallySigned digitallySigned, byte[] hash) throws IOException
{
SignatureAndHashAlgorithm algorithm = digitallySigned.getAlgorithm();
try
{
Signature verifier = getRawVerifier();
if (algorithm != null)
{
if (algorithm.getSignature() != SignatureAlgorithm.rsa)
{
throw new IllegalStateException("Invalid algorithm: " + algorithm);
}
/*
* RFC 5246 4.7. In RSA signing, the opaque vector contains the signature generated
* using the RSASSA-PKCS1-v1_5 signature scheme defined in [PKCS1].
*/
AlgorithmIdentifier algID = new AlgorithmIdentifier(
TlsUtils.getOIDForHashAlgorithm(algorithm.getHash()), DERNull.INSTANCE);
byte[] digestInfo = new DigestInfo(algID, hash).getEncoded();
verifier.update(digestInfo, 0, digestInfo.length);
}
else
{
/*
* RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature
* scheme that did not include a DigestInfo encoding.
*/
verifier.update(hash, 0, hash.length);
}
return verifier.verify(digitallySigned.getSignature());
}
catch (GeneralSecurityException e)
{
throw Exceptions.illegalStateException("unable to process signature: " + e.getMessage(), e);
}
}
protected Signature getRawVerifier() throws GeneralSecurityException
{
if (rawVerifier == null)
{
rawVerifier = crypto.getHelper().createSignature("NoneWithRSA");
rawVerifier.initVerify(publicKey);
}
return rawVerifier;
}
protected boolean isSunMSCAPIRawVerifier() throws IOException
{
try
{
Signature rawVerifier = getRawVerifier();
return JcaUtils.isSunMSCAPIProvider(rawVerifier.getProvider());
}
catch (GeneralSecurityException e)
{
// Assume the worst!
return true;
}
}
}