All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsRSAVerifier Maven / Gradle / Ivy

package org.bouncycastle.tls.crypto.impl.jcajce;

import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;

import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.tls.AlertDescription;
import org.bouncycastle.tls.DigitallySigned;
import org.bouncycastle.tls.SignatureAlgorithm;
import org.bouncycastle.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.tls.TlsFatalAlert;
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(final DigitallySigned signature) throws IOException
    {
        SignatureAndHashAlgorithm algorithm = signature.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())
        {
            try
            {
                Signature rawVerifier = getRawVerifier();

                if (JcaUtils.isSunMSCAPIProvider(rawVerifier.getProvider()))
                {
                    String algorithmName = JcaUtils.getJcaAlgorithmName(algorithm);

                    final Signature verifier = crypto.getHelper().createSignature(algorithmName);
                    verifier.initVerify(publicKey);

                    return new TlsStreamVerifier()
                    {
                        public OutputStream getOutputStream()
                        {
                            return new SignatureOutputStream(verifier);
                        }

                        public boolean isVerified() throws IOException
                        {
                            try
                            {
                                return verifier.verify(signature.getSignature());
                            }
                            catch (SignatureException e)
                            {
                                throw new TlsFatalAlert(AlertDescription.internal_error, e);
                            }
                        }
                    };
                }
            }
            catch (GeneralSecurityException e)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error, e);
            }
        }

        return null;
    }

    public boolean verifyRawSignature(DigitallySigned signedParams, byte[] hash) throws IOException
    {
        SignatureAndHashAlgorithm algorithm = signedParams.getAlgorithm();

        try
        {
            Signature verifier = getRawVerifier();

            if (algorithm != null)
            {
                if (algorithm.getSignature() != SignatureAlgorithm.rsa)
                {
                    throw new IllegalStateException();
                }

                /*
                 * 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(signedParams.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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy