package org.bouncycastle.tls.crypto.impl.bc; import java.io.IOException; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.Signer; import org.bouncycastle.crypto.digests.NullDigest; import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSABlindedEngine; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.signers.GenericSigner; import org.bouncycastle.crypto.signers.RSADigestSigner; 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 RSA signatures using the BC light-weight API. */ public class BcTlsRSASigner implements TlsSigner { private final AsymmetricKeyParameter privateKey; private final BcTlsCrypto crypto; public BcTlsRSASigner(BcTlsCrypto crypto, AsymmetricKeyParameter privateKey) { this.crypto = crypto; if (privateKey == null) { throw new IllegalArgumentException("'privateKey' cannot be null"); } if (!privateKey.isPrivate()) { throw new IllegalArgumentException("'privateKey' must be private"); } this.privateKey = privateKey; } public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm, byte[] hash) throws IOException { Signer signer; 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]. */ signer = new RSADigestSigner(new NullDigest(), TlsUtils.getOIDForHashAlgorithm(algorithm.getHash())); } else { /* * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme * that did not include a DigestInfo encoding. */ signer = new GenericSigner(new PKCS1Encoding(new RSABlindedEngine()), new NullDigest()); } signer.init(true, new ParametersWithRandom(privateKey, crypto.getSecureRandom())); signer.update(hash, 0, hash.length); try { return signer.generateSignature(); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.internal_error, e); } } public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) { return null; } }