Skip to content

Commit b0cffd6

Browse files
committed
Merge pull request #82 from philr/rsa_priv_and_pub_from_params
Instantiate both the RSA private and public keys when setting parameters
2 parents b8bac99 + c106648 commit b0cffd6

File tree

2 files changed

+79
-23
lines changed

2 files changed

+79
-23
lines changed

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

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -648,17 +648,19 @@ public synchronized IRubyObject get_q() {
648648
return getRuntime().getNil();
649649
}
650650

651-
@JRubyMethod(name="e")
652-
public synchronized IRubyObject get_e() {
653-
RSAPublicKey key;
654-
BigInteger e;
655-
if ((key = publicKey) != null) {
656-
e = key.getPublicExponent();
657-
} else if(privateKey != null) {
658-
e = privateKey.getPublicExponent();
651+
private BigInteger getPublicExponent() {
652+
if (publicKey != null) {
653+
return publicKey.getPublicExponent();
654+
} else if (privateKey != null) {
655+
return privateKey.getPublicExponent();
659656
} else {
660-
e = rsa_e;
657+
return rsa_e;
661658
}
659+
}
660+
661+
@JRubyMethod(name="e")
662+
public synchronized IRubyObject get_e() {
663+
BigInteger e = getPublicExponent();
662664
if (e != null) {
663665
return BN.newBN(getRuntime(), e);
664666
}
@@ -679,17 +681,19 @@ public synchronized IRubyObject set_e(final ThreadContext context, IRubyObject v
679681
return value;
680682
}
681683

682-
@JRubyMethod(name="n")
683-
public synchronized IRubyObject get_n() {
684-
RSAPublicKey key;
685-
BigInteger n;
686-
if ((key = publicKey) != null) {
687-
n = key.getModulus();
688-
} else if(privateKey != null) {
689-
n = privateKey.getModulus();
684+
private BigInteger getModulus() {
685+
if (publicKey != null) {
686+
return publicKey.getModulus();
687+
} else if (privateKey != null) {
688+
return privateKey.getModulus();
690689
} else {
691-
n = rsa_n;
690+
return rsa_n;
692691
}
692+
}
693+
694+
@JRubyMethod(name="n")
695+
public synchronized IRubyObject get_n() {
696+
BigInteger n = getModulus();
693697
if (n != null) {
694698
return BN.newBN(getRuntime(), n);
695699
}
@@ -715,8 +719,12 @@ private void generatePublicKeyIfParams(final ThreadContext context) {
715719

716720
if ( publicKey != null ) throw newRSAError(runtime, "illegal modification");
717721

718-
BigInteger e, n;
719-
if ( (e = rsa_e) != null && (n = rsa_n) != null ) {
722+
// Don't access the rsa_n and rsa_e fields directly. They may have
723+
// already been consumed and cleared by generatePrivateKeyIfParams.
724+
BigInteger _rsa_n = getModulus();
725+
BigInteger _rsa_e = getPublicExponent();
726+
727+
if (_rsa_n != null && _rsa_e != null) {
720728
final KeyFactory rsaFactory;
721729
try {
722730
rsaFactory = SecurityHelper.getKeyFactory("RSA");
@@ -726,7 +734,7 @@ private void generatePublicKeyIfParams(final ThreadContext context) {
726734
}
727735

728736
try {
729-
publicKey = (RSAPublicKey) rsaFactory.generatePublic(new RSAPublicKeySpec(n, e));
737+
publicKey = (RSAPublicKey) rsaFactory.generatePublic(new RSAPublicKeySpec(_rsa_n, _rsa_e));
730738
}
731739
catch (InvalidKeySpecException ex) {
732740
throw newRSAError(runtime, "invalid parameters");
@@ -741,7 +749,12 @@ private void generatePrivateKeyIfParams(final ThreadContext context) {
741749

742750
if ( privateKey != null ) throw newRSAError(runtime, "illegal modification");
743751

744-
if (rsa_e != null && rsa_n != null && rsa_p != null && rsa_q != null && rsa_d != null && rsa_dmp1 != null && rsa_dmq1 != null && rsa_iqmp != null) {
752+
// Don't access the rsa_n and rsa_e fields directly. They may have
753+
// already been consumed and cleared by generatePublicKeyIfParams.
754+
BigInteger _rsa_n = getModulus();
755+
BigInteger _rsa_e = getPublicExponent();
756+
757+
if (_rsa_n != null && _rsa_e != null && rsa_p != null && rsa_q != null && rsa_d != null && rsa_dmp1 != null && rsa_dmq1 != null && rsa_iqmp != null) {
745758
final KeyFactory rsaFactory;
746759
try {
747760
rsaFactory = SecurityHelper.getKeyFactory("RSA");
@@ -752,7 +765,7 @@ private void generatePrivateKeyIfParams(final ThreadContext context) {
752765

753766
try {
754767
privateKey = (RSAPrivateCrtKey) rsaFactory.generatePrivate(
755-
new RSAPrivateCrtKeySpec(rsa_n, rsa_e, rsa_d, rsa_p, rsa_q, rsa_dmp1, rsa_dmq1, rsa_iqmp)
768+
new RSAPrivateCrtKeySpec(_rsa_n, _rsa_e, rsa_d, rsa_p, rsa_q, rsa_dmp1, rsa_dmq1, rsa_iqmp)
756769
);
757770
}
758771
catch (InvalidKeySpecException e) {

src/test/ruby/rsa/test_rsa.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,47 @@ def test_rsa_public_encrypt
4747
# }
4848
end
4949

50+
def test_rsa_param_accessors
51+
key_file = File.join(File.dirname(__FILE__), 'private_key.pem')
52+
key = OpenSSL::PKey::RSA.new(File.read(key_file))
53+
54+
[:e, :n, :d, :p, :q, :iqmp, :dmp1, :dmq1].each do |param|
55+
rsa = OpenSSL::PKey::RSA.new
56+
assert_nil(rsa.send(param))
57+
value = key.send(param)
58+
rsa.send("#{param}=", value)
59+
assert_equal(value, rsa.send(param), param)
60+
end
61+
end
62+
63+
def test_rsa_from_params_public_first
64+
key_file = File.join(File.dirname(__FILE__), 'private_key.pem')
65+
key = OpenSSL::PKey::RSA.new(File.read(key_file))
66+
67+
rsa = OpenSSL::PKey::RSA.new
68+
rsa.e, rsa.n = key.e, key.n
69+
assert_nothing_raised { rsa.public_encrypt('Test string') }
70+
[:e, :n].each {|param| assert_equal(key.send(param), rsa.send(param)) }
71+
72+
rsa.d, rsa.p, rsa.q, rsa.iqmp, rsa.dmp1, rsa.dmq1 = key.d, key.p, key.q, key.iqmp, key.dmp1, key.dmq1
73+
assert_nothing_raised { rsa.private_encrypt('Test string') }
74+
[:e, :n, :d, :p, :q, :iqmp, :dmp1, :dmq1].each do |param|
75+
assert_equal(key.send(param), rsa.send(param), param)
76+
end
77+
end
78+
79+
def test_rsa_from_params_private_first
80+
key_file = File.join(File.dirname(__FILE__), 'private_key.pem')
81+
key = OpenSSL::PKey::RSA.new(File.read(key_file))
82+
83+
rsa = OpenSSL::PKey::RSA.new
84+
rsa.d, rsa.p, rsa.q, rsa.iqmp, rsa.dmp1, rsa.dmq1 = key.d, key.p, key.q, key.iqmp, key.dmp1, key.dmq1
85+
rsa.e, rsa.n = key.e, key.n
86+
assert_nothing_raised { rsa.public_encrypt('Test string') }
87+
assert_nothing_raised { rsa.private_encrypt('Test string') }
88+
[:e, :n, :d, :p, :q, :iqmp, :dmp1, :dmq1].each do |param|
89+
assert_equal(key.send(param), rsa.send(param), param)
90+
end
91+
end
92+
5093
end

0 commit comments

Comments
 (0)