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

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

Go to download

The Bouncy Castle Java APIs for the TLS, including a JSSE provider. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.

There is a newer version: 2.0.19
Show newest version
package org.bouncycastle.tls.crypto.impl.jcajce;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
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.AlertDescription;
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.TlsSigner;
import org.bouncycastle.tls.crypto.TlsStreamSigner;

/**
 * Operator supporting the generation of RSASSA-PKCS1-v1_5 signatures.
 */
public class JcaTlsRSASigner
    implements TlsSigner
{
    private final JcaTlsCrypto crypto;
    private final PrivateKey privateKey;
    private final PublicKey publicKey;

    private Signature rawSigner = null;

    public JcaTlsRSASigner(JcaTlsCrypto crypto, PrivateKey privateKey, PublicKey publicKey)
    {
        if (null == crypto)
        {
            throw new NullPointerException("crypto");
        }
        if (null == privateKey)
        {
            throw new NullPointerException("privateKey");
        }

        this.crypto = crypto;
        this.privateKey = privateKey;
        this.publicKey = publicKey;
    }

    public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm, byte[] hash) throws IOException
    {
        try
        {
            Signature signer = getRawSigner();

            byte[] input;
            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);
                input = new DigestInfo(algID, hash).getEncoded();
            }
            else
            {
                /*
                 * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature
                 * scheme that did not include a DigestInfo encoding.
                 */
                input = hash;
            }

            signer.update(input, 0, input.length);

            byte[] signature = signer.sign();

            signer.initVerify(publicKey);
            signer.update(input, 0, input.length);

            if (signer.verify(signature))
            {
                return signature;
            }
        }
        catch (GeneralSecurityException e)
        {
            throw new TlsFatalAlert(AlertDescription.internal_error, e);
        }
        finally
        {
            this.rawSigner = null;
        }

        throw new TlsFatalAlert(AlertDescription.internal_error);
    }

    public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) throws IOException
    {
        /*
         * NOTE: The SunMSCAPI provider's "NoneWithRSA" can't produce/verify RSA signatures in the correct format for TLS 1.2
         */
        if (algorithm != null
            && SignatureAlgorithm.rsa == algorithm.getSignature()
            && JcaUtils.isSunMSCAPIProviderActive()
            && isSunMSCAPIRawSigner())
        {
            return crypto.createVerifyingStreamSigner(algorithm, privateKey, true, publicKey);
        }

        return null;
    }

    protected Signature getRawSigner() throws GeneralSecurityException
    {
        if (rawSigner == null)
        {
            rawSigner = crypto.getHelper().createSignature("NoneWithRSA");
            rawSigner.initSign(privateKey, crypto.getSecureRandom());
        }
        return rawSigner;
    }

    protected boolean isSunMSCAPIRawSigner() throws IOException
    {
        try
        {
            Signature rawSigner = getRawSigner();

            return JcaUtils.isSunMSCAPIProvider(rawSigner.getProvider());
        }
        catch (GeneralSecurityException e)
        {
            // Assume the worst!
            return true;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy