1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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());
}
}
|