Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby-openssl
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b5bec3e62ba5
Choose a base ref
...
head repository: jruby/jruby-openssl
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d434bc622793
Choose a head ref
  • 3 commits
  • 5 files changed
  • 1 contributor

Commits on Nov 30, 2016

  1. Copy the full SHA
    3805a2f View commit details
  2. Copy the full SHA
    2fbb259 View commit details
  3. Copy the full SHA
    d434bc6 View commit details
73 changes: 44 additions & 29 deletions src/main/java/org/jruby/ext/openssl/PKey.java
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@
import org.jruby.ext.openssl.x509store.PEMInputOutput;
import static org.jruby.ext.openssl.OpenSSL.*;
import org.jruby.ext.openssl.impl.CipherSpec;
import org.jruby.util.ByteList;

/**
* @author <a href="mailto:ola.bini@ki.se">Ola Bini</a>
@@ -187,6 +188,8 @@ public IRubyObject initialize(ThreadContext context) {

public String getAlgorithm() { return "NONE"; }

public boolean isPrivateKey() { return getPrivateKey() != null; }

public abstract RubyString to_der() ;

public abstract RubyString to_pem(final IRubyObject[] args) ;
@@ -198,54 +201,66 @@ public RubyString export(final IRubyObject[] args) {

@JRubyMethod(name = "sign")
public IRubyObject sign(IRubyObject digest, IRubyObject data) {
if (!this.callMethod(getRuntime().getCurrentContext(), "private?").isTrue()) {
throw getRuntime().newArgumentError("Private key is needed.");
final Ruby runtime = getRuntime();
if ( ! isPrivateKey() ) {
throw runtime.newArgumentError("Private key is needed.");
}
String digAlg = ((Digest) digest).getShortAlgorithm();
try {
Signature signature = SecurityHelper.getSignature(digAlg + "WITH" + getAlgorithm());
signature.initSign(getPrivateKey());
byte[] inp = data.convertToString().getBytes();
signature.update(inp);
byte[] sigge = signature.sign();
return RubyString.newString(getRuntime(), sigge);
ByteList sign = sign(digAlg + "WITH" + getAlgorithm(), getPrivateKey(), data.convertToString().getByteList());
return RubyString.newString(runtime, sign);
}
catch (GeneralSecurityException gse) {
throw newPKeyError(getRuntime(), gse.getMessage());
catch (GeneralSecurityException ex) {
throw newPKeyError(runtime, ex.getMessage());
}
}

static ByteList sign(final String signAlg, final PrivateKey privateKey, final ByteList data)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = SecurityHelper.getSignature(signAlg);
signature.initSign( privateKey );
signature.update( data.getUnsafeBytes(), data.getBegin(), data.getRealSize() );
return new ByteList(signature.sign(), false);
}

@JRubyMethod(name = "verify")
public IRubyObject verify(IRubyObject digest, IRubyObject sig, IRubyObject data) {
public IRubyObject verify(IRubyObject digest, IRubyObject sign, IRubyObject data) {
final Ruby runtime = getRuntime();
if ( ! (digest instanceof Digest) ) {
throw newPKeyError(getRuntime(), "invalid digest");
throw newPKeyError(runtime, "invalid digest");
}
if ( ! (sig instanceof RubyString) ) {
throw newPKeyError(getRuntime(), "invalid signature");
}
if ( ! (data instanceof RubyString) ) {
throw newPKeyError(getRuntime(), "invalid data");
}
byte[] sigBytes = ((RubyString) sig).getBytes();
byte[] dataBytes = ((RubyString) data).getBytes();
ByteList sigBytes = convertToString(runtime, sign, "OpenSSL::PKey::PKeyError", "invalid signature").getByteList();
ByteList dataBytes = convertToString(runtime, data, "OpenSSL::PKey::PKeyError", "invalid data").getByteList();
String algorithm = ((Digest) digest).getShortAlgorithm() + "WITH" + getAlgorithm();
boolean valid;
try {
Signature signature = SecurityHelper.getSignature(algorithm);
signature.initVerify(getPublicKey());
signature.update(dataBytes);
valid = signature.verify(sigBytes);
return runtime.newBoolean( verify(algorithm, getPublicKey(), dataBytes, sigBytes) );
}
catch (NoSuchAlgorithmException e) {
throw newPKeyError(getRuntime(), "unsupported algorithm: " + algorithm);
throw newPKeyError(runtime, "unsupported algorithm: " + algorithm);
}
catch (SignatureException e) {
throw newPKeyError(getRuntime(), "invalid signature");
throw newPKeyError(runtime, "invalid signature");
}
catch (InvalidKeyException e) {
throw newPKeyError(getRuntime(), "invalid key");
throw newPKeyError(runtime, "invalid key");
}
}

static RubyString convertToString(final Ruby runtime, final IRubyObject str, final String errorType, final CharSequence errorMsg) {
try {
return str.convertToString();
}
return getRuntime().newBoolean(valid);
catch (RaiseException ex) { // to_str conversion failed
throw Utils.newError(runtime, (RubyClass) runtime.getClassFromPath(errorType), errorMsg == null ? null : errorMsg.toString());
}
}

static boolean verify(final String signAlg, final PublicKey publicKey, final ByteList data, final ByteList sign)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = SecurityHelper.getSignature(signAlg);
signature.initVerify(publicKey);
signature.update(data.getUnsafeBytes(), data.getBegin(), data.getRealSize());
return signature.verify(sign.getUnsafeBytes(), sign.getBegin(), sign.getRealSize());
}

// shared Helpers for PKeyRSA / PKEyDSA :
7 changes: 6 additions & 1 deletion src/main/java/org/jruby/ext/openssl/PKeyDH.java
Original file line number Diff line number Diff line change
@@ -274,12 +274,17 @@ public RubyBoolean public_p() {
return getRuntime().newBoolean(dh_y != null);
}

@Override
public boolean isPrivateKey() {
return dh_x != null /* || haveEngine */;
}

@JRubyMethod(name = "private?")
public RubyBoolean private_p() {
// FIXME! need to figure out what it means in MRI/OSSL code to
// claim a DH is private if an engine is present -- doesn't really
// map to Java implementation.
return getRuntime().newBoolean(dh_x != null /* || haveEngine */);
return getRuntime().newBoolean(isPrivateKey());
}

@Override
89 changes: 52 additions & 37 deletions src/main/java/org/jruby/ext/openssl/PKeyDSA.java
Original file line number Diff line number Diff line change
@@ -32,13 +32,7 @@
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.*;
import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
@@ -62,6 +56,7 @@
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.util.ByteList;

import static org.jruby.ext.openssl.OpenSSL.*;
import static org.jruby.ext.openssl.impl.PKey.readDSAPrivateKey;
@@ -129,28 +124,29 @@ public PKeyDSA(Ruby runtime, RubyClass type, DSAPrivateKey privKey, DSAPublicKey

@JRubyMethod(name = "generate", meta = true)
public static IRubyObject generate(IRubyObject self, IRubyObject arg) {
final int keysize = RubyNumeric.fix2int(arg);
PKeyDSA dsa = new PKeyDSA(self.getRuntime(), (RubyClass) self);
dsaGenerate(dsa, keysize);
return dsa;
final Ruby runtime = self.getRuntime();
final int keySize = RubyNumeric.fix2int(arg);
return dsaGenerate(runtime, new PKeyDSA(runtime, (RubyClass) self), keySize);
}

/*
* c: dsa_generate
*/
private static void dsaGenerate(PKeyDSA dsa, int keysize) throws RaiseException {
private static PKeyDSA dsaGenerate(final Ruby runtime,
PKeyDSA dsa, int keySize) throws RaiseException {
try {
KeyPairGenerator gen = SecurityHelper.getKeyPairGenerator("DSA");
gen.initialize(keysize, new SecureRandom());
gen.initialize(keySize, new SecureRandom());
KeyPair pair = gen.generateKeyPair();
dsa.privateKey = (DSAPrivateKey) pair.getPrivate();
dsa.publicKey = (DSAPublicKey) pair.getPublic();
return dsa;
}
catch (NoSuchAlgorithmException e) {
throw newDSAError(dsa.getRuntime(), e.getMessage());
throw newDSAError(runtime, e.getMessage());
}
catch (RuntimeException e) {
throw newDSAError(dsa.getRuntime(), e.getMessage(), e);
throw newDSAError(runtime, e.getMessage(), e);
}
}

@@ -172,8 +168,8 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
if ( args.length > 1 ) pass = args[1];

if ( arg instanceof RubyFixnum ) {
int keysize = RubyNumeric.fix2int((RubyFixnum) arg);
dsaGenerate(this, keysize); return this;
int keySize = RubyNumeric.fix2int((RubyFixnum) arg);
return dsaGenerate(context.runtime, this, keySize);
}

final char[] passwd = password(pass);
@@ -359,35 +355,58 @@ public RubyString to_pem(final IRubyObject[] args) {
}
}

@JRubyMethod
public IRubyObject syssign(IRubyObject arg) {
// TODO
return getRuntime().getNil();
@JRubyMethod // ossl_dsa_sign
public IRubyObject syssign(IRubyObject data) {
final Ruby runtime = getRuntime();

DSAPrivateKey privateKey;
if ((privateKey = this.privateKey) == null) {
throw newDSAError(runtime, "Private DSA key needed!");
}

try {
ByteList sign = sign("NONEwithDSA", privateKey, data.convertToString().getByteList()); // DSS1
return RubyString.newString(runtime, sign);
}
catch (GeneralSecurityException ex) {
throw newDSAError(runtime, ex.getMessage());
}
}

@JRubyMethod
public IRubyObject sysverify(IRubyObject arg, IRubyObject arg2) {
// TODO
return getRuntime().getNil();
@JRubyMethod // ossl_dsa_verify
public IRubyObject sysverify(IRubyObject data, IRubyObject sign) {
final Ruby runtime = getRuntime();
ByteList sigBytes = convertToString(runtime, sign, "OpenSSL::PKey::DSAError", "invalid signature").getByteList();
ByteList dataBytes = convertToString(runtime, data, "OpenSSL::PKey::DSAError", "invalid data").getByteList();
try {
return runtime.newBoolean( verify("NONEwithDSA", getPublicKey(), dataBytes, sigBytes) );
}
catch (NoSuchAlgorithmException e) {
throw newDSAError(runtime, e.getMessage());
}
catch (SignatureException e) {
throw newDSAError(runtime, "invalid signature");
}
catch (InvalidKeyException e) {
throw newDSAError(runtime, "invalid key");
}
}

private DSAKey getDsaKey() {
DSAKey result;
return (result = publicKey) != null ? result : privateKey;
DSAKey result;
return (result = publicKey) != null ? result : privateKey;
}

private IRubyObject toBN(BigInteger value) {
return value == null ? getRuntime().getNil() : BN.newBN(getRuntime(), value);
return value == null ? getRuntime().getNil() : BN.newBN(getRuntime(), value);
}

private synchronized BigInteger getP() {
DSAKey key = getDsaKey();
if (key != null) {
return key.getParams().getP();
}
else {
return dsa_p;
}
return dsa_p;
}

@JRubyMethod(name = "p")
@@ -405,9 +424,7 @@ private synchronized BigInteger getQ() {
if (key != null) {
return key.getParams().getQ();
}
else {
return dsa_q;
}
return dsa_q;
}

@JRubyMethod(name = "q")
@@ -425,9 +442,7 @@ private synchronized BigInteger getG() {
if (key != null) {
return key.getParams().getG();
}
else {
return dsa_g;
}
return dsa_g;
}

@JRubyMethod(name = "g")
7 changes: 6 additions & 1 deletion src/main/java/org/jruby/ext/openssl/PKeyRSA.java
Original file line number Diff line number Diff line change
@@ -322,9 +322,14 @@ public RubyBoolean public_p() {
return publicKey != null ? getRuntime().getTrue() : getRuntime().getFalse();
}

@Override
public boolean isPrivateKey() {
return privateKey != null;
}

@JRubyMethod(name = "private?")
public RubyBoolean private_p() {
return privateKey != null ? getRuntime().getTrue() : getRuntime().getFalse();
return getRuntime().newBoolean(isPrivateKey());
}

@Override
10 changes: 10 additions & 0 deletions src/test/ruby/dsa/test_dsa.rb
Original file line number Diff line number Diff line change
@@ -61,4 +61,14 @@ def test_dsa_from_params_public_first
assert_equal(key.send(param), dsa.send(param), param)
end
end

def test_dsa_sys_sign_verify
dsa = OpenSSL::PKey::DSA.new(1024)
doc = 'Sign ME!'
digest = OpenSSL::Digest::SHA1.digest(doc)
sig = dsa.syssign(digest)
puts sig.inspect if $VERBOSE
assert dsa.sysverify(digest, sig).eql?(true)
end

end