From d95a42940ff4c52e39cfed5f452c8688ab2a1c6e Mon Sep 17 00:00:00 2001 From: kares Date: Sun, 19 Jan 2025 17:51:00 +0100 Subject: [PATCH 01/16] [release] update to next dev SNAPSHOT --- lib/jopenssl/version.rb | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index 3a84cdf9..05f5275a 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,5 +1,5 @@ module JOpenSSL - VERSION = '0.15.3' + VERSION = '0.15.4.dev' BOUNCY_CASTLE_VERSION = '1.79' end diff --git a/pom.xml b/pom.xml index ac6278e6..9c248a14 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ DO NOT MODIFY - GENERATED CODE 4.0.0 rubygems jruby-openssl - 0.15.3 + 0.15.4.dev-SNAPSHOT gem JRuby OpenSSL JRuby-OpenSSL is an add-on gem for JRuby that emulates the Ruby OpenSSL native library. From 758b62e712e2b0c32b4edd2fe4ce0e164abeaa7e Mon Sep 17 00:00:00 2001 From: kares Date: Sun, 19 Jan 2025 18:09:58 +0100 Subject: [PATCH 02/16] [deps] upgrade BC to version 1.80 --- lib/jopenssl/version.rb | 2 +- pom.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index 05f5275a..b5e7fcad 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,6 +1,6 @@ module JOpenSSL VERSION = '0.15.4.dev' - BOUNCY_CASTLE_VERSION = '1.79' + BOUNCY_CASTLE_VERSION = '1.80' end Object.class_eval do diff --git a/pom.xml b/pom.xml index 9c248a14..d68cabb6 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ DO NOT MODIFY - GENERATED CODE - 1.79 + 1.80 ${maven.test.skip} ${bc.versions} 3.0.2 @@ -77,22 +77,22 @@ DO NOT MODIFY - GENERATED CODE org.bouncycastle bcprov-jdk18on - 1.79 + 1.80 org.bouncycastle bcpkix-jdk18on - 1.79 + 1.80 org.bouncycastle bctls-jdk18on - 1.79 + 1.80 org.bouncycastle bcutil-jdk18on - 1.79 + 1.80 org.jruby From 9c9835778fb321756f73f517e3845081a233fe96 Mon Sep 17 00:00:00 2001 From: kares Date: Mon, 14 Apr 2025 13:00:41 +0200 Subject: [PATCH 03/16] [ci] test against latest jruby 9.4 + some variation --- .github/workflows/ci-test.yml | 5 ++++- .github/workflows/ci-test_provider.yml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index e2ed9a48..cdc4968e 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - ruby-version: [ jruby-9.4.8.0 ] + ruby-version: [ jruby-9.4.12.0 ] java-version: [ 8, 11, 21, 23 ] distribution: [ temurin ] include: @@ -38,6 +38,9 @@ jobs: - java-version: 17 distribution: oracle ruby-version: jruby-9.4.7.0 + - java-version: 21 + distribution: oracle + ruby-version: jruby-9.4.8.0 fail-fast: false steps: diff --git a/.github/workflows/ci-test_provider.yml b/.github/workflows/ci-test_provider.yml index 55dadb9d..42a17c83 100644 --- a/.github/workflows/ci-test_provider.yml +++ b/.github/workflows/ci-test_provider.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - ruby-version: [ jruby-9.4.8.0 ] + ruby-version: [ jruby-9.4.12.0 ] java-version: [ 21, 23 ] distribution: [ temurin, oracle ] include: From 97798e0f5a0f5001f66b43d33ac37db7399c43c6 Mon Sep 17 00:00:00 2001 From: kares Date: Mon, 14 Apr 2025 13:03:21 +0200 Subject: [PATCH 04/16] [ci] test against jruby-head (10.0 atm) --- .github/workflows/ci-test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index cdc4968e..c3c23334 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -41,6 +41,12 @@ jobs: - java-version: 21 distribution: oracle ruby-version: jruby-9.4.8.0 + - java-version: 21 + distribution: zulu + ruby-version: jruby-head # 10.0 + - java-version: 24 + distribution: corretto + ruby-version: jruby-head # 10.0 fail-fast: false steps: From b1fc5d645c0d90891b8865925ac1c15e3f15a055 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 7 May 2025 09:18:03 -0500 Subject: [PATCH 05/16] Verify hostname by default This was disabled years ago while we were adding support for it, but it has been working for some time now. This patch re-enables hostname verification by default. This addresses CVE-2025-46551 and GHSA-72qj-48g4-5xgx. Users can work around this by applying this patch manually to their own jruby-openssl and jruby installs, or by re-enabling hostname verification with the following code early in application boot: ```ruby require 'openssl' OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_hostname] = true ``` --- lib/openssl/ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index b77f0b52..991f05e3 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -20,7 +20,7 @@ class SSLContext DEFAULT_PARAMS = { # :nodoc: :min_version => OpenSSL::SSL::TLS1_VERSION, :verify_mode => OpenSSL::SSL::VERIFY_PEER, - :verify_hostname => nil, # TODO => true needs JRuby support to call verify_certificate_identity + :verify_hostname => true, :options => OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_COMPRESSION } From a2be52f3b69ff82b9dc886e19d77275701d48189 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 7 May 2025 11:15:42 -0500 Subject: [PATCH 06/16] Update version for 0.15.5 --- lib/jopenssl/version.rb | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index b5e7fcad..2f9c701d 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,5 +1,5 @@ module JOpenSSL - VERSION = '0.15.4.dev' + VERSION = '0.15.5.dev' BOUNCY_CASTLE_VERSION = '1.80' end diff --git a/pom.xml b/pom.xml index d68cabb6..f4bb1935 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ DO NOT MODIFY - GENERATED CODE 4.0.0 rubygems jruby-openssl - 0.15.4.dev-SNAPSHOT + 0.15.5.dev-SNAPSHOT gem JRuby OpenSSL JRuby-OpenSSL is an add-on gem for JRuby that emulates the Ruby OpenSSL native library. From 050856c2c72b852f225826af8e4fffe58ffedfe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Rosick=C3=BD?= Date: Mon, 9 Jun 2025 16:52:35 +0200 Subject: [PATCH 07/16] [test] remove a special test case (#331) --- src/test/ruby/test_cipher.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/test/ruby/test_cipher.rb b/src/test/ruby/test_cipher.rb index f5366aa9..1ef7c4e6 100644 --- a/src/test/ruby/test_cipher.rb +++ b/src/test/ruby/test_cipher.rb @@ -470,23 +470,19 @@ def test_encrypt_aes_cfb_20_incompatibility def test_encrypt_aes_256_cbc_modifies_buffer cipher = OpenSSL::Cipher.new("AES-256-CBC") - cipher.key = "a" * 32 cipher.encrypt + cipher.key = "a" * 32 buffer = '' actual = cipher.update('bar' * 10, buffer) - if jruby? - expected = "\xE6\xD3Y\fc\xEE\xBA\xB2*\x0Fr\xD1\xC2b\x03\xD0" - else - expected = "8\xA7\xBE\xB1\xAE\x88j\xCB\xA3\xE9j\x00\xD2W_\x91" - end + expected = "\xE6\xD3Y\fc\xEE\xBA\xB2*\x0Fr\xD1\xC2b\x03\xD0" assert_equal actual, expected assert_equal buffer, expected end def test_encrypt_aes_256_cbc_invalid_buffer cipher = OpenSSL::Cipher.new("AES-256-CBC") - cipher.key = "a" * 32 cipher.encrypt + cipher.key = "a" * 32 buffer = Object.new assert_raise(TypeError) { cipher.update('bar' * 10, buffer) } end From de0d96c189c29e4f7668e3943d678696e7d7e3c3 Mon Sep 17 00:00:00 2001 From: Tiago Date: Thu, 12 Jun 2025 14:07:51 +0100 Subject: [PATCH 08/16] [fix] OpenSSL::ASN1::ASN1Data encoding/decoding compatibility (#265) * to_der on ASN1Data should convert ruby strings into java strings before encoding * handle string in asn1data * unify how taggedobjects get decoded --- src/main/java/org/jruby/ext/openssl/ASN1.java | 100 +++++++++++++++--- src/test/ruby/test_asn1.rb | 30 ++++++ 2 files changed, 116 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jruby/ext/openssl/ASN1.java b/src/main/java/org/jruby/ext/openssl/ASN1.java index 8344b0d1..03a19e81 100644 --- a/src/main/java/org/jruby/ext/openssl/ASN1.java +++ b/src/main/java/org/jruby/ext/openssl/ASN1.java @@ -1071,15 +1071,14 @@ else if ( obj instanceof ASN1GraphicString ) { break; } - if (taggedObj.getTagClass() == BERTags.APPLICATION) { + try { final ASN1Sequence sequence = (ASN1Sequence) taggedObj.getBaseUniversal(false, SEQUENCE); @SuppressWarnings("unchecked") final RubyArray valArr = decodeObjects(context, ASN1, sequence.getObjects()); return ASN1.getClass("ASN1Data").newInstance(context, new IRubyObject[] { valArr, tag, tag_class }, Block.NULL_BLOCK); - } else { - IRubyObject val = decodeObject(context, ASN1, taggedObj.getBaseObject()); - final RubyArray valArr = runtime.newArray(val); - return ASN1.getClass("ASN1Data").newInstance(context, new IRubyObject[] { valArr, tag, tag_class }, Block.NULL_BLOCK); + } catch (IllegalStateException e) { + IRubyObject val = decodeObject(context, ASN1, taggedObj.getBaseObject()).callMethod(context, "value"); + return ASN1.getClass("ASN1Data").newInstance(context, new IRubyObject[] { val, tag, tag_class }, Block.NULL_BLOCK); } } @@ -1357,6 +1356,10 @@ boolean isEOC() { return "EndOfContent".equals( getClassBaseName() ); } + boolean isUniversal(final ThreadContext context) { + return "ASN1Data".equals(getClassBaseName()) && getTagClass(context) == 0; + } + IRubyObject tagging() { return getInstanceVariable("@tagging"); } @@ -1395,22 +1398,51 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) { final IRubyObject value = callMethod(context, "value"); if (value instanceof RubyArray) { + // Cruby openssl joins elements of array and casts to string final RubyArray arr = (RubyArray) value; - assert ! arr.isEmpty(); + StringBuilder values = new StringBuilder(); ASN1EncodableVector vec = new ASN1EncodableVector(); + for (final IRubyObject obj : arr.toJavaArray()) { - ASN1Encodable data = ((ASN1Data) obj).toASN1(context); - if ( data == null ) break; - vec.add( data ); + if (obj instanceof ASN1Data) { + ASN1Encodable data = ((ASN1Data) obj).toASN1(context); + if (data == null) break; + vec.add(data); + } else { + final IRubyObject string = obj.checkStringType(); + if (string instanceof RubyString) { + values.append(string.asJavaString()); + } else { + throw context.runtime.newTypeError( + "no implicit conversion of " + obj.getMetaClass().getBaseName() + " into String"); + } + } } - return new DERTaggedObject(isExplicitTagging(), tag, new DERSequence(vec)); - } - if (!(value instanceof ASN1Data)) { - throw new UnsupportedOperationException("toASN1 " + inspect() + " value: " + value.inspect() + " (" + value.getMetaClass() + ")"); + if (vec.size() > 0) { + // array of asn1 objects as value + return new DERTaggedObject(isExplicitTagging(), tag, new DERSequence(vec)); + } + + // array of strings as value (default) + return new DERTaggedObject(isExplicitTagging(), tagClass, tag, + new DERGeneralString(values.toString())); + } else if (value instanceof ASN1Data) { + return new DERTaggedObject(isExplicitTagging(), tagClass, tag, ((ASN1Data) value).toASN1(context)); + } else if (value instanceof RubyObject) { + final IRubyObject string = value.checkStringType(); + if (string instanceof RubyString) { + return new DERTaggedObject(isExplicitTagging(), tagClass, tag, + new DERGeneralString(string.asJavaString())); + } else { + throw context.runtime.newTypeError( + "no implicit conversion of " + value.getMetaClass().getBaseName() + " into String"); + } + } else { + throw context.runtime.newTypeError( + "no implicit conversion of " + value.getMetaClass().getBaseName() + " into String"); } - return new DERTaggedObject(isExplicitTagging(), tagClass, tag, ((ASN1Data) value).toASN1(context)); } @JRubyMethod @@ -1426,6 +1458,41 @@ public IRubyObject to_der(final ThreadContext context) { byte[] toDER(final ThreadContext context) throws IOException { if ( isEOC() ) return new byte[] { 0x00, 0x00 }; + + if (isUniversal(context)) { + // handstitch conversion + final java.io.ByteArrayOutputStream out = new ByteArrayOutputStream(); + final IRubyObject value = callMethod(context, "value"); + + final byte[] valueBytes; + if (value instanceof RubyArray) { + final RubyArray arr = (RubyArray) value; + final java.io.ByteArrayOutputStream valueOut = new ByteArrayOutputStream(); + + for (final IRubyObject obj : arr.toJavaArray()) { + final IRubyObject string = value.checkStringType(); + if (string instanceof RubyString) { + valueOut.write(((RubyString) string).getBytes()); + } else { + throw context.runtime.newTypeError( + "no implicit conversion of " + obj.getMetaClass().getBaseName() + " into String"); + } + } + valueBytes = valueOut.toByteArray(); + } else { + final IRubyObject string = value.checkStringType(); + if (string instanceof RubyString) { + valueBytes = ((RubyString) string).getBytes(); + } else { + throw context.runtime.newTypeError( + "no implicit conversion of " + value.getMetaClass().getBaseName() + " into String"); + } + } + out.write(getTag(context)); + out.write(valueBytes.length); + out.write(valueBytes); + return out.toByteArray(); + } return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER); } @@ -1619,6 +1686,11 @@ boolean isEOC() { return false; } + @Override + boolean isUniversal(final ThreadContext context) { + return false; + } + private boolean isNull() { return "Null".equals(getMetaClass().getRealClass().getBaseName()); } diff --git a/src/test/ruby/test_asn1.rb b/src/test/ruby/test_asn1.rb index 6f8eb955..9544fc73 100644 --- a/src/test/ruby/test_asn1.rb +++ b/src/test/ruby/test_asn1.rb @@ -251,6 +251,36 @@ def test_null } end + def test_encode_asn1_data + ai = OpenSSL::ASN1::ASN1Data.new(i = "bla", 0, :APPLICATION) + ai2 = OpenSSL::ASN1.decode(ai.to_der) + assert_equal :APPLICATION, ai2.tag_class + assert_equal 0, ai2.tag + assert_equal i, ai2.value + + ai = OpenSSL::ASN1::ASN1Data.new(i = "bla", 4, :UNIVERSAL) + ai2 = OpenSSL::ASN1.decode(ai.to_der) + assert_equal :UNIVERSAL, ai2.tag_class + assert_equal 4, ai2.tag + assert_equal i, ai2.value + + ai = OpenSSL::ASN1::ASN1Data.new(i = ["bla"], 0, :APPLICATION) + ai2 = OpenSSL::ASN1.decode(ai.to_der) + assert_equal :APPLICATION, ai2.tag_class + assert_equal 0, ai2.tag + assert_equal "bla", ai2.value + + ai = OpenSSL::ASN1::ASN1Data.new(i = ["bla", "bla"], 0, :APPLICATION) + ai2 = OpenSSL::ASN1.decode(ai.to_der) + assert_equal :APPLICATION, ai2.tag_class + assert_equal 0, ai2.tag + assert_equal "blabla", ai2.value + + assert_raise(ArgumentError) { OpenSSL::ASN1::ASN1Data.new(1).to_der } + assert_raise("no implicit conversion of Integer into String") { OpenSSL::ASN1::ASN1Data.new(1, 0, :APPLICATION).to_der } + assert_raise("no implicit conversion of Integer into String") { OpenSSL::ASN1::ASN1Data.new(1, 0, :CONTEXT_SPECIFIC).to_der } + end + def test_encode_nil #Primitives raise TypeError, Constructives NoMethodError From 9dd7159dec67d57e31615a217a0a57f64d8e060d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Fri, 25 Jul 2025 02:13:20 -1000 Subject: [PATCH 09/16] Fix `OpenSSL::X509::CRL#to_pem` when building CRL from scratch (#333) When building an CRL from scratch, the `crl` member variable has no value, and when calling `to_pem` on the object, the following value is returned instead of the actual CRL: ``` -----BEGIN X509 CRL----- MAA= -----END X509 CRL----- ``` The function `getCRL()` return the `crl` member variable if it is non-null, and generate the CRL and store it in this variable otherwise. It seems adequate to use this getter function rather than accessing the member variable directly. Fixes #163 --- src/main/java/org/jruby/ext/openssl/X509CRL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jruby/ext/openssl/X509CRL.java b/src/main/java/org/jruby/ext/openssl/X509CRL.java index df9e1453..b5baa2b8 100644 --- a/src/main/java/org/jruby/ext/openssl/X509CRL.java +++ b/src/main/java/org/jruby/ext/openssl/X509CRL.java @@ -304,7 +304,7 @@ public IRubyObject initialize_copy(final IRubyObject obj) { public IRubyObject to_pem(final ThreadContext context) { StringWriter writer = new StringWriter(); try { - PEMInputOutput.writeX509CRL(writer, crl); + PEMInputOutput.writeX509CRL(writer, getCRL()); return RubyString.newString(context.runtime, writer.getBuffer()); } catch (IOException e) { From 8c8232e1e82dcd83fab742d594ffc8acc3111c01 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 17:19:30 +0200 Subject: [PATCH 10/16] [test] regenerate ca+cert setup for testing --- src/test/ruby/x509/demoCA/index.txt | 1 + src/test/ruby/x509/demoCA/index.txt.attr.old | 1 - src/test/ruby/x509/demoCA/index.txt.old | 1 - src/test/ruby/x509/demoCA/serial | 2 +- src/test/ruby/x509/demoCA/serial.old | 1 - src/test/ruby/x509/newcert.pem | 135 +++++++++++-------- src/test/ruby/x509/newkey.pem | 30 ----- src/test/ruby/x509/newreq.key | 52 +++++++ src/test/ruby/x509/newreq.pem | 40 +++--- 9 files changed, 158 insertions(+), 105 deletions(-) delete mode 100644 src/test/ruby/x509/demoCA/index.txt.attr.old delete mode 100644 src/test/ruby/x509/demoCA/index.txt.old delete mode 100644 src/test/ruby/x509/demoCA/serial.old delete mode 100644 src/test/ruby/x509/newkey.pem create mode 100644 src/test/ruby/x509/newreq.key diff --git a/src/test/ruby/x509/demoCA/index.txt b/src/test/ruby/x509/demoCA/index.txt index ee9978dd..8cb8f4c2 100644 --- a/src/test/ruby/x509/demoCA/index.txt +++ b/src/test/ruby/x509/demoCA/index.txt @@ -1,2 +1,3 @@ V 270420110921Z 7FE0E82756779BDA39DFF3AEE16916DE984FFD24 unknown /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=demo.ca V 250420111357Z 7FE0E82756779BDA39DFF3AEE16916DE984FFD25 unknown /C=AU/ST=None/O=JRuby Dev Team/OU=JOSSL/CN=jruby.org +V 260725151415Z 7FE0E82756779BDA39DFF3AEE16916DE984FFD26 unknown /C=CS/ST=Bohemia/O=JRuby/OU=JOSSL/CN=jruby.org diff --git a/src/test/ruby/x509/demoCA/index.txt.attr.old b/src/test/ruby/x509/demoCA/index.txt.attr.old deleted file mode 100644 index 8f7e63a3..00000000 --- a/src/test/ruby/x509/demoCA/index.txt.attr.old +++ /dev/null @@ -1 +0,0 @@ -unique_subject = yes diff --git a/src/test/ruby/x509/demoCA/index.txt.old b/src/test/ruby/x509/demoCA/index.txt.old deleted file mode 100644 index 2c79c486..00000000 --- a/src/test/ruby/x509/demoCA/index.txt.old +++ /dev/null @@ -1 +0,0 @@ -V 270420110921Z 7FE0E82756779BDA39DFF3AEE16916DE984FFD24 unknown /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=demo.ca diff --git a/src/test/ruby/x509/demoCA/serial b/src/test/ruby/x509/demoCA/serial index 0b14c109..e06d064f 100644 --- a/src/test/ruby/x509/demoCA/serial +++ b/src/test/ruby/x509/demoCA/serial @@ -1 +1 @@ -7FE0E82756779BDA39DFF3AEE16916DE984FFD26 +7FE0E82756779BDA39DFF3AEE16916DE984FFD27 diff --git a/src/test/ruby/x509/demoCA/serial.old b/src/test/ruby/x509/demoCA/serial.old deleted file mode 100644 index f82eb9f3..00000000 --- a/src/test/ruby/x509/demoCA/serial.old +++ /dev/null @@ -1 +0,0 @@ -7FE0E82756779BDA39DFF3AEE16916DE984FFD25 diff --git a/src/test/ruby/x509/newcert.pem b/src/test/ruby/x509/newcert.pem index b9309714..f49f6fc8 100644 --- a/src/test/ruby/x509/newcert.pem +++ b/src/test/ruby/x509/newcert.pem @@ -2,78 +2,101 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 7f:e0:e8:27:56:77:9b:da:39:df:f3:ae:e1:69:16:de:98:4f:fd:25 + 7f:e0:e8:27:56:77:9b:da:39:df:f3:ae:e1:69:16:de:98:4f:fd:26 Signature Algorithm: sha256WithRSAEncryption Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=demo.ca Validity - Not Before: Apr 20 11:13:57 2024 GMT - Not After : Apr 20 11:13:57 2025 GMT - Subject: C=AU, ST=None, O=JRuby Dev Team, OU=JOSSL, CN=jruby.org + Not Before: Jul 25 15:14:15 2025 GMT + Not After : Jul 25 15:14:15 2026 GMT + Subject: C=CS, ST=Bohemia, O=JRuby, OU=JOSSL, CN=jruby.org Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + Public-Key: (4096 bit) Modulus: - 00:b3:83:9b:f8:e7:5d:25:cd:ac:dc:19:aa:46:ce: - ff:66:30:b0:9d:da:1f:24:32:b1:9a:82:fc:bb:d0: - 4a:38:96:fe:b3:64:51:92:a0:11:5c:51:4f:f3:dc: - d9:29:5e:25:ed:8b:17:35:6b:b2:01:0a:10:ce:ea: - 4d:67:7f:b3:a1:12:6d:dd:6e:31:11:12:a7:56:98: - 4a:89:87:e7:e8:4d:23:aa:6a:28:6e:4f:b4:73:9b: - 0f:6d:e7:32:5b:50:46:0e:06:5d:96:e4:5b:23:b1: - b3:f3:a4:9b:12:ff:a1:7c:1a:ef:76:6a:b0:52:bf: - 03:1a:b8:7c:07:8d:f8:53:15:80:e5:37:38:05:01: - 01:ef:25:d7:86:ea:1d:79:0f:fc:00:35:0d:7d:4d: - 9c:9f:d8:d6:2e:42:df:72:13:8a:49:3a:59:ae:a7: - d9:a1:a7:92:74:ca:c1:ab:c5:47:04:ad:b1:3f:69: - 02:a4:09:e0:94:bb:80:54:81:e6:8a:bc:1c:db:db: - 60:87:66:77:8d:f9:2b:bf:74:ba:dc:3d:5a:20:fa: - 5a:fd:50:4b:a7:43:f3:e2:11:04:31:0a:42:69:1f: - 4c:6d:db:71:a0:5b:1a:e8:70:2c:69:3e:e9:ce:ce: - 4e:c1:83:3c:39:cb:2b:8d:45:72:0a:3d:b8:74:c8: - f7:a9 + 00:b7:f5:4e:f1:f1:11:58:b5:b7:10:e2:e6:0a:b6: + 25:f7:e3:bc:e0:c8:ce:aa:ac:8c:6d:98:8c:f3:e8: + 04:f6:83:75:77:c4:1f:61:f1:a4:de:38:cf:e6:b0: + da:4a:85:d7:0a:14:06:dd:2a:ff:48:1c:a3:76:e5: + ef:95:8c:20:8d:49:37:14:8c:c9:9b:fe:92:85:82: + aa:f9:9a:28:b1:21:33:6f:85:6e:80:9d:cf:17:79: + b1:6d:d5:95:34:e2:52:72:be:6b:2b:f7:3c:69:d5: + 11:2e:27:64:f5:98:5d:1b:40:4e:80:a2:3c:38:22: + de:a8:e9:2b:e3:b2:54:c7:4d:1e:51:5c:1b:49:1a: + 46:47:4f:53:02:0e:c1:f5:40:11:03:e3:3e:c7:dd: + 54:91:09:cb:d7:60:4f:89:36:60:23:f9:cc:be:ad: + 0d:cc:60:67:e8:4c:06:8a:4c:4c:fc:6f:2a:99:9d: + 23:56:19:cd:ce:78:4e:4f:a8:69:e7:dd:35:b4:7f: + a1:f2:3a:88:ed:a2:74:2e:83:e8:99:14:56:9f:45: + 60:43:0d:83:31:b6:f6:ff:1d:45:49:fa:91:6c:a2: + 4b:44:40:ae:77:85:55:0d:8a:cf:75:ca:75:dc:a9: + 2b:55:2b:c2:d6:15:7c:02:dd:22:fa:6b:6e:ed:fe: + 18:64:82:17:78:b2:82:5a:31:ef:ab:25:c6:1f:d5: + a2:bc:4b:bf:88:2c:5f:98:64:00:ae:96:a9:5f:a1: + 22:3a:37:9d:7d:44:5d:d4:f3:d6:b2:c5:cf:5a:50: + 5b:3f:b1:72:e5:87:2f:d1:44:37:35:c4:ef:bc:f2: + 8f:c4:87:f8:64:65:5f:69:24:94:9e:ea:9d:d2:c0: + 1b:2d:ea:17:0f:14:71:1e:8b:8d:a6:48:5b:1e:d7: + 95:48:3a:fd:c7:c1:3b:a0:e4:06:d6:38:15:13:0a: + 15:df:0d:69:86:c2:90:1e:9d:a8:d7:56:b3:88:2d: + ca:98:8f:88:d5:fa:6c:52:3a:bf:03:5a:59:53:46: + fe:6a:68:cb:9e:b3:f0:4f:b9:f5:01:2d:75:4a:00: + e8:3b:d6:25:4b:d3:4d:4a:fc:59:f2:b5:d0:60:92: + c0:23:a0:36:cb:eb:97:c3:68:80:b5:93:94:68:56: + 73:66:25:25:c9:44:3f:56:b3:5a:50:d6:80:b6:8f: + db:93:a2:c3:9e:b6:8c:70:48:1b:c5:92:44:2b:ca: + ab:59:c0:93:57:03:21:19:68:67:f9:6a:0d:4b:95: + fa:76:00:17:78:f4:b0:2f:77:18:92:81:59:16:f7: + d1:cf:40:14:bd:b9:6d:5e:50:dc:dc:67:21:fd:8b: + 32:3b:0d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - A4:5D:C3:4D:EA:92:65:AE:F2:66:60:9B:E2:4C:EC:78:FD:CA:E9:A2 + 79:85:4B:D2:26:9F:7B:14:09:A0:94:05:85:69:22:FC:AB:92:A8:6D X509v3 Authority Key Identifier: 8F:B4:94:C8:7F:CB:EF:00:89:B2:F6:C1:BE:44:4B:1C:12:54:3B:28 Signature Algorithm: sha256WithRSAEncryption Signature Value: - 3a:cf:7b:5c:f4:46:9b:dc:77:38:68:1d:a9:48:f0:01:68:9a: - 9f:f7:34:4a:63:8a:d1:50:d6:18:a7:b3:ad:13:9f:46:01:e6: - 89:7d:81:de:5f:49:1f:76:18:ec:23:07:fb:a2:3d:e0:eb:29: - 67:12:2a:c0:ea:a6:51:69:37:81:49:c0:6e:6e:73:db:7d:09: - 92:db:fe:5b:9f:3f:a0:3e:96:1c:2a:40:bc:9b:73:3b:38:59: - a4:e4:6b:07:a6:d3:3c:fd:48:07:fc:d8:3d:d4:e9:91:20:fd: - d5:a7:98:4f:ea:8b:ab:39:fa:f3:95:e0:cd:af:85:0b:85:ed: - 72:ad:e0:74:83:88:b1:1f:1e:a7:13:56:4a:b5:6a:c5:6d:81: - cd:e7:69:f2:b9:49:f0:50:ae:21:ff:12:af:2f:c4:2a:23:43: - c3:73:64:f6:1a:b7:0f:9a:7b:3a:1f:93:6d:e3:30:23:00:dc: - b1:f1:83:22:a2:e6:6a:b0:e5:89:6a:71:f6:76:c3:4d:1f:c7: - 4a:75:75:8a:85:6e:b6:11:89:9d:59:3a:ac:6a:bc:df:4e:ad: - 1e:db:4c:81:66:64:b8:8a:86:be:0e:f2:10:3e:94:63:e3:e5: - 97:9a:b1:24:6f:ea:ff:09:06:9c:e8:f7:38:e1:7e:32:5e:55: - ae:39:5b:fa + 73:c9:bd:4e:ea:79:53:c1:ea:6a:9f:69:f8:59:89:a7:5c:64: + eb:20:ae:93:78:a9:5d:01:8d:3d:dc:9a:b9:5f:7b:18:77:a5: + 55:1a:ad:cd:9a:24:4e:28:e7:33:55:e4:64:a4:e3:64:45:3f: + 6c:26:16:f0:56:c0:e8:de:0e:8c:27:aa:a1:0c:8a:74:9d:2c: + 3b:cc:5c:aa:91:67:e7:59:e4:83:79:eb:c5:71:06:c2:64:4f: + 96:27:26:7b:61:5f:59:99:88:91:bf:93:c4:4a:29:f3:63:a4: + e6:c0:54:d2:50:d3:9c:10:83:45:d9:f2:22:47:f6:79:0a:26: + 04:b8:26:bf:61:41:a6:9c:17:4f:dd:3c:51:7a:87:cc:c6:92: + 2c:7d:b8:95:41:e9:91:8c:5d:d9:ca:88:a6:fb:1a:43:c4:92: + 19:89:61:e0:b8:73:c4:94:38:b7:0c:d9:cb:28:16:c0:02:65: + 51:96:1c:d9:16:64:e4:30:1e:d2:6e:3c:1a:e6:b5:16:38:5d: + 3f:92:96:21:95:bf:ac:30:c3:85:3e:ee:8a:31:c7:8d:c5:19: + 08:1b:7c:74:c3:18:84:2f:e8:31:c2:c5:7b:da:8a:56:6f:51: + 6f:c8:e0:91:fb:d6:09:41:42:34:89:36:80:88:e3:80:29:21: + 26:ea:ad:d8 -----BEGIN CERTIFICATE----- -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 +iOOAKSEm6q3Y -----END CERTIFICATE----- diff --git a/src/test/ruby/x509/newkey.pem b/src/test/ruby/x509/newkey.pem deleted file mode 100644 index b16ccc14..00000000 --- a/src/test/ruby/x509/newkey.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIptI6IvNIXLQCAggA -MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGgu1pMy79jcBIIEyEOSty89/eCt -JNyk3QHvg254W31IfjwiUwHE8WfzXXrQJxAxaFKwsMLZQ1B5E85C1Hvaol1Ufr7E -okC8Erm0UDBF9GsBhKBHclgh97clvqsA1oxdnIwJmn/0W7fZbhI3o3/34iTZvEmy -C5gQ9h4mgpi1RXBKofu2HYp9YFSu+8xz/A75U8k33oCTIcBh8l3XUpf1iczB9KUN -Np1e+HKfSkbyT60GrnOiRGtJXn7X67OHLNIMjB902zccW0ByA0ZTB4tv/Fbvohcw -L3bytY+CixS/DBlvGVX+JT7NxOpRTVBeXpLiv5GG2zi+uL8EFHfzqblM8OW+l5j7 -SiJeQ0pCvIeKT3cIgzVIWpO3FNzQ0ucP4AjvFvKOXkyey/aLpmi9cJ9m8uPvJSuN -wNtzfxVXdQ1bgbos2GmFQmriSWSinagKWWm1zsqElNlQue9jOdRK44HosllgGd1Y -GuneH+LFAGEBCefxA3zO00uACPlqhY5HO545YrYkaHGJ6eMtjojb+P8rsNvJ9c4e -8/IDIzVPo7zDSTuFiZFFGCU3GQSKjOrDfLb+cNdHfqMAjiyEjmeYkdrkxanKFyBv -Tc1Cpi5EicpXHK/Lfu77r64Hg06cItIkgJh8P+m5/X0JU/c2Ynqq8paXs4eqqt7t -q6t1okvy7kOpDEQ/UyLcMqKtPmnJa68bpJDkbTuWXCexFrQhnYyIxuHJtRVKp/oz -mBsUexZpHp8PtCCB4dbyU+AuADZO1GMS8BJWBGh3I4/kDGnZ2C8UpSQ+UfbaOtu/ -hMoNT21jvadogd4by1DeFkYBjIQxwPoSaZfTRkcwu2NozJJlZT0f3MtMlntLJrR9 -wMQMviv/uEJGcQUJ4oNMHjkkK2N5pqZ2f8GOLuRm7xuHSAHBKjN9XHshoxjTiOPn -DmplHX+vaRr+J9GAfmkg/jr2u4fGeFp+Y08HPbAfpvlxHuR6HWcDBm0vhK4qt0rx -vBxsZs2hQr6m43eCPgJG92PDD/o831/6IMLsW/kowrDiSBfIVo9LFvPteFilA+Bd -QVUh1CMnxqeWsfswzK38EwcHXxz1dLdL/aH6z7OkdAUzHaFaY8VZnEfECQfdHgJB -Yk2NEuatOsQynTcCenXz0H86gYQT3mftneVWgM2AXDpTEBQ5XeU4iWUbVt0/s3ho -tEYfcNUEacYVaQ9d5M4sylMIPm6Hx/MGx1zddgAw637w8dPWipsQbR860qW1uaZJ -oQrIRIPq/n/W7kkM5XBZmAoLLPjvCzjtF6FGXiW8yrkN0HF1hs/nK50McorbqRYy -MGV+jEHpzTE2CWPyTFjXn2idSJz4nX0D6IgjIbM9zB67cXHwsUMnGpVOMgaqB4en -weaUWRUzau6mPa2o3eM5UHcSbbwXVDtHKIne6pZqpA6XATBPmRQujWA5GqWQ9PyO -6r2DTrVRh1aYKsXl0EyX0OBPkB6C1ULoY+X4gT8riEX8mZSCn4aM6TYheCdhAHwo -Zya5au7bxE+oimNrMuVDPRuGAizvox/ZCi9NgFbFxUFm8xC62g1mru0FU1y3thmO -sAigENLt0iA15L0miimBnEjUbksIx7Ug0zr2VwpVe3knDo4o4FWBOOUPet6hg+lU -oCkOpwuVQReqT6UE7feIvw== ------END ENCRYPTED PRIVATE KEY----- diff --git a/src/test/ruby/x509/newreq.key b/src/test/ruby/x509/newreq.key new file mode 100644 index 00000000..5d8bd70a --- /dev/null +++ b/src/test/ruby/x509/newreq.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +eOI3Ol45btJyhVklr2SRTkiDakayaw== +-----END PRIVATE KEY----- diff --git a/src/test/ruby/x509/newreq.pem b/src/test/ruby/x509/newreq.pem index 75f86afd..fdaf840a 100644 --- a/src/test/ruby/x509/newreq.pem +++ b/src/test/ruby/x509/newreq.pem @@ -1,17 +1,27 @@ -----BEGIN CERTIFICATE REQUEST----- -MIICtDCCAZwCAQAwWTELMAkGA1UEBhMCQVUxDTALBgNVBAgMBE5vbmUxFzAVBgNV -BAoMDkpSdWJ5IERldiBUZWFtMQ4wDAYDVQQLDAVKT1NTTDESMBAGA1UEAwwJanJ1 -Ynkub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs4Ob+OddJc2s -3BmqRs7/ZjCwndofJDKxmoL8u9BKOJb+s2RRkqARXFFP89zZKV4l7YsXNWuyAQoQ -zupNZ3+zoRJt3W4xERKnVphKiYfn6E0jqmoobk+0c5sPbecyW1BGDgZdluRbI7Gz -86SbEv+hfBrvdmqwUr8DGrh8B434UxWA5Tc4BQEB7yXXhuodeQ/8ADUNfU2cn9jW -LkLfchOKSTpZrqfZoaeSdMrBq8VHBK2xP2kCpAnglLuAVIHmirwc29tgh2Z3jfkr -v3S63D1aIPpa/VBLp0Pz4hEEMQpCaR9MbdtxoFsa6HAsaT7pzs5OwYM8OcsrjUVy -Cj24dMj3qQIDAQABoBYwFAYJKoZIhvcNAQkCMQcMBUpSdWJ5MA0GCSqGSIb3DQEB -CwUAA4IBAQCc5UgGQGiJPKbYoBQ/ro0hejCX6rvyTmjpJwJTBX07JtcQmLDpQZkt -kfwPOw/nCQS1q+QcO7gvjyULYCFuAJ+Ff+kyCYEMv4uQ7Xkc6U9sQSzdCSaXp6ob -yR6boc26ioI9FZrwyGxEeu6XGlQ2ihRKjfx0sbdIoHKiSsWk9AZZXT3SgxtcnKDh -zbMx1NAvQ8dO7mn1bWIYi5zfWjTIMGTrxD2GT3GuybWP/VXEJi5Nz9idfeN2dpPq -yJH1mKTJZv/7ZRAF9kQwuDO5gtVuRzR3qSENpjOSmpKEn1hm8o1966APLV6SJZC4 -fsyzgvHK5Tsu+I5bj1CLmLjNppvQkaTu +MIIEmDCCAoACAQAwUzELMAkGA1UEBhMCQ1MxEDAOBgNVBAgMB0JvaGVtaWExDjAM +BgNVBAoMBUpSdWJ5MQ4wDAYDVQQLDAVKT1NTTDESMBAGA1UEAwwJanJ1Ynkub3Jn +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt/VO8fERWLW3EOLmCrYl +9+O84MjOqqyMbZiM8+gE9oN1d8QfYfGk3jjP5rDaSoXXChQG3Sr/SByjduXvlYwg +jUk3FIzJm/6ShYKq+ZoosSEzb4VugJ3PF3mxbdWVNOJScr5rK/c8adURLidk9Zhd +G0BOgKI8OCLeqOkr47JUx00eUVwbSRpGR09TAg7B9UARA+M+x91UkQnL12BPiTZg +I/nMvq0NzGBn6EwGikxM/G8qmZ0jVhnNznhOT6hp5901tH+h8jqI7aJ0LoPomRRW +n0VgQw2DMbb2/x1FSfqRbKJLRECud4VVDYrPdcp13KkrVSvC1hV8At0i+mtu7f4Y +ZIIXeLKCWjHvqyXGH9WivEu/iCxfmGQArpapX6EiOjedfURd1PPWssXPWlBbP7Fy +5Ycv0UQ3NcTvvPKPxIf4ZGVfaSSUnuqd0sAbLeoXDxRxHouNpkhbHteVSDr9x8E7 +oOQG1jgVEwoV3w1phsKQHp2o11aziC3KmI+I1fpsUjq/A1pZU0b+amjLnrPwT7n1 +AS11SgDoO9YlS9NNSvxZ8rXQYJLAI6A2y+uXw2iAtZOUaFZzZiUlyUQ/VrNaUNaA +to/bk6LDnraMcEgbxZJEK8qrWcCTVwMhGWhn+WoNS5X6dgAXePSwL3cYkoFZFvfR +z0AUvbltXlDc3Gch/YsyOw0CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQAXleZN +2nEv3LxF6LQMkJxUH1jPM0xbQR49xU92nVr6sKnmONf1ZuguRGXwsnQMpdfaKCNh +k222mxeiKokjNRGr/sMiRrulLZnAOzVVOeJ4GiGhlkpR0dSCkMzhOS79q+uUc8TP +IwI5ZCoTlkapA7YfoJQbZwdUjWx2VrrRH+IWNzFf0n8mqCxs+BAOOdCSFTlXHOxE +NcFCzXT+mjPCMdiKLs4LKeRN0kasDuKQQHVgi6JTRdsucDwx3KzanvHV2aSmOFbP +uV5XQ5lWlNZtA2npsd7lcoPK3NJ56Kw5OXExR7HTU8ktZ1+WgjT5Q0ICSpiG4n5T +tAzhkj/IIxal5ZJy5x86MNtmdwekt8vlJLF8DCnB+MieP4prOaIkLviEzwk8VnDY +btHNT51y8gKqlsaygrjTtpOKMbYcixFDWs/c5qmsZfD0NSz8ZQg9HoBhiKlagDeT +fg3YU5Kw0MT6nbVgW5HZ9mfw4a3eBqZA5gJVx7tWSvutFzFk0lor2wxw4ZkCA88O +71QUJ3EgM2O71WdbdFaL6kGmAZz8qgKDHXbqi77eW8akHFv83DYjEMkogvKddryQ +B/TUvKt+mMewPWSuvHFcnjIf3NvzBuEleTswPu2b6FWJZZ13cIeIQmPCXX+GOZjj +ZIH34u+GXytujPEAQ1kyNtuQaVQ23FAFxXO+sw== -----END CERTIFICATE REQUEST----- From e1b03ab0d94b048de7b56a88e53977d920509d81 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 17:23:03 +0200 Subject: [PATCH 11/16] [ci] add jruby 10.0.1 + bump 9.4 target --- .github/workflows/ci-test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index c3c23334..fcea30ed 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - ruby-version: [ jruby-9.4.12.0 ] + ruby-version: [ jruby-9.4.13.0 ] java-version: [ 8, 11, 21, 23 ] distribution: [ temurin ] include: @@ -35,16 +35,16 @@ jobs: - java-version: 11 distribution: zulu ruby-version: jruby-9.4.5.0 - - java-version: 17 - distribution: oracle - ruby-version: jruby-9.4.7.0 - java-version: 21 distribution: oracle ruby-version: jruby-9.4.8.0 - java-version: 21 - distribution: zulu - ruby-version: jruby-head # 10.0 + distribution: temurin + ruby-version: jruby-10.0.1.0 - java-version: 24 + distribution: zulu + ruby-version: jruby-10.0.1.0 + - java-version: 21 distribution: corretto ruby-version: jruby-head # 10.0 fail-fast: false From cf64b705b00a31433fb5e8dfdb5e1f6fb4b8b3da Mon Sep 17 00:00:00 2001 From: Tiago Date: Fri, 25 Jul 2025 18:29:11 +0300 Subject: [PATCH 12/16] Improving completeness of ASN1 encoding/decoding (#335) * uncommenting the last assertion of the application specific der test * adding the basicdata tests from upstream ruby-openssl excluding already the one that I know that I can't solve, as BC does not allow tag > 31 for UNIVERSAL tag class * inlining getConstructiveTag logic, expand on the rest of the information in the tag segment the tag segment also contains info about whether the payload is for a constructed DER, and whether it's indefinite length; this info was buried in the method, with no easy way to piggyback on, so it was easier to inline the logic (only used here anyway), and propagate the rest of the information, which allows setting the indefinite_length ivar for ASN1Data objects it also raises exceptions where it couldn't (or shouldn't?) * fixing encoding of arrays in ASN1Data structures as well as dealing with EOC empty arrays on asn1data are encoded to BERSequences, which fixed some corner cases associated with asn1data EOC isn't supported OOTB by bouncycastle, so these have to be ignored in the ASN1 part, since there's no way to use DERTaggedObject some of the logic to add the EOC bytes are inlined based on the implemented from bouncycastle, which does not allow to compose on anything, as all entities are private and unextendable * do not allow encoding asn1data with indefinite_length set and a value which is not an array this is the behaviour from upstream * making the EndOfContent class a subclass of ASN1Data this is what upstream does * fixed initialization of Primitive the logic was unaligned with upstream (see ruby rewrite here: https://github.com/ruby/openssl/blob/master/lib/openssl/asn1.rb\#L107C40-L122) * rewrote isEOC as a function of its data ruby allows EOC objects to be built via ASN1Data initialization, so one has to use the info of tag and tag class instead * implement logic to der-encode objects at the base class since ruby does not have abstract classes, instances of root/intermediate classes may be instantiated, and args will determine how those objects really have to be handled this follows the logic of upstream, which implements der-encode at the base class by outsourcing to specific impls based on ivar state * loading EndOfContent class correctly so overrides are correctly loaded * adding basic constructive tests from upstream commenting out the one I could only half port, as no BC parser supports random tagged objects --- src/main/java/org/jruby/ext/openssl/ASN1.java | 529 +++++++++++------- src/test/ruby/test_asn1.rb | 121 ++-- 2 files changed, 369 insertions(+), 281 deletions(-) diff --git a/src/main/java/org/jruby/ext/openssl/ASN1.java b/src/main/java/org/jruby/ext/openssl/ASN1.java index 03a19e81..3e7417e4 100644 --- a/src/main/java/org/jruby/ext/openssl/ASN1.java +++ b/src/main/java/org/jruby/ext/openssl/ASN1.java @@ -41,7 +41,6 @@ import java.util.WeakHashMap; import org.bouncycastle.asn1.*; - import org.jruby.Ruby; import org.jruby.RubyArray; import org.jruby.RubyBignum; @@ -704,6 +703,10 @@ public static void createASN1(final Ruby runtime, final RubyModule OpenSSL, fina Constructive.addReadWriteAttribute(context, "tagging"); Constructive.defineAnnotatedMethods(Constructive.class); + final ObjectAllocator eocAllocator = EndOfContent.ALLOCATOR; + RubyClass EndOfContent = ASN1.defineClassUnder("EndOfContent", _ASN1Data, eocAllocator); + EndOfContent.defineAnnotatedMethods(EndOfContent.class); + ASN1.defineClassUnder("Boolean", Primitive, primitiveAllocator); // OpenSSL::ASN1::Boolean <=> value is a Boolean ASN1.defineClassUnder("Integer", Primitive, primitiveAllocator); // OpenSSL::ASN1::Integer <=> value is a Number ASN1.defineClassUnder("Null", Primitive, primitiveAllocator); // OpenSSL::ASN1::Null <=> value is always nil @@ -728,9 +731,6 @@ public static void createASN1(final Ruby runtime, final RubyModule OpenSSL, fina ASN1.defineClassUnder("UTCTime", Primitive, primitiveAllocator); // OpenSSL::ASN1::UTCTime <=> value is a Time ASN1.defineClassUnder("GeneralizedTime", Primitive, primitiveAllocator); // OpenSSL::ASN1::GeneralizedTime <=> value is a Time - ASN1.defineClassUnder("EndOfContent", _ASN1Data, asn1DataAllocator). // OpenSSL::ASN1::EndOfContent <=> value is always nil - defineAnnotatedMethods(EndOfContent.class); - ASN1.defineClassUnder("ObjectId", Primitive, primitiveAllocator). defineAnnotatedMethods(ObjectId.class); @@ -1166,19 +1166,62 @@ private BytesInputStream(final ByteList bytes) { private static IRubyObject decodeImpl(final ThreadContext context, final RubyModule ASN1, final BytesInputStream in) throws IOException, IllegalArgumentException { + final byte[] asn1 = in.bytes(); + int offset = in.offset(); + final int tag = asn1[offset] & 0xFF; + + if ( ( tag & BERTags.CONSTRUCTED ) == 0 ) { + return decodeObject(context, ASN1, readObject(in)); + } + // NOTE: need to handle OpenSSL::ASN1::Constructive wrapping by hand : - final Integer tag = getConstructiveTag(in.bytes(), in.offset()); - IRubyObject decoded = decodeObject(context, ASN1, readObject( in )); - if ( tag != null ) { // OpenSSL::ASN1::Constructive.new( arg ) : - if ( tag.intValue() == SEQUENCE ) { - //type = "Sequence"; // got a OpenSSL::ASN1::Sequence already : - return Constructive.setInfiniteLength(context, decoded); + int tagNo = tag & 0x1f; + if (tagNo == 0x1f) + { + tagNo = 0; + int b = asn1[ ++offset ]; + + // X.690-0207 8.1.2.4.2 + // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." + if ((b & 0x7f) == 0) // Note: -1 will pass + { + throw new IOException("corrupted stream - invalid high tag number found"); + } + + while ((b >= 0) && ((b & 0x80) != 0)) + { + tagNo |= (b & 0x7f); + tagNo <<= 7; + b = asn1[ ++offset ]; + } + + if (b < 0) + { + throw new IOException("EOF found inside tag value."); } - if ( tag.intValue() == SET ) { - //type = "Set"; // got a OpenSSL::ASN1::Set already : - return Constructive.setInfiniteLength(context, decoded); + + tagNo |= (b & 0x7f); + } + final int length = asn1[ ++offset ] & 0xFF; + final boolean isIndefiniteLength = length == 0x80; + IRubyObject decoded; + + decoded = decodeObject(context, ASN1, readObject(in)); + + final boolean isUniversal = ((ASN1Data) decoded).isUniversal(context); + + if (isIndefiniteLength) { + if (tagNo == BERTags.SEQUENCE || tagNo == BERTags.SET) { + return ASN1Data.setInfiniteLength(context, decoded); + } else if (isUniversal) { + decoded = Constructive.newInfiniteLength(context, context.runtime.newArray(decoded), tagNo); + } else { + if (decoded instanceof ASN1Data) { + return ASN1Data.setInfiniteLength(context, decoded); + } else { + decoded = ASN1Data.newInfiniteLength(context, context.runtime.newArray(decoded), tagNo, ((ASN1Data) decoded).tagClass()); + } } - return Constructive.newInfiniteConstructive(context, "Constructive", context.runtime.newArray(decoded), tag); } return decoded; } @@ -1235,89 +1278,6 @@ private static org.bouncycastle.asn1.ASN1Primitive readObject(final InputStream return new ASN1InputStream(bytes).readObject(); } - // NOTE: BC's ASNInputStream internals "reinvented" a bit : - private static Integer getConstructiveTag(final byte[] asn1, int offset) { - final int tag = asn1[ offset ] & 0xFF; - if ( ( tag & BERTags.CONSTRUCTED ) != 0 ) { // isConstructed - // - // calculate tag number - // - // readTagNumber(asn1, ++offset, tag) : - int tagNo = tag & 0x1f; - // - // with tagged object tag number is bottom 5 bits, or stored at the start of the content - // - if (tagNo == 0x1f) - { - tagNo = 0; - - int b = asn1[ ++offset ]; //s.read(); - - // X.690-0207 8.1.2.4.2 - // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." - if ((b & 0x7f) == 0) // Note: -1 will pass - { - return null; //throw new IOException("corrupted stream - invalid high tag number found"); - } - - while ((b >= 0) && ((b & 0x80) != 0)) - { - tagNo |= (b & 0x7f); - tagNo <<= 7; - b = asn1[ ++offset ]; //s.read(); - } - - if (b < 0) - { - return null; //throw new EOFException("EOF found inside tag value."); - } - - tagNo |= (b & 0x7f); - } - - // - // calculate length - // - final int length = asn1[ ++offset ] & 0xFF; - - if ( length == 0x80 ) { - // return -1; // indefinite-length encoding - } - else { - return null; - } - - if ((tag & BERTags.APPLICATION) != 0) { - //return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject(); - } - - if ((tag & BERTags.TAGGED) != 0) { - //return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject(); - } - - //System.out.println(" tagNo = 0x" + Integer.toHexString(tagNo)); - // TODO There are other tags that may be constructed (e.g. BIT_STRING) - switch (tagNo) { - case BERTags.SEQUENCE : - //return new BERSequenceParser(sp).getLoadedObject(); - return Integer.valueOf( SEQUENCE ); //return "Sequence"; - case BERTags.SET : - //return new BERSetParser(sp).getLoadedObject(); - return Integer.valueOf( SET ); //return "Set"; - case BERTags.OCTET_STRING : - return Integer.valueOf( OCTET_STRING ); - //return new BEROctetStringParser(sp).getLoadedObject(); - case BERTags.EXTERNAL : - //return new DERExternalParser(sp).getLoadedObject(); - default: - return Integer.valueOf( 0 ); //return "Constructive"; - //throw new IOException("unknown BER object encountered"); - } - } - - return null; - } - public static class ASN1Data extends RubyObject { private static final long serialVersionUID = 6117598347932209839L; @@ -1340,9 +1300,38 @@ public IRubyObject initialize(final ThreadContext context, this.callMethod(context, "tag=", tag); this.callMethod(context, "value=", value); this.callMethod(context, "tag_class=", tag_class); + this.setInstanceVariable("@indefinite_length", context.runtime.getFalse()); return this; } + static ASN1Data newInfiniteLength(final ThreadContext context, + final IRubyObject value, final int defaultTag, final IRubyObject tagClass) { + final Ruby runtime = context.runtime; + + final RubyClass klass = _ASN1(runtime).getClass("ASN1Data"); + final ASN1Data self = new Constructive(runtime, klass); + + ASN1Data.newInfiniteLengthImpl(context, self, value, defaultTag, tagClass); + return self; + } + + static void newInfiniteLengthImpl(final ThreadContext context, final ASN1Data self, final IRubyObject value, final int defaultTag, final IRubyObject tagClass) { + self.setInstanceVariable("@tag", context.runtime.newFixnum(defaultTag)); + self.setInstanceVariable("@value", value); + self.setInstanceVariable("@tag_class", tagClass); + self.setInstanceVariable("@tagging", context.nil); + + setInfiniteLength(context, self); + } + + static ASN1Data setInfiniteLength(final ThreadContext context, final IRubyObject constructive) { + final ASN1Data instance = ((ASN1Data) constructive); + final IRubyObject value = instance.value(context); + value.callMethod(context, "<<", EndOfContent.newInstance(context)); + instance.setInstanceVariable("@indefinite_length", context.runtime.getTrue()); + return instance; + } + private void checkTag(final Ruby runtime, final IRubyObject tag, final IRubyObject tagClass) { if ( ! (tagClass instanceof RubySymbol) ) { throw newASN1Error(runtime, "invalid tag class"); @@ -1352,18 +1341,30 @@ private void checkTag(final Ruby runtime, final IRubyObject tag, final IRubyObje } } - boolean isEOC() { - return "EndOfContent".equals( getClassBaseName() ); + private boolean isConstructive() { + return "Constructive".equals(getMetaClass().getRealClass().getBaseName()); + } + + boolean isInfiniteLength() { + return getInstanceVariable("@indefinite_length").isTrue(); + } + + boolean isEOC(final ThreadContext context) { + return getTag(context) == 0 && isUniversal((context)); } boolean isUniversal(final ThreadContext context) { - return "ASN1Data".equals(getClassBaseName()) && getTagClass(context) == 0; + return getTagClass(context) == BERTags.UNIVERSAL; } IRubyObject tagging() { return getInstanceVariable("@tagging"); } + IRubyObject tagClass() { + return getInstanceVariable("@tag_class"); + } + boolean isExplicitTagging() { return ! isImplicitTagging(); } boolean isImplicitTagging() { return true; } @@ -1420,17 +1421,18 @@ final ASN1TaggedObject toASN1TaggedObject(final ThreadContext context) { } } - if (vec.size() > 0) { - // array of asn1 objects as value - return new DERTaggedObject(isExplicitTagging(), tag, new DERSequence(vec)); + if (values.length() > 0) { + return new DERTaggedObject(isExplicitTagging(), tagClass, tag, new DERGeneralString(values.toString())); + } else { + // array of strings as value (default) + return new DERTaggedObject(isExplicitTagging(), tagClass, tag, new BERSequence(vec)); } - - // array of strings as value (default) - return new DERTaggedObject(isExplicitTagging(), tagClass, tag, - new DERGeneralString(values.toString())); } else if (value instanceof ASN1Data) { return new DERTaggedObject(isExplicitTagging(), tagClass, tag, ((ASN1Data) value).toASN1(context)); } else if (value instanceof RubyObject) { + if (isEOC(context)) { + return null; + } final IRubyObject string = value.checkStringType(); if (string instanceof RubyString) { return new DERTaggedObject(isExplicitTagging(), tagClass, tag, @@ -1457,43 +1459,147 @@ public IRubyObject to_der(final ThreadContext context) { } byte[] toDER(final ThreadContext context) throws IOException { - if ( isEOC() ) return new byte[] { 0x00, 0x00 }; + if ( + ("ASN1Data".equals(getClassBaseName()) && isUniversal(context)) + ) { + return toDERInternal(context, isConstructive(), isInfiniteLength(), value(context)); + } + + final ASN1Primitive prim = toASN1(context).toASN1Primitive(); - if (isUniversal(context)) { - // handstitch conversion + if (isInfiniteLength()) { + final java.io.ByteArrayOutputStream tagOut = new ByteArrayOutputStream(); + final java.io.ByteArrayOutputStream contentOut = new ByteArrayOutputStream(); final java.io.ByteArrayOutputStream out = new ByteArrayOutputStream(); - final IRubyObject value = callMethod(context, "value"); + prim.encodeTo(contentOut, ASN1Encoding.DER); + writeDERIdentifier(getTag(context), getTagClass(context) | BERTags.CONSTRUCTED, tagOut); - final byte[] valueBytes; - if (value instanceof RubyArray) { - final RubyArray arr = (RubyArray) value; - final java.io.ByteArrayOutputStream valueOut = new ByteArrayOutputStream(); + byte[] tagOutArr = tagOut.toByteArray(); + byte[] contentOutArr = contentOut.toByteArray(); - for (final IRubyObject obj : arr.toJavaArray()) { - final IRubyObject string = value.checkStringType(); - if (string instanceof RubyString) { - valueOut.write(((RubyString) string).getBytes()); - } else { - throw context.runtime.newTypeError( - "no implicit conversion of " + obj.getMetaClass().getBaseName() + " into String"); - } - } - valueBytes = valueOut.toByteArray(); - } else { - final IRubyObject string = value.checkStringType(); - if (string instanceof RubyString) { - valueBytes = ((RubyString) string).getBytes(); + out.write(tagOutArr); + out.write(0x80); + out.write(contentOutArr, tagOutArr.length + 1, contentOutArr.length - tagOutArr.length - 1); + out.write(0x00); + out.write(0x00); + + return out.toByteArray(); + } else { + return prim.getEncoded(ASN1Encoding.DER); + } + } + + byte[] toDERInternal(final ThreadContext context, boolean isConstructed, boolean isIndefiniteLength, final IRubyObject value) throws IOException { + // handstitch conversion + final java.io.ByteArrayOutputStream out = new ByteArrayOutputStream(); + + final byte[] valueBytes; + + if (value == null) { + valueBytes = new byte[] {}; + } else if (value instanceof RubyArray) { + final IRubyObject[] arr = ((RubyArray) value).toJavaArray(); + final java.io.ByteArrayOutputStream valueOut = new ByteArrayOutputStream(); + + + for ( int i = 0; i < arr.length; i++ ) { + final IRubyObject obj = arr[i]; + + if (obj instanceof EndOfContent && i != arr.length - 1) { + throw newASN1Error(context.runtime, "illegal EOC octets in value"); + } + + final byte[] objBytes; + + if (obj.respondsTo("to_der")) { + objBytes = ((RubyString) obj.callMethod(context, "to_der")).getBytes(); } else { - throw context.runtime.newTypeError( - "no implicit conversion of " + value.getMetaClass().getBaseName() + " into String"); + objBytes = ((RubyString) obj.convertToString()).getBytes(); } + + valueOut.write(objBytes); + } + + if (isIndefiniteLength) { + if (arr.length != 0 && !(arr[arr.length - 1] instanceof EndOfContent)) { + // indefinite length object with no EOC object in the array. + valueOut.write(0x00); + valueOut.write(0x00); + } + } + + valueBytes = valueOut.toByteArray(); + } else { + if (isIndefiniteLength) { + throw newASN1Error( + context.runtime, + "indefinite length form cannot be used with primitive encoding" + ); + } + + if (value instanceof RubyString) { + valueBytes = ((RubyString) value).getBytes(); + } else { + valueBytes = value.convertToString().getBytes(); } - out.write(getTag(context)); - out.write(valueBytes.length); - out.write(valueBytes); - return out.toByteArray(); } - return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER); + + int flags = getTagClass(context); + if (isConstructed) { + flags |= BERTags.CONSTRUCTED; + } + // tag + writeDERIdentifier(getTag(context), flags, out); + if (isIndefiniteLength) { + out.write(0x80); + } else { + writeDERLength(valueBytes.length, out); + } + // value + out.write(valueBytes); + + return out.toByteArray(); + } + + void writeDERIdentifier(int tag, int flags, java.io.ByteArrayOutputStream out) { + if (tag > 0x1f) { + byte[] stack = new byte[6]; + int pos = stack.length; + + stack[--pos] = (byte)(tag & 0x7F); + while (tag > 127) + { + tag >>>= 7; + stack[--pos] = (byte)(tag & 0x7F | 0x80); + } + + stack[--pos] = (byte)(flags | 0x1F); + + out.write(stack, pos, stack.length - pos); + } else { + out.write(flags | tag); + } + } + + void writeDERLength(int length, java.io.ByteArrayOutputStream out) { + if (length < 128) { + out.write(length); + } else { + byte[] stack = new byte[5]; + int pos = stack.length; + + do + { + stack[--pos] = (byte)length; + length >>>= 8; + } + while (length != 0); + + int count = stack.length - pos; + stack[--pos] = (byte)(0x80 | count); + + out.write(stack, pos, count - pos); + } } protected IRubyObject defaultTag() { @@ -1545,11 +1651,20 @@ static void printArray(final PrintStream out, final int indent, final RubyArray } - public static class EndOfContent { + public static class EndOfContent extends ASN1Data { - private EndOfContent() {} + static ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new EndOfContent(runtime, klass); + } + }; - @JRubyMethod(visibility = Visibility.PRIVATE) + public EndOfContent(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + + @JRubyMethod(required = 0, optional = 0, visibility = Visibility.PRIVATE) public static IRubyObject initialize(final ThreadContext context, final IRubyObject self) { final Ruby runtime = context.runtime; self.getInstanceVariables().setInstanceVariable("@tag", runtime.newFixnum(0)); @@ -1563,6 +1678,17 @@ static IRubyObject newInstance(final ThreadContext context) { return klass.newInstance(context, Block.NULL_BLOCK); } + @Override + boolean isImplicitTagging() { + IRubyObject tagging = tagging(); + if ( tagging.isNil() ) return true; + return "IMPLICIT".equals( tagging.toString() ); + } + + @Override + byte[] toDER(final ThreadContext context) throws IOException { + return toDERInternal(context, false, false, null); + } } public static class Primitive extends ASN1Data { @@ -1620,12 +1746,20 @@ static void initializeImpl(final ThreadContext context, if ( tag.isNil() ) throw newASN1Error(runtime, "must specify tag number"); - if ( tagging.isNil() ) tagging = runtime.newSymbol("EXPLICIT"); - if ( ! (tagging instanceof RubySymbol) ) { - throw newASN1Error(runtime, "invalid tag default"); + if ( tagging.isNil()) { + if (tag_class.isNil()) { + tag_class = runtime.newSymbol("UNIVERSAL"); + } + } else { + if (!(tagging instanceof RubySymbol)) { + throw newASN1Error(runtime, "invalid tagging method"); + } + + if (tag_class.isNil()) { + tag_class = runtime.newSymbol("CONTEXT_SPECIFIC"); + } } - if ( tag_class.isNil() ) tag_class = runtime.newSymbol("CONTEXT_SPECIFIC"); if ( ! (tag_class instanceof RubySymbol) ) { throw newASN1Error(runtime, "invalid tag class"); } @@ -1682,12 +1816,7 @@ boolean isImplicitTagging() { } @Override - boolean isEOC() { - return false; - } - - @Override - boolean isUniversal(final ThreadContext context) { + boolean isEOC(final ThreadContext context) { return false; } @@ -1697,6 +1826,21 @@ private boolean isNull() { @Override byte[] toDER(final ThreadContext context) throws IOException { + Class type = typeClass( getMetaClass() ); + final IRubyObject value = value(context); + + if ( type == null ) { + RubyString string; + + if (value instanceof RubyString) { + string = (RubyString) value; + } else { + string = value.convertToString(); + } + + return toDERInternal(context, false, false, string); + } + return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER); } @@ -1711,16 +1855,6 @@ ASN1Encodable toASN1(final ThreadContext context) { private ASN1Encodable toASN1Primitive(final ThreadContext context) { Class type = typeClass( getMetaClass() ); - if ( type == null ) { - final int tag = getTag(context); - if ( tag == 0 ) return null; // TODO pass EOC to BC ? - if ( isExplicitTagging() ) type = typeClass( tag ); - if ( type == null ) { - throw new IllegalArgumentException( - "no type for: " + getMetaClass() + " or tag: " + getTag(context) - ); - } - } final IRubyObject val = value(context); if ( type == ASN1ObjectIdentifier.class ) { @@ -1857,27 +1991,15 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a return this; } - static Constructive newInfiniteConstructive(final ThreadContext context, - final String type, final IRubyObject value, final int defaultTag) { + static Constructive newInfiniteLength(final ThreadContext context, + final IRubyObject value, final int defaultTag) { final Ruby runtime = context.runtime; - final RubyClass klass = _ASN1(context.runtime).getClass(type); + final RubyClass klass = _ASN1(context.runtime).getClass("Constructive"); final Constructive self = new Constructive(runtime, klass); - self.setInstanceVariable("@tag", runtime.newFixnum(defaultTag)); - self.setInstanceVariable("@value", value); - self.setInstanceVariable("@tag_class", runtime.newSymbol("UNIVERSAL")); - self.setInstanceVariable("@tagging", context.nil); - - return setInfiniteLength(context, self); - } - - static Constructive setInfiniteLength(final ThreadContext context, final IRubyObject constructive) { - final Constructive instance = ((Constructive) constructive); - final IRubyObject value = instance.value(context); - value.callMethod(context, "<<", EndOfContent.newInstance(context)); - instance.setInstanceVariable("@indefinite_length", context.runtime.getTrue()); - return instance; + ASN1Data.newInfiniteLengthImpl(context, self, value, defaultTag, runtime.newSymbol("UNIVERSAL")); + return self; } private boolean rawConstructive() { @@ -1892,10 +2014,6 @@ private boolean isSet() { return "Set".equals( getClassBaseName() ); } - private boolean isInfiniteLength() { - return getInstanceVariable("@indefinite_length").isTrue(); - } - private boolean isTagged() { return !tagging().isNil(); } @@ -1941,22 +2059,19 @@ ASN1Encodable toASN1(final ThreadContext context) { @Override @JRubyMethod public IRubyObject to_der(final ThreadContext context) { - if ( rawConstructive() ) { // MRI compatibility - if ( ! isInfiniteLength() && ! super.value(context).isNil() ) { - final Ruby runtime = context.runtime; - throw newASN1Error(runtime, "Constructive shall only be used with indefinite length"); - } - } return super.to_der(context); } @Override byte[] toDER(final ThreadContext context) throws IOException { - if ( isInfiniteLength() ) { - if ( isSequence() ) { + final int tagNo = getTag(context); + final boolean isIndefiniteLength = isInfiniteLength(); + + if ( isIndefiniteLength ) { + if ( isSequence() || tagNo == SEQUENCE ) { return sequenceToDER(context); } - if ( isSet() ) { + if ( isSet() || tagNo == SET) { return setToDER(context); } // "raw" Constructive @@ -1965,12 +2080,18 @@ byte[] toDER(final ThreadContext context) throws IOException { return octetStringToDER(context); case BIT_STRING: return bitStringToDER(context); - case SEQUENCE: - return sequenceToDER(context); - case SET: - return setToDER(context); } - throw new UnsupportedOperationException( this.inspect().toString() ); + return toDERInternal(context, true, isInfiniteLength(), value(context)); + } + + if (isEOC(context)) { + return toDERInternal(context, true, isIndefiniteLength, null); + } + + Class type = typeClass( getMetaClass() ); + + if ( type == null ) { + return toDERInternal(context, true, isIndefiniteLength, valueAsArray(context)); } return super.toDER(context); @@ -2022,19 +2143,23 @@ private byte[] setToDER(final ThreadContext context) throws IOException { private ASN1EncodableVector toASN1EncodableVector(final ThreadContext context) { final ASN1EncodableVector vec = new ASN1EncodableVector(); final IRubyObject value = value(context); - final RubyArray val; + final RubyArray val = valueAsArray(context); + for ( int i = 0; i < val.size(); i++ ) { + if ( addEntry(context, vec, val.entry(i)) ) break; + } + return vec; + } + + private RubyArray valueAsArray(final ThreadContext context) { + final IRubyObject value = value(context); if (value instanceof RubyArray ) { - val = (RubyArray) value; + return (RubyArray) value; } else { if (!value.respondsTo("to_a")) { throw context.runtime.newTypeError("can't convert " + value.getMetaClass().getName() + " into Array"); } - val = (RubyArray) value.callMethod(context, "to_a"); - } - for ( int i = 0; i < val.size(); i++ ) { - if ( addEntry(context, vec, val.entry(i)) ) break; + return (RubyArray) value.callMethod(context, "to_a"); } - return vec; } public ASN1Primitive toASN1Primitive() { @@ -2067,7 +2192,7 @@ private static boolean addEntry(final ThreadContext context, final ASN1Encodable } else if ( entry instanceof ASN1Data ) { final ASN1Data data = ( (ASN1Data) entry ); - if ( data.isEOC() ) return true; + if ( data.isEOC(context) ) return true; vec.add( data.toASN1(context) ); } else { diff --git a/src/test/ruby/test_asn1.rb b/src/test/ruby/test_asn1.rb index 9544fc73..0cc59e27 100644 --- a/src/test/ruby/test_asn1.rb +++ b/src/test/ruby/test_asn1.rb @@ -509,66 +509,37 @@ def test_generalizedtime end def test_basic_asn1data - # TODO: Import Issue - # Java::JavaLang::ClassCastException: - # class org.jruby.RubyString cannot be cast to class org.jruby.ext.openssl.ASN1$ASN1Data - # org.jruby.ext.openssl.ASN1$ASN1Data.toASN1TaggedObject(ASN1.java:1408) - # org.jruby.ext.openssl.ASN1$ASN1Data.toASN1(ASN1.java:1383) - # org.jruby.ext.openssl.ASN1$ASN1Data.toDER(ASN1.java:1424) - # org.jruby.ext.openssl.ASN1$ASN1Data.to_der(ASN1.java:1414) - #encode_test B(%w{ 00 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 0, :UNIVERSAL) - #encode_test B(%w{ 01 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 1, :UNIVERSAL) - #encode_decode_test B(%w{ 41 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 1, :APPLICATION) - #encode_decode_test B(%w{ 81 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 1, :CONTEXT_SPECIFIC) - #encode_decode_test B(%w{ C1 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 1, :PRIVATE) - # TODO: Import Issue - # OpenSSL::ASN1::ASN1Error: tag number for :UNIVERSAL too large - # org/jruby/RubyClass.java:942:in `new' - #encode_decode_test B(%w{ 1F 20 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 32, :UNIVERSAL) - #encode_decode_test B(%w{ 1F C0 20 00 }), OpenSSL::ASN1::ASN1Data.new(B(%w{}), 8224, :UNIVERSAL) - # TODO: Import Issue (same as start of this test) - # Java::JavaLang::ClassCastException: - # class org.jruby.RubyString cannot be cast to class org.jruby.ext.openssl.ASN1$ASN1Data - # org.jruby.ext.openssl.ASN1$ASN1Data.toASN1TaggedObject(ASN1.java:1408) - # org.jruby.ext.openssl.ASN1$ASN1Data.toASN1(ASN1.java:1383) - # org.jruby.ext.openssl.ASN1$ASN1Data.toDER(ASN1.java:1424) - # org.jruby.ext.openssl.ASN1$ASN1Data.to_der(ASN1.java:1414) - #encode_decode_test B(%w{ 41 02 AB CD }), OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 1, :APPLICATION) - #encode_decode_test B(%w{ 41 81 80 } + %w{ AB CD } * 64), OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD } * 64), 1, :APPLICATION) - #encode_decode_test B(%w{ 41 82 01 00 } + %w{ AB CD } * 128), OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD } * 128), 1, :APPLICATION) - #encode_decode_test B(%w{ 61 00 }), OpenSSL::ASN1::ASN1Data.new([], 1, :APPLICATION) - #obj = OpenSSL::ASN1::ASN1Data.new([OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 2, :PRIVATE)], 1, :APPLICATION) - #obj.indefinite_length = true - #encode_decode_test B(%w{ 61 80 C2 02 AB CD 00 00 }), obj - #obj = OpenSSL::ASN1::ASN1Data.new([ - # OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 2, :PRIVATE), - # OpenSSL::ASN1::EndOfContent.new - #], 1, :APPLICATION) - #obj.indefinite_length = true - #encode_test B(%w{ 61 80 C2 02 AB CD 00 00 }), obj - #obj = OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 1, :UNIVERSAL) - #obj.indefinite_length = true - # TODO: Import Issue - # expected but was <# expected but was <"\x01\x01\xFF"> - #encode_test B(%w{ 01 00 }), OpenSSL::ASN1::Primitive.new(B(%w{}), 1, nil, :UNIVERSAL) - # <"\x81\x00"> expected but was <"\x01\x01\xFF"> - #encode_test B(%w{ 81 00 }), OpenSSL::ASN1::Primitive.new(B(%w{}), 1, nil, :CONTEXT_SPECIFIC) - # <"\x01\x02\xAB\xCD"> expected but was <"\x01\x01\xFF"> - #encode_test B(%w{ 01 02 AB CD }), OpenSSL::ASN1::Primitive.new(B(%w{ AB CD }), 1) - # exception was expected but none was thrown. - #assert_raise(TypeError) { OpenSSL::ASN1::Primitive.new([], 1).to_der } + encode_test B(%w{ 00 00 }), OpenSSL::ASN1::Primitive.new(B(%w{}), 0) + encode_test B(%w{ 01 00 }), OpenSSL::ASN1::Primitive.new(B(%w{}), 1, nil, :UNIVERSAL) + encode_test B(%w{ 81 00 }), OpenSSL::ASN1::Primitive.new(B(%w{}), 1, nil, :CONTEXT_SPECIFIC) + encode_test B(%w{ 01 02 AB CD }), OpenSSL::ASN1::Primitive.new(B(%w{ AB CD }), 1) + assert_raise(TypeError) { OpenSSL::ASN1::Primitive.new([], 1).to_der } prim = OpenSSL::ASN1::Integer.new(50) assert_equal false, prim.indefinite_length @@ -582,27 +553,19 @@ def test_basic_primitive # def test_basic_constructed - #octet_string = OpenSSL::ASN1::OctetString.new(B(%w{ AB CD })) - # TODO: Import Issue - # OpenSSL::ASN1::ASN1Error: Constructive shall only be used with indefinite length - #encode_test B(%w{ 20 00 }), OpenSSL::ASN1::Constructive.new([], 0) - #encode_test B(%w{ 21 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :UNIVERSAL) - #encode_test B(%w{ A1 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :CONTEXT_SPECIFIC) - #encode_test B(%w{ 21 04 04 02 AB CD }), OpenSSL::ASN1::Constructive.new([octet_string], 1) - # Java::JavaLang::UnsupportedOperationException: - # #], - # @tag_class=:CONTEXT_SPECIFIC, @tagging=:EXPLICIT, @indefinite_length=true> - # org.jruby.ext.openssl.ASN1$Constructive.toDER(ASN1.java:1881) - # org.jruby.ext.openssl.ASN1$ASN1Data.to_der(ASN1.java:1414) - # org.jruby.ext.openssl.ASN1$Constructive.to_der(ASN1.java:1858) - #obj = OpenSSL::ASN1::Constructive.new([octet_string], 1) - #obj.indefinite_length = true - #encode_decode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj - # (see above) Java::JavaLang::UnsupportedOperationException - #obj = OpenSSL::ASN1::Constructive.new([octet_string, OpenSSL::ASN1::EndOfContent.new], 1) - #obj.indefinite_length = true - #encode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj + octet_string = OpenSSL::ASN1::OctetString.new(B(%w{ AB CD })) + encode_test B(%w{ 20 00 }), OpenSSL::ASN1::Constructive.new([], 0) + encode_test B(%w{ 21 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :UNIVERSAL) + encode_test B(%w{ A1 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :CONTEXT_SPECIFIC) + encode_test B(%w{ 21 04 04 02 AB CD }), OpenSSL::ASN1::Constructive.new([octet_string], 1) + obj = OpenSSL::ASN1::Constructive.new([octet_string], 1) + obj.indefinite_length = true + encode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj + # TODO: BC doesn't support decoding indef constructive asn1s from unsupported tag types. + # encode_decode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj + obj = OpenSSL::ASN1::Constructive.new([octet_string, OpenSSL::ASN1::EndOfContent.new], 1) + obj.indefinite_length = true + encode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj end def test_constructive @@ -1295,7 +1258,7 @@ def test_decode_application_specific assert_equal 'o=Telstra', asn1_data.value[1].value assert_equal OpenSSL::ASN1::ASN1Data, asn1_data.value[2].class assert_equal :CONTEXT_SPECIFIC, asn1_data.value[2].tag_class -# assert_equal 'ess', asn1_data.value[2].value + assert_equal 'ess', asn1_data.value[2].value # assert_equal raw, asn1.to_der end From 67490b5d11f7a33c0971c269ec4f7f6f32716551 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 17:32:41 +0200 Subject: [PATCH 13/16] [deps] upgrade BC to version 1.81 --- lib/jopenssl/version.rb | 2 +- pom.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index 2f9c701d..727c6c94 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,6 +1,6 @@ module JOpenSSL VERSION = '0.15.5.dev' - BOUNCY_CASTLE_VERSION = '1.80' + BOUNCY_CASTLE_VERSION = '1.81' end Object.class_eval do diff --git a/pom.xml b/pom.xml index f4bb1935..aa720a18 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ DO NOT MODIFY - GENERATED CODE - 1.80 + 1.81 ${maven.test.skip} ${bc.versions} 3.0.2 @@ -77,22 +77,22 @@ DO NOT MODIFY - GENERATED CODE org.bouncycastle bcprov-jdk18on - 1.80 + 1.81 org.bouncycastle bcpkix-jdk18on - 1.80 + 1.81 org.bouncycastle bctls-jdk18on - 1.80 + 1.81 org.bouncycastle bcutil-jdk18on - 1.80 + 1.81 org.jruby From 889bd6dc6b749adbf5d70733cdf04291931193a9 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 17:39:08 +0200 Subject: [PATCH 14/16] [release] prepare for 0.15.5 --- History.md | 22 ++++++++++++++++++++++ lib/jopenssl/version.rb | 2 +- pom.xml | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 33f645a4..d81fc667 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,25 @@ +## 0.15.5 + +* [deps] upgrade BC to version 1.81 +* Improving completeness of ASN1 encoding/decoding (#335) +* [fix] OpenSSL::X509::CRL#to_pem when building CRL from scratch (#163) +* [fix] OpenSSL::ASN1::ASN1Data encoding/decoding compatibility (#265) + +## 0.15.4 + +* Verify hostname by default + +This addresses **CVE-2025-46551** and **GHSA-72qj-48g4-5xgx**. + +Users can work around this by applying this patch manually to their +own jruby-openssl and jruby installs, or by re-enabling hostname +verification with the following code early in application boot: +```ruby +require 'openssl' + +OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_hostname] = true +``` + ## 0.15.3 * [fix] keep curve name when group is set into another key diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index 727c6c94..56ac497b 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,5 +1,5 @@ module JOpenSSL - VERSION = '0.15.5.dev' + VERSION = '0.15.5' BOUNCY_CASTLE_VERSION = '1.81' end diff --git a/pom.xml b/pom.xml index aa720a18..79e5e9f6 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ DO NOT MODIFY - GENERATED CODE 4.0.0 rubygems jruby-openssl - 0.15.5.dev-SNAPSHOT + 0.15.5 gem JRuby OpenSSL JRuby-OpenSSL is an add-on gem for JRuby that emulates the Ruby OpenSSL native library. From 9ad979b5a26ceea2438e9262aba47f446a748394 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 17:42:35 +0200 Subject: [PATCH 15/16] [release] update to next dev SNAPSHOT --- lib/jopenssl/version.rb | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jopenssl/version.rb b/lib/jopenssl/version.rb index 56ac497b..d5766787 100644 --- a/lib/jopenssl/version.rb +++ b/lib/jopenssl/version.rb @@ -1,5 +1,5 @@ module JOpenSSL - VERSION = '0.15.5' + VERSION = '0.15.6.dev' BOUNCY_CASTLE_VERSION = '1.81' end diff --git a/pom.xml b/pom.xml index 79e5e9f6..3881bc14 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ DO NOT MODIFY - GENERATED CODE 4.0.0 rubygems jruby-openssl - 0.15.5 + 0.15.6.dev-SNAPSHOT gem JRuby OpenSSL JRuby-OpenSSL is an add-on gem for JRuby that emulates the Ruby OpenSSL native library. From 2585b09ec9508e5bbf45d87943c791796f8cf107 Mon Sep 17 00:00:00 2001 From: kares Date: Fri, 25 Jul 2025 20:02:57 +0200 Subject: [PATCH 16/16] [fix] compat with JRuby 10 initialize_copy changes --- src/main/java/org/jruby/ext/openssl/BN.java | 1 + src/main/java/org/jruby/ext/openssl/PKeyDH.java | 1 + src/main/java/org/jruby/ext/openssl/PKeyDSA.java | 1 + src/main/java/org/jruby/ext/openssl/PKeyEC.java | 1 + src/main/java/org/jruby/ext/openssl/PKeyRSA.java | 1 + src/main/java/org/jruby/ext/openssl/SSLContext.java | 1 + src/main/java/org/jruby/ext/openssl/X509Attribute.java | 1 + src/main/java/org/jruby/ext/openssl/X509Extension.java | 1 + 8 files changed, 8 insertions(+) diff --git a/src/main/java/org/jruby/ext/openssl/BN.java b/src/main/java/org/jruby/ext/openssl/BN.java index ca393b4f..1e61d463 100644 --- a/src/main/java/org/jruby/ext/openssl/BN.java +++ b/src/main/java/org/jruby/ext/openssl/BN.java @@ -171,6 +171,7 @@ private static BigInteger initBigIntegerBase(final Ruby runtime, RubyString str, } } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject that) { super.initialize_copy(that); diff --git a/src/main/java/org/jruby/ext/openssl/PKeyDH.java b/src/main/java/org/jruby/ext/openssl/PKeyDH.java index 159ef832..d05dea65 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyDH.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyDH.java @@ -101,6 +101,7 @@ public PKeyDH(Ruby runtime, RubyClass clazz) { super(runtime, clazz); } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this; diff --git a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java index be364fdf..83c6d1fd 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java @@ -117,6 +117,7 @@ public PKeyDSA(Ruby runtime, RubyClass type, DSAPrivateKey privKey, DSAPublicKey private transient volatile BigInteger dsa_q; private transient volatile BigInteger dsa_g; + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this; diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 099bc75f..e698e425 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -403,6 +403,7 @@ private void setGroup(final Group group) { this.curveName = this.group.getCurveName(); } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this; diff --git a/src/main/java/org/jruby/ext/openssl/PKeyRSA.java b/src/main/java/org/jruby/ext/openssl/PKeyRSA.java index 5cc9059c..7e0e28bb 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyRSA.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyRSA.java @@ -148,6 +148,7 @@ public PKeyRSA(Ruby runtime, RubyClass type, RSAPrivateCrtKey privKey, RSAPublic private transient volatile BigInteger rsa_dmq1; private transient volatile BigInteger rsa_iqmp; + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this; diff --git a/src/main/java/org/jruby/ext/openssl/SSLContext.java b/src/main/java/org/jruby/ext/openssl/SSLContext.java index 07804365..3fc0ef5a 100644 --- a/src/main/java/org/jruby/ext/openssl/SSLContext.java +++ b/src/main/java/org/jruby/ext/openssl/SSLContext.java @@ -324,6 +324,7 @@ public IRubyObject initialize(IRubyObject[] args) { return initializeImpl(); } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override // NOTE: instance variables (no internal state) on #dup public IRubyObject initialize_copy(IRubyObject original) { SSLContext copy = (SSLContext) super.initialize_copy(original); diff --git a/src/main/java/org/jruby/ext/openssl/X509Attribute.java b/src/main/java/org/jruby/ext/openssl/X509Attribute.java index cb4dac7d..abff135b 100644 --- a/src/main/java/org/jruby/ext/openssl/X509Attribute.java +++ b/src/main/java/org/jruby/ext/openssl/X509Attribute.java @@ -120,6 +120,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a return this; } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this; diff --git a/src/main/java/org/jruby/ext/openssl/X509Extension.java b/src/main/java/org/jruby/ext/openssl/X509Extension.java index be9c7aac..48aafbd6 100644 --- a/src/main/java/org/jruby/ext/openssl/X509Extension.java +++ b/src/main/java/org/jruby/ext/openssl/X509Extension.java @@ -250,6 +250,7 @@ else if ( args.length > 1 ) { return this; } + @JRubyMethod(visibility = Visibility.PRIVATE) @Override public IRubyObject initialize_copy(final IRubyObject original) { if (this == original) return this;