| package org.bouncycastle.crypto.tls; |
| |
| import org.bouncycastle.crypto.AsymmetricBlockCipher; |
| import org.bouncycastle.crypto.CipherParameters; |
| import org.bouncycastle.crypto.CryptoException; |
| import org.bouncycastle.crypto.Digest; |
| 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.params.RSAKeyParameters; |
| import org.bouncycastle.crypto.signers.GenericSigner; |
| import org.bouncycastle.crypto.signers.RSADigestSigner; |
| |
| public class TlsRSASigner |
| extends AbstractTlsSigner |
| { |
| public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm, |
| AsymmetricKeyParameter privateKey, byte[] hash) |
| throws CryptoException |
| { |
| Signer signer = makeSigner(algorithm, true, true, |
| new ParametersWithRandom(privateKey, this.context.getSecureRandom())); |
| signer.update(hash, 0, hash.length); |
| return signer.generateSignature(); |
| } |
| |
| public boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes, |
| AsymmetricKeyParameter publicKey, byte[] hash) |
| throws CryptoException |
| { |
| Signer signer = makeSigner(algorithm, true, false, publicKey); |
| signer.update(hash, 0, hash.length); |
| return signer.verifySignature(sigBytes); |
| } |
| |
| public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey) |
| { |
| return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom())); |
| } |
| |
| public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey) |
| { |
| return makeSigner(algorithm, false, false, publicKey); |
| } |
| |
| public boolean isValidPublicKey(AsymmetricKeyParameter publicKey) |
| { |
| return publicKey instanceof RSAKeyParameters && !publicKey.isPrivate(); |
| } |
| |
| protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning, |
| CipherParameters cp) |
| { |
| if ((algorithm != null) != TlsUtils.isTLSv12(context)) |
| { |
| throw new IllegalStateException(); |
| } |
| |
| if (algorithm != null && algorithm.getSignature() != SignatureAlgorithm.rsa) |
| { |
| throw new IllegalStateException(); |
| } |
| |
| Digest d; |
| if (raw) |
| { |
| d = new NullDigest(); |
| } |
| else if (algorithm == null) |
| { |
| d = new CombinedHash(); |
| } |
| else |
| { |
| d = TlsUtils.createHash(algorithm.getHash()); |
| } |
| |
| Signer s; |
| if (algorithm != null) |
| { |
| /* |
| * 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]. |
| */ |
| s = new RSADigestSigner(d, 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. |
| */ |
| s = new GenericSigner(createRSAImpl(), d); |
| } |
| s.init(forSigning, cp); |
| return s; |
| } |
| |
| protected AsymmetricBlockCipher createRSAImpl() |
| { |
| /* |
| * RFC 5264 7.4.7.1. Implementation note: It is now known that remote timing-based attacks |
| * on TLS are possible, at least when the client and server are on the same LAN. |
| * Accordingly, implementations that use static RSA keys MUST use RSA blinding or some other |
| * anti-timing technique, as described in [TIMING]. |
| */ |
| return new PKCS1Encoding(new RSABlindedEngine()); |
| } |
| } |