diff --git a/lib/jopenssl/_compat23.rb b/lib/jopenssl/_compat23.rb index e080c840..978a8ce0 100644 --- a/lib/jopenssl/_compat23.rb +++ b/lib/jopenssl/_compat23.rb @@ -33,13 +33,6 @@ def set_key(pub_key, priv_key) self end - def set_pqg(p, q, g) - self.p = p - self.q = q - self.g = g - self - end - end end diff --git a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java index bf484a72..53acd197 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java @@ -450,11 +450,11 @@ private IRubyObject toBN(BigInteger value) { } private synchronized BigInteger getP() { + if (dsa_p != null) return dsa_p; + DSAKey key = getDsaKey(); - if (key != null) { - return key.getParams().getP(); - } - return dsa_p; + if (key != null) return key.getParams().getP(); + return null; } @JRubyMethod(name = "p") @@ -468,11 +468,11 @@ public synchronized IRubyObject set_p(IRubyObject p) { } private synchronized BigInteger getQ() { + if (dsa_q != null) return dsa_q; + DSAKey key = getDsaKey(); - if (key != null) { - return key.getParams().getQ(); - } - return dsa_q; + if (key != null) return key.getParams().getQ(); + return null; } @JRubyMethod(name = "q") @@ -486,11 +486,11 @@ public synchronized IRubyObject set_q(IRubyObject q) { } private synchronized BigInteger getG() { + if (dsa_g != null) return dsa_g; + DSAKey key = getDsaKey(); - if (key != null) { - return key.getParams().getG(); - } - return dsa_g; + if (key != null) return key.getParams().getG(); + return null; } @JRubyMethod(name = "g") @@ -503,6 +503,15 @@ public synchronized IRubyObject set_g(IRubyObject g) { return setKeySpecComponent(SPEC_G, g); } + @JRubyMethod + public IRubyObject set_pqg(IRubyObject p, IRubyObject q, IRubyObject g) { + this.dsa_p = BN.getBigInteger(p); + this.dsa_q = BN.getBigInteger(q); + this.dsa_g = BN.getBigInteger(g); + generateKeyInternal(); + return this; + } + @JRubyMethod(name = "priv_key") public synchronized IRubyObject get_priv_key() { DSAPrivateKey key; @@ -533,7 +542,6 @@ public synchronized IRubyObject set_pub_key(IRubyObject pub_key) { private IRubyObject setKeySpecComponent(final int index, final IRubyObject value) { final BigInteger val = BN.getBigInteger(value); - switch (index) { case SPEC_X: this.dsa_x = val; break; case SPEC_Y: this.dsa_y = val; break; @@ -542,19 +550,49 @@ private IRubyObject setKeySpecComponent(final int index, final IRubyObject value case SPEC_G: this.dsa_g = val; break; } + generateKeyInternal(); + return value; + } + + private BigInteger getX() { + if (dsa_x != null) return dsa_x; + + DSAPrivateKey key; + if ((key = this.privateKey) != null) { + return key.getX(); + } + return null; + } + + private BigInteger getY() { + if (dsa_y != null) return dsa_y; + + DSAPublicKey key; + if ((key = this.publicKey) != null) { + return key.getY(); + } + return null; + } + + private void generateKeyInternal() { // Don't access the dsa_p, dsa_q and dsa_g fields directly. They may // have already been consumed and cleared. - BigInteger _dsa_p = getP(); - BigInteger _dsa_q = getQ(); - BigInteger _dsa_g = getG(); + final BigInteger dsa_p = getP(); + final BigInteger dsa_q = getQ(); + final BigInteger dsa_g = getG(); + + final BigInteger dsa_x = getX(); + final BigInteger dsa_y = getY(); - if ( dsa_x != null && _dsa_p != null && _dsa_q != null && _dsa_g != null ) { + if ( dsa_x != null && dsa_p != null && dsa_q != null && dsa_g != null ) { // we now have all private key components. create the key : - DSAPrivateKeySpec spec = new DSAPrivateKeySpec(dsa_x, _dsa_p, _dsa_q, _dsa_g); + DSAPrivateKeySpec spec = new DSAPrivateKeySpec(dsa_x, dsa_p, dsa_q, dsa_g); try { this.privateKey = (DSAPrivateKey) SecurityHelper.getKeyFactory("DSA").generatePrivate(spec); } catch (InvalidKeySpecException e) { + e.printStackTrace(); + throw newDSAError(getRuntime(), "invalid keyspec", e); } catch (NoSuchAlgorithmException e) { @@ -564,9 +602,9 @@ private IRubyObject setKeySpecComponent(final int index, final IRubyObject value this.dsa_x = this.dsa_p = this.dsa_q = this.dsa_g = null; } - if ( dsa_y != null && _dsa_p != null && _dsa_q != null && _dsa_g != null ) { + if ( dsa_y != null && dsa_p != null && dsa_q != null && dsa_g != null ) { // we now have all public key components. create the key : - DSAPublicKeySpec spec = new DSAPublicKeySpec(dsa_y, _dsa_p, _dsa_q, _dsa_g); + DSAPublicKeySpec spec = new DSAPublicKeySpec(dsa_y, dsa_p, dsa_q, dsa_g); try { this.publicKey = (DSAPublicKey) SecurityHelper.getKeyFactory("DSA").generatePublic(spec); } @@ -579,8 +617,6 @@ private IRubyObject setKeySpecComponent(final int index, final IRubyObject value // clear out the specValues this.dsa_y = this.dsa_p = this.dsa_q = this.dsa_g = null; } - - return value; } private static final int SPEC_X = 0; diff --git a/src/test/ruby/dsa/test_dsa.rb b/src/test/ruby/dsa/test_dsa.rb index bda20c57..d0bb5aee 100644 --- a/src/test/ruby/dsa/test_dsa.rb +++ b/src/test/ruby/dsa/test_dsa.rb @@ -7,6 +7,18 @@ def setup super end + def test_dup + key = Fixtures.pkey("dsa1024") + key2 = key.dup + assert_equal key.params, key2.params + + # PKey is immutable in OpenSSL >= 3.0 + #if !openssl?(3, 0, 0) + key2.set_pqg(key2.p, key2.q, key2.g + 1) + assert_not_equal key.params, key2.params + #end + end + def test_dsa_param_accessors key_file = File.join(File.dirname(__FILE__), 'private_key.pem') key = OpenSSL::PKey::DSA.new(File.read(key_file)) @@ -65,7 +77,7 @@ def test_dsa_sys_sign_verify doc = 'Sign ME!' digest = OpenSSL::Digest::SHA1.digest(doc) sig = dsa.syssign(digest) - puts sig.inspect if $VERBOSE + #puts sig.inspect if $VERBOSE assert dsa.sysverify(digest, sig).eql?(true) end diff --git a/src/test/ruby/fixtures/pkey/dsa1024 b/src/test/ruby/fixtures/pkey/dsa1024 new file mode 100644 index 00000000..1bf49889 --- /dev/null +++ b/src/test/ruby/fixtures/pkey/dsa1024 @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n +D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa +/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz +4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx +OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg +YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w +DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4 +IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2 +jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2 +CVArsEzlPUCbohPvZnE= +-----END DSA PRIVATE KEY-----