From 329bbe1b4fff6ca20f35559a9a2bd43b16498c1c Mon Sep 17 00:00:00 2001 From: Lucas Kanashiro Date: Fri, 6 May 2022 09:41:27 -0300 Subject: [PATCH] Support openssl 3 (Fixes: #100) The openssl API introduced some breaking changes which are fixed by this commit. For more information about those changes check this out: https://github.com/ruby/openssl/blob/master/History.md#version-300 Co-authored-by: Sergio Durigan Junior --- lib/json/jwk.rb | 64 ++++++++++++++++++++++++++++++------------- lib/json/jws.rb | 4 +-- spec/json/jwk_spec.rb | 4 +-- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/lib/json/jwk.rb b/lib/json/jwk.rb index 5bda7f8..f214fea 100644 --- a/lib/json/jwk.rb +++ b/lib/json/jwk.rb @@ -101,22 +101,29 @@ def to_rsa_key OpenSSL::BN.new Base64.urlsafe_decode64(self[key]), 2 end end - key = OpenSSL::PKey::RSA.new - if key.respond_to? :set_key - key.set_key n, e, d - key.set_factors p, q if p && q - key.set_crt_params dp, dq, qi if dp && dq && qi - else - key.e = e - key.n = n - key.d = d if d - key.p = p if p - key.q = q if q - key.dmp1 = dp if dp - key.dmq1 = dq if dq - key.iqmp = qi if qi + + # Public key + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(n), + OpenSSL::ASN1::Integer(e), + ]) + + if d && p && q && dp && dq && qi + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(n), + OpenSSL::ASN1::Integer(e), + OpenSSL::ASN1::Integer(d), + OpenSSL::ASN1::Integer(p), + OpenSSL::ASN1::Integer(q), + OpenSSL::ASN1::Integer(dp), + OpenSSL::ASN1::Integer(dq), + OpenSSL::ASN1::Integer(qi), + ]) end - key + + asn1 = OpenSSL::ASN1::Sequence(data_sequence) + OpenSSL::PKey::RSA.new(asn1.to_der) end def to_ec_key @@ -137,13 +144,32 @@ def to_ec_key Base64.urlsafe_decode64(self[key]) end end - key = OpenSSL::PKey::EC.new curve_name - key.private_key = OpenSSL::BN.new(d, 2) if d - key.public_key = OpenSSL::PKey::EC::Point.new( + + point = OpenSSL::PKey::EC::Point.new( OpenSSL::PKey::EC::Group.new(curve_name), OpenSSL::BN.new(['04' + x.unpack('H*').first + y.unpack('H*').first].pack('H*'), 2) ) - key + + # Public key + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::ObjectId("id-ecPublicKey"), + OpenSSL::ASN1::ObjectId(curve_name) + ]), + OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed)) + ]) + + if d + # Private key + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(1), + OpenSSL::ASN1::OctetString(OpenSSL::BN.new(d, 2).to_s(2)), + OpenSSL::ASN1::ObjectId(curve_name, 0, :EXPLICIT), + OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT) + ]) + end + + OpenSSL::PKey::EC.new(data_sequence.to_der) end end end diff --git a/lib/json/jws.rb b/lib/json/jws.rb index 68f1d5f..f6d1591 100644 --- a/lib/json/jws.rb +++ b/lib/json/jws.rb @@ -156,8 +156,8 @@ def verify_ecdsa_group!(key) when 512 :secp521r1 end - key.group = OpenSSL::PKey::EC::Group.new group_name.to_s - key.check_key + newkey = OpenSSL::PKey::EC.generate(group_name.to_s) + newkey.check_key end def raw_to_asn1(signature, public_key) diff --git a/spec/json/jwk_spec.rb b/spec/json/jwk_spec.rb index f82bd66..6432702 100644 --- a/spec/json/jwk_spec.rb +++ b/spec/json/jwk_spec.rb @@ -145,7 +145,7 @@ describe 'unknown curve' do it do - key = OpenSSL::PKey::EC.new('secp112r2').generate_key + key = OpenSSL::PKey::EC.generate('secp112r2') expect do JSON::JWK.new key end.to raise_error JSON::JWK::UnknownAlgorithm, 'Unknown EC Curve' @@ -193,7 +193,7 @@ describe 'unknown key type' do it do - key = OpenSSL::PKey::DSA.generate 256 + key = OpenSSL::PKey::DSA.generate 2048 expect do JSON::JWK.new key end.to raise_error JSON::JWK::UnknownAlgorithm, 'Unknown Key Type'