Skip to content

Commit a3ac55f

Browse files
committed
try using thread-shared secure random gen (in PKey-s) where possible
1 parent 3e1b97b commit a3ac55f

File tree

4 files changed

+26
-25
lines changed

4 files changed

+26
-25
lines changed

src/main/java/org/jruby/ext/openssl/PKey.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,7 @@
3232
import java.io.InputStreamReader;
3333
import java.io.StringReader;
3434
import java.math.BigInteger;
35-
import java.security.GeneralSecurityException;
36-
import java.security.InvalidKeyException;
37-
import java.security.KeyFactory;
38-
import java.security.KeyPair;
39-
import java.security.NoSuchAlgorithmException;
40-
import java.security.PrivateKey;
41-
import java.security.PublicKey;
42-
import java.security.Signature;
43-
import java.security.SignatureException;
35+
import java.security.*;
4436
import java.security.interfaces.DSAPrivateKey;
4537
import java.security.interfaces.DSAPublicKey;
4638
import java.security.interfaces.RSAPrivateCrtKey;
@@ -263,6 +255,26 @@ static boolean verify(final String signAlg, final PublicKey publicKey, final Byt
263255
return signature.verify(sign.getUnsafeBytes(), sign.getBegin(), sign.getRealSize());
264256
}
265257

258+
private static boolean tryContextSecureRandom = true;
259+
260+
static SecureRandom getSecureRandom(final Ruby runtime) {
261+
if ( tryContextSecureRandom ) {
262+
final ThreadContext context = runtime.getCurrentContext();
263+
try {
264+
SecureRandom random = context.secureRandom;
265+
if (random == null) { // public SecureRandom getSecureRandom() on 9K
266+
random = (SecureRandom) context.getClass().getMethod("getSecureRandom").invoke(context);
267+
}
268+
return random;
269+
}
270+
catch (Throwable ex) {
271+
tryContextSecureRandom = false;
272+
debug(runtime, "PKey falling back to using new SecureRandom()", ex);
273+
}
274+
}
275+
return new SecureRandom();
276+
}
277+
266278
// shared Helpers for PKeyRSA / PKEyDSA :
267279

268280
protected PrivateKey tryPKCS8EncodedKey(final Ruby runtime, final KeyFactory keyFactory, final byte[] encodedKey) {

src/main/java/org/jruby/ext/openssl/PKeyDH.java

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,6 @@ public static RaiseException newDHError(Ruby runtime, String message) {
9393
return Utils.newError(runtime, _PKey(runtime).getClass("DHError"), message);
9494
}
9595

96-
private static SecureRandom _secureRandom;
97-
98-
private static SecureRandom getSecureRandom() {
99-
SecureRandom rand;
100-
if ((rand = _secureRandom) != null) {
101-
return rand;
102-
}
103-
// FIXME: do we want a particular algorithm / provider? BC?
104-
return _secureRandom = new SecureRandom();
105-
}
106-
10796
// transient because: we do not want these value serialized (insecure)
10897
// volatile because: permits unsynchronized reads in some cases
10998
private transient volatile BigInteger dh_p;
@@ -201,7 +190,7 @@ public static BigInteger generateX(BigInteger p, int limit) {
201190
if (limit < 0) throw new IllegalArgumentException("invalid limit");
202191

203192
BigInteger x;
204-
SecureRandom secureRandom = getSecureRandom();
193+
SecureRandom secureRandom = new SecureRandom();
205194
// adapting algorithm from org.bouncycastle.crypto.generators.DHKeyGeneratorHelper,
206195
// which seems a little stronger (?) than OpenSSL's (OSSL just generates a random,
207196
// while BC generates a random potential prime [for limit > 0], though it's not
@@ -252,11 +241,11 @@ public synchronized IRubyObject generate_key() {
252241
@JRubyMethod(name = "compute_key")
253242
public synchronized IRubyObject compute_key(IRubyObject other_pub_key) {
254243
BigInteger x, y, p;
255-
if ((y = BN.getBigInteger(other_pub_key)) == null) {
244+
if ((y = BN.asBigInteger(other_pub_key)) == null) {
256245
throw getRuntime().newArgumentError("invalid public key");
257246
}
258247
if ((x = this.dh_x) == null || (p = this.dh_p) == null) {
259-
throw newDHError(getRuntime(), "can't compute key");
248+
throw newDHError(getRuntime(), "incomplete DH");
260249
}
261250
int plen;
262251
if ((plen = p.bitLength()) == 0 || plen > OPENSSL_DH_MAX_MODULUS_BITS) {

src/main/java/org/jruby/ext/openssl/PKeyDSA.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private static PKeyDSA dsaGenerate(final Ruby runtime,
136136
PKeyDSA dsa, int keySize) throws RaiseException {
137137
try {
138138
KeyPairGenerator gen = SecurityHelper.getKeyPairGenerator("DSA");
139-
gen.initialize(keySize, new SecureRandom());
139+
gen.initialize(keySize, getSecureRandom(runtime));
140140
KeyPair pair = gen.generateKeyPair();
141141
dsa.privateKey = (DSAPrivateKey) pair.getPrivate();
142142
dsa.publicKey = (DSAPublicKey) pair.getPublic();

src/main/java/org/jruby/ext/openssl/PKeyRSA.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ private static PKeyRSA rsaGenerate(final Ruby runtime,
175175
if ( "IBMJCEFIPS".equals( gen.getProvider().getName() ) ) {
176176
gen.initialize(keySize); // IBMJCEFIPS does not support parameters
177177
} else {
178-
gen.initialize(new RSAKeyGenParameterSpec(keySize, exp), new SecureRandom());
178+
gen.initialize(new RSAKeyGenParameterSpec(keySize, exp), getSecureRandom(runtime));
179179
}
180180
KeyPair pair = gen.generateKeyPair();
181181
rsa.privateKey = (RSAPrivateCrtKey) pair.getPrivate();

0 commit comments

Comments
 (0)