Skip to content

Start adding support for missing features #330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/java/org/jruby/ext/openssl/ASN1.java
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,9 @@ private static void defaultObjects(final Ruby runtime) {
addObject(runtime, 184, "AES-256-CBC", "aes-256-cbc","2.16.840.1.101.3.4.1.42");
addObject(runtime, 185, "AES-256-OFB", "aes-256-ofb","2.16.840.1.101.3.4.1.43");
addObject(runtime, 186, "AES-256-CFB", "aes-256-cfb","2.16.840.1.101.3.4.1.44");
addObject(runtime, 187, "Ed25519", "ed25519", "1.3.101.112");
addObject(runtime, 188, "X25519", "x25519", "1.3.101.110");
addObject(runtime, 672, "SHA256", "sha256", "2.16.840.1.101.3.4.2.1");

addObject(runtime, 660, "street", "streetAddress", "2.5.4.9");
addObject(runtime, 391, "DC", "domainComponent", "0.9.2342.19200300.100.1.25");
//addObject(runtime, 509, null, "generationQualifier", "2.5.4.44");
Expand Down
69 changes: 68 additions & 1 deletion src/main/java/org/jruby/ext/openssl/PKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;

import javax.crypto.spec.DHParameterSpec;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyException;
import org.jruby.RubyInteger;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.RubyString;
Expand Down Expand Up @@ -124,13 +129,16 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
pass = args[1].isNil() ? null : args[1].toString().toCharArray();
}

ArrayList<Exception> exceptions = new ArrayList<>();

final RubyString str = readInitArg(context, data);
KeyPair keyPair;
// d2i_PrivateKey_bio
try {
keyPair = readPrivateKey(str, pass);
} catch (IOException e) {
debugStackTrace(runtime, "PKey readPrivateKey", e); /* ignore */
exceptions.add(e);
keyPair = null;
}
// PEM_read_bio_PrivateKey
Expand All @@ -154,12 +162,14 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
if (pubKey != null) return new PKeyRSA(runtime, (RSAPublicKey) pubKey);
} catch (IOException e) {
debugStackTrace(runtime, "PKey readRSAPublicKey", e); /* ignore */
exceptions.add(e);
}
try {
pubKey = PEMInputOutput.readDSAPublicKey(new StringReader(str.toString()), null);
if (pubKey != null) return new PKeyDSA(runtime, (DSAPublicKey) pubKey);
} catch (IOException e) {
debugStackTrace(runtime, "PKey readDSAPublicKey", e); /* ignore */
exceptions.add(e);
}

final byte[] input = StringHelper.readX509PEM(context, str);
Expand All @@ -168,14 +178,27 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
pubKey = org.jruby.ext.openssl.impl.PKey.readPublicKey(input);
} catch (IOException e) {
debugStackTrace(runtime, "PKey readPublicKey", e); /* ignore */
exceptions.add(e);
}
// PEM_read_bio_PUBKEY
if (pubKey == null) {
try {
pubKey = PEMInputOutput.readPubKey(new StringReader(str.toString()));
} catch (IOException e) {
debugStackTrace(runtime, "PKey readPubKey", e); /* ignore */
exceptions.add(e);
}
}

if (pubKey == null) {
try {
final PKeyDH dh = new PKeyDH(runtime, str);
return dh;
} catch (Exception e) {
debugStackTrace(runtime, "PKey read DH", e); /* ignore */
exceptions.add(e);
}

}

if (pubKey instanceof RSAPublicKey) {
Expand All @@ -188,14 +211,35 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
return new PKeyEC(runtime, pubKey);
}

throw newPKeyError(runtime, "Could not parse PKey: unsupported");
exceptions.stream().forEach(Throwable::printStackTrace);

throw newPKeyError(runtime, "Could not parse PKey: unsupported " + pubKey + " " + exceptions);
}

private static String getAlgorithm(final KeyPair key) {
if ( key.getPrivate() != null ) return key.getPrivate().getAlgorithm();
if ( key.getPublic() != null ) return key.getPublic().getAlgorithm();
return null;
}

@JRubyMethod(name = "generate_key", meta = true, required = 1, optional = 1)
public static IRubyObject generateKey(final ThreadContext context, IRubyObject recv, IRubyObject[] args) {
if (!(args[0] instanceof RubyString)) {
throw context.getRuntime().newNotImplementedError("generate_key not implemented for " + args[0].getMetaClass().getName());
}


throw context.getRuntime().newNotImplementedError("generate_key not implemented for " + args[0].inspect());
}

@JRubyMethod(name = "generate_parameters", meta = true, required = 1, optional = 1)
public static IRubyObject generateParameters(final ThreadContext context, IRubyObject recv, IRubyObject[] args) {
if (!(args[0] instanceof RubyString)) {
throw context.getRuntime().newArgumentError("generate_parameters requires a string argument");
}

throw context.getRuntime().newNotImplementedError("generate_parameters not implemented for " + args[0].inspect() + " " + args[1].inspect());
}
}

public PKey(Ruby runtime, RubyClass type) {
Expand All @@ -222,6 +266,8 @@ public IRubyObject initialize(ThreadContext context) {

public abstract RubyString to_pem(ThreadContext context, final IRubyObject[] args) ;

public abstract RubyString oid() ;

@JRubyMethod(name = "sign")
public IRubyObject sign(IRubyObject digest, IRubyObject data) {
final Ruby runtime = getRuntime();
Expand All @@ -246,6 +292,27 @@ public ASN1Primitive toASN1PublicInfo() throws IOException {
return data;
}

@JRubyMethod(name = "inspect")
public IRubyObject inspect() {
final Ruby runtime = getRuntime();
final StringBuilder result = new StringBuilder();
result.append("#<").append(getMetaClass().getName()).append(" ");
result.append("oid=").append(this.oid().asJavaString());
result.append(">");
return runtime.newString(result.toString());
}

@JRubyMethod(name = "compare?", required = 1)
public IRubyObject compare(ThreadContext context, IRubyObject other) {
if (other instanceof PKey) {
final PKey otherKey = (PKey) other;
if (this.getAlgorithm().equals(otherKey.getAlgorithm())) {
return context.runtime.newBoolean(this.to_der().equals(otherKey.to_der()));
}
}
return context.runtime.getFalse();
}

@Override
public Object toJava(final Class target) {
if (PrivateKey.class.isAssignableFrom(target)) {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/jruby/ext/openssl/PKeyDH.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ static void createPKeyDH(final Ruby runtime, final RubyModule PKey, final RubyCl
DH.defineAnnotatedMethods(PKeyDH.class);
}

public PKeyDH(Ruby runtime, RubyString str) {
super(runtime, _DH(runtime));
this.initialize(runtime.getCurrentContext(), new IRubyObject[] { str });
}

static RubyClass _DH(final Ruby runtime) {
return _PKey(runtime).getClass("DH");
}

public static RaiseException newDHError(Ruby runtime, String message) {
return Utils.newError(runtime, _PKey(runtime).getClass("DHError"), message);
}
Expand Down Expand Up @@ -431,6 +440,12 @@ public synchronized IRubyObject set_priv_key(IRubyObject arg) {
return arg;
}

@Override
@JRubyMethod
public RubyString oid() {
return getRuntime().newString("DH");
}

@JRubyMethod
public IRubyObject set_key(final ThreadContext context, IRubyObject pub_key, IRubyObject priv_key) {
set_pub_key(pub_key);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jruby/ext/openssl/PKeyDSA.java
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ public IRubyObject sysverify(IRubyObject data, IRubyObject sign) {
}

@JRubyMethod
public IRubyObject oid() {
public RubyString oid() {
return getRuntime().newString("DSA");
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jruby/ext/openssl/PKeyEC.java
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ public IRubyObject dh_compute_key(final ThreadContext context, final IRubyObject
}

@JRubyMethod
public IRubyObject oid() {
public RubyString oid() {
return getRuntime().newString("id-ecPublicKey");
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/jruby/ext/openssl/PKeyRSA.java
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,9 @@ private RubyString doCipherRSA(final Ruby runtime,
}
}

@Override
@JRubyMethod
public IRubyObject oid() {
public RubyString oid() {
return getRuntime().newString("rsaEncryption");
}

Expand Down
Loading
Loading