Skip to content

Commit

Permalink
Merge branch 'beanieboi-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
potatosalad committed Jan 8, 2024
2 parents e1be589 + b42bb7c commit be15a7e
Show file tree
Hide file tree
Showing 17 changed files with 105 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.5.1
3.2.2
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ env:
- RUBYOPT="-W0"

rvm:
- 2.5.1
- 3.2.2

notifications:
email: false
Expand Down
9 changes: 8 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ platforms :ruby do
end

group :test do
gem "bundler"
gem "rake"
gem "minitest"
gem "json"
gem "rbnacl"
gem "ed25519"
gem "x25519"
gem 'minitest-focus', require: false
gem 'minitest-perf', require: false
gem 'rantly', github: 'abargnesi/rantly', ref: '2875f63bfc695d270ecb574c56d1a7d8f6af0153', require: false
gem 'rantly', github: 'abargnesi/rantly', ref: '8ba1d908659c1cf2a08487b2a4e758a6197a0802', require: false
gem 'simplecov', require: false
if ENV['CI']
gem 'coveralls', require: false
Expand Down
10 changes: 1 addition & 9 deletions jose.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,5 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency "hamster"

spec.add_development_dependency "bundler", "~> 1.16"
spec.add_development_dependency "rake", "~> 12.3"
spec.add_development_dependency "minitest"
spec.add_development_dependency "json"
spec.add_development_dependency "rbnacl-libsodium"
spec.add_development_dependency "ed25519"
spec.add_development_dependency "x25519"
spec.add_dependency "immutable-ruby"
end
6 changes: 3 additions & 3 deletions lib/jose.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'jose/version'

require 'base64'
require 'hamster/hash'
require 'immutable/hash'
require 'json'
require 'openssl'
require 'securerandom'
Expand All @@ -28,8 +28,8 @@ module JOSE
# @!visibility private
MUTEX = Mutex.new

# Immutable Map structure based on `Hamster::Hash`.
class Map < Hamster::Hash; end
# Immutable Map structure based on `Immutable::Hash`.
class Map < Immutable::Hash; end

@__crypto_fallback__ = ENV['JOSE_CRYPTO_FALLBACK'] ? true : false
@__unsecured_signing__ = ENV['JOSE_UNSECURED_SIGNING'] ? true : false
Expand Down
2 changes: 1 addition & 1 deletion lib/jose/jwa.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def __jwk_kty_support_check__(key_types)
kty.push(key_type) if not kty_OKP_crv.empty?
when 'RSA'
begin
JOSE::JWK.generate_key([:rsa, 256])
JOSE::JWK.generate_key([:rsa, 1024])
kty.push(key_type)
rescue StandardError, NotImplementedError
# do nothing
Expand Down
4 changes: 0 additions & 4 deletions lib/jose/jwa/curve25519_rbnacl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ def __ruby__?; false; end

def __supported__?
return @supported ||= begin
begin
require 'rbnacl/libsodium'
rescue LoadError
end
begin
require 'rbnacl'
rescue LoadError
Expand Down
2 changes: 1 addition & 1 deletion lib/jose/jwk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ def to_pem_file(file, password = nil)
# Converts a private {JOSE::JWK JOSE::JWK} into a public {JOSE::JWK JOSE::JWK}.
#
# !!!ruby
# jwk_rsa = JOSE::JWK.generate_key([:rsa, 256]).to_map
# jwk_rsa = JOSE::JWK.generate_key([:rsa, 1024]).to_map
# # => JOSE::Map[
# # "dq" => "Iv_BghpjRyv8hk4AgsX_3w",
# # "e" => "AQAB",
Expand Down
25 changes: 20 additions & 5 deletions lib/jose/jwk/kty_ec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,31 @@ def self.from_map(fields)
else
raise ArgumentError, "invalid 'EC' JWK"
end
ec = OpenSSL::PKey::EC.new(crv)

x = JOSE.urlsafe_decode64(fields['x'])
y = JOSE.urlsafe_decode64(fields['y'])
ec.public_key = OpenSSL::PKey::EC::Point.new(
point = OpenSSL::PKey::EC::Point.new(
OpenSSL::PKey::EC::Group.new(crv),
OpenSSL::BN.new([0x04, x, y].pack('Ca*a*'), 2)
)
if fields['d'].is_a?(String)
ec.private_key = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)

sequence = if fields['d'].is_a?(String)
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(1),
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2).to_s(2)),
OpenSSL::ASN1::ObjectId(crv, 0, :EXPLICIT),
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
])
else
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
OpenSSL::ASN1::ObjectId(crv)
]),
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
])
end
ec = OpenSSL::PKey::EC.new(sequence.to_der)
return JOSE::JWK::KTY_EC.new(JOSE::JWK::PKeyProxy.new(ec)), fields.except('kty', 'crv', 'd', 'x', 'y')
else
raise ArgumentError, "invalid 'EC' JWK"
Expand Down Expand Up @@ -132,7 +147,7 @@ def self.generate_key(curve_name)
curve_name
end
if curve_name.is_a?(String)
return from_key(OpenSSL::PKey::EC.new(curve_name).generate_key)
return from_key(OpenSSL::PKey::EC.generate(curve_name))
else
raise ArgumentError, "'curve_name' must be a String"
end
Expand Down
64 changes: 34 additions & 30 deletions lib/jose/jwk/kty_rsa.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,32 @@ def self.from_map(fields)
raise ArgumentError, "multi-prime RSA keys are not supported"
elsif fields['d'].is_a?(String)
if fields['dp'].is_a?(String) and fields['dq'].is_a?(String) and fields['p'].is_a?(String) and fields['q'].is_a?(String) and fields['qi'].is_a?(String)
rsa = OpenSSL::PKey::RSA.new
rsa.set_key(
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)
)
rsa.set_factors(
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['p']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['q']), 2)
)
rsa.set_crt_params(
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['dp']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['dq']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['qi']), 2)
)
asn1_sequence = OpenSSL::ASN1::Sequence.new([
OpenSSL::ASN1::Integer.new(0),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['p']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['q']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['dp']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['dq']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['qi']), 2))
])
rsa = OpenSSL::PKey::RSA.new(asn1_sequence.to_der)
return JOSE::JWK::KTY_RSA.new(JOSE::JWK::PKeyProxy.new(rsa)), fields.except('kty', 'd', 'dp', 'dq', 'e', 'n', 'p', 'q', 'qi')
else
d = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)
e = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2)
n = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2)
d = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)
e = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2)
n = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2)
rsa = convert_sfm_to_crt(d, e, n)
return JOSE::JWK::KTY_RSA.new(JOSE::JWK::PKeyProxy.new(rsa)), fields.except('kty', 'd', 'dp', 'dq', 'e', 'n', 'p', 'q', 'qi')
end
else
rsa = OpenSSL::PKey::RSA.new
rsa.set_key(
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2),
OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2),
nil
)
asn1_sequence = OpenSSL::ASN1::Sequence.new([
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2)),
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2))
])
rsa = OpenSSL::PKey::RSA.new(OpenSSL::PKey::RSA.new(asn1_sequence.to_der))
return JOSE::JWK::KTY_RSA.new(JOSE::JWK::PKeyProxy.new(rsa)), fields.except('kty', 'e', 'n')
end
else
Expand Down Expand Up @@ -140,7 +136,8 @@ def self.generate_key(modulus_size, exponent_size = nil)
end
end
if modulus_size.is_a?(Integer) and (exponent_size.nil? or exponent_size.is_a?(Integer))
return from_key(OpenSSL::PKey::RSA.generate(modulus_size, exponent_size))
return from_key(OpenSSL::PKey::RSA.generate(modulus_size)) if exponent_size.nil?
return from_key(OpenSSL::PKey::RSA.generate(modulus_size, exponent_size)) if exponent_size.is_a?(Integer)
else
raise ArgumentError, "'modulus_size' must be an Integer and 'exponent_size' must be nil or an Integer"
end
Expand Down Expand Up @@ -230,11 +227,18 @@ def self.convert_sfm_to_crt(d, e, n)
dq = d % (q - 1)
qi = q.mod_inverse(p)

rsa = OpenSSL::PKey::RSA.new
rsa.set_key(n, e, d)
rsa.set_factors(p, q)
rsa.set_crt_params(dp, dq, qi)

asn1_sequence = OpenSSL::ASN1::Sequence.new([
OpenSSL::ASN1::Integer.new(0),
OpenSSL::ASN1::Integer.new(n),
OpenSSL::ASN1::Integer.new(e),
OpenSSL::ASN1::Integer.new(d),
OpenSSL::ASN1::Integer.new(p),
OpenSSL::ASN1::Integer.new(q),
OpenSSL::ASN1::Integer.new(dp),
OpenSSL::ASN1::Integer.new(dq),
OpenSSL::ASN1::Integer.new(qi)
])
rsa = OpenSSL::PKey::RSA.new(asn1_sequence.to_der)
return rsa
end

Expand Down
1 change: 0 additions & 1 deletion lib/jose/jwk/openssh_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ def parse_key_body(body)

def parse_publickeys(body, n, pks = [])
return pks, body if n == 0
pos = body.pos
if pk_len = body.read(4) and pk_len.bytesize == 4
pk_len, = pk_len.unpack('N')
if pk = body.read(pk_len) and pk.bytesize == pk_len
Expand Down
6 changes: 3 additions & 3 deletions lib/jose/jwk/set.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'hamster/vector'
require 'immutable/vector'

# Immutable Set structure based on `Hamster::Vector`.
class JOSE::JWK::Set < Hamster::Vector
# Immutable Set structure based on `Immutable::Vector`.
class JOSE::JWK::Set < Immutable::Vector

def self.from_map(fields)
if fields['keys'].is_a?(Array)
Expand Down
14 changes: 9 additions & 5 deletions test/cfrg_curves_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ def test_curve25519_eddsa_ed25519
hexstr2bin(
"d75a980182b10ab7d54bfed3c964073a"\
"0ee172f3daa62325af021a68f707511a"), # PUBLIC KEY
"", # MESSAGE
hexstr2bin(
"e5564300c360ac729086e2cc806e828a"\
"84877f1eb8e5d974d873e06522490155"\
"5fb8821590a33bacc61e39701cf9b46b"\
"d25bf5f0595bbe24655141438e7a100b") # SIGNATURE
"1b79abc415a34efe5915b4c1b53d2435"\
"e731b3c92d0ba440de29cab2999fa885"\
"bd0eb3c71dfd8df6fbecf8c0ef403e89"\
"02dec8e2abd00a2bb9b04b1df027929609"), # MESSAGE
hexstr2bin(
"c2ace0031e4c62e758872427e1bca3df"\
"683339792a2c18c4547190678152e91c"\
"9be04f5704acf5c2e61d835e8a53b49d"\
"83e27879f26024afc7320e94c7d84a07") # SIGNATURE
],
[ # TEST 2
hexstr2bin(
Expand Down
6 changes: 3 additions & 3 deletions test/jose/jwa/curve25519_rbnacl_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ class JOSE::JWA::Curve25519_RbNaClTest < Minitest::Test
EdDSA_SECRET = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].pack('C*')
EdDSA_SK = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,106,39,188,206,182,164,45,98,163,168,208,42,111,13,115,101,50,21,119,29,226,67,166,58,192,72,161,139,89,218,41].pack('C*')
EdDSA_PK = [59,106,39,188,206,182,164,45,98,163,168,208,42,111,13,115,101,50,21,119,29,226,67,166,58,192,72,161,139,89,218,41].pack('C*')
EdDSA_M = [].pack('C*')
Ed25519_SIGNATURE = [143,137,91,60,175,226,201,80,96,57,208,226,166,99,130,86,128,4,103,79,232,210,55,120,80,146,228,13,106,175,72,62,79,198,1,104,112,95,49,241,1,89,97,56,206,33,170,53,124,13,50,160,100,244,35,220,62,228,170,58,191,83,248,3].pack('C*')
Ed25519ph_SIGNATURE = [156,203,202,248,117,129,126,7,75,58,114,37,34,97,88,28,107,134,137,45,226,153,205,227,223,176,47,120,25,58,104,151,0,98,205,14,60,170,233,142,178,63,207,181,133,191,210,47,240,169,14,31,162,243,195,196,214,28,175,237,234,99,76,4].pack('C*')
EdDSA_M = [143,137,91,60,175,226,201,80,96,57,208,226,166,99,130,86,128,4,103,79,232,210,55,120,80,146,228,13,106,175,72,62,79,198,1,104,112,95,49,241,1,89,97,56,206,33,170,53,124,13,50,160,100,244,35,220,62,228,170,58,191,83,248,3].pack('C*')
Ed25519_SIGNATURE = [41,13,154,178,137,160,128,144,140,163,130,167,13,188,171,152,138,171,163,229,123,125,178,222,201,119,31,0,244,114,40,135,185,194,25,223,208,40,26,246,220,92,60,130,121,177,46,218,177,207,103,148,115,236,154,41,233,169,27,182,157,125,23,11].pack('C*')
Ed25519ph_SIGNATURE = [99,146,10,64,251,96,187,115,154,193,232,23,243,125,159,138,198,173,49,91,250,230,124,186,106,14,225,15,195,111,55,210,137,77,19,250,148,204,114,68,57,177,38,94,69,116,89,197,65,35,186,106,61,54,120,211,45,27,53,190,175,167,49,11].pack('C*')
Curve25519_SECRET = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64].pack('C*')
Curve25519_PUBLIC = [47,229,125,163,71,205,98,67,21,40,218,172,95,187,41,7,48,255,246,132,175,196,207,194,237,144,153,95,88,203,59,116].pack('C*')
Curve25519_SHARED = [147,254,162,167,193,174,182,44,253,100,82,255,91,173,174,139,223,252,189,113,150,220,145,12,137,148,64,6,216,93,187,104].pack('C*')
Expand Down
4 changes: 2 additions & 2 deletions test/jose/jwk/kty_rsa_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def test_from_key_and_to_key
end

def test_generate_key
jwk1 = JOSE::JWK.generate_key([:rsa, 128])
jwk2 = JOSE::JWK.generate_key([:rsa, 128, 13])
jwk1 = JOSE::JWK.generate_key([:rsa, 1024])
jwk2 = JOSE::JWK.generate_key([:rsa, 1024, 13])
jwk3 = JOSE::JWK.generate_key(jwk2)
refute_equal JOSE::JWK.thumbprint(jwk1), JOSE::JWK.thumbprint(jwk2)
refute_equal JOSE::JWK.thumbprint(jwk1), JOSE::JWK.thumbprint(jwk3)
Expand Down
7 changes: 4 additions & 3 deletions test/jose_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,10 @@ def test_rfc7520_5_9
assert_equal v_5_9_2_cek, JOSE.urlsafe_encode64(JOSE::JWE::ALG_AES_KW.new(128).key_decrypt(v_5_9_1_jwk, nil, JOSE.urlsafe_decode64(v_5_9_3_encrypted_key)))
# 5.9.4
v_5_9_4_jwe = JOSE::JWE.from_binary(figures[166])
v_5_9_4_jwe_protected = figures[167]
v_5_9_4_cipher_text = figures[168]
v_5_9_4_cipher_tag = figures[169]
# commenting out unused variables because they are helpful as documentation
# v_5_9_4_jwe_protected = figures[167]
# v_5_9_4_cipher_text = figures[168]
# v_5_9_4_cipher_tag = figures[169]
v_5_9_5_jwe_compact = figures[170]
v_5_9_5_jwe_map = JOSE.decode(figures[172])
plain_text, jwe = JOSE::JWE.block_decrypt(v_5_9_1_jwk, v_5_9_5_jwe_compact)
Expand Down
15 changes: 14 additions & 1 deletion test/rantly_extensions.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
require 'rantly/minitest_extensions'
require 'minitest'
require 'rantly/property'
require 'rantly/shrinks'

test_class = if defined?(Minitest::Test)
Minitest::Test
else
Minitest::Unit::TestCase
end

test_class.class_eval do
def property_of(&blk)
Rantly::Property.new(blk)
end
end

class Rantly

JWE_ALG_GROUPS = {
Expand Down

0 comments on commit be15a7e

Please sign in to comment.