From c073c98c7154fcdcd8a87ad5e245983449ff3d57 Mon Sep 17 00:00:00 2001 From: Joakim Antman Date: Sat, 28 Dec 2024 22:57:30 +0200 Subject: [PATCH] Require RSA keys of minimum 2048 bits --- CHANGELOG.md | 3 ++- lib/jwt/jwa/ps.rb | 1 + lib/jwt/jwa/rsa.rb | 1 + spec/jwt/jwa/ps_spec.rb | 10 ++++++++++ spec/jwt/jwa/rsa_spec.rb | 10 ++++++++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 033f94ac..5816c184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ - Remove deprecated claim verification methods [#654](https://github.com/jwt/ruby-jwt/pull/654) ([@anakinj](https://github.com/anakinj)) - Remove dependency to rbnacl [#655](https://github.com/jwt/ruby-jwt/pull/655) ([@anakinj](https://github.com/anakinj)) - Support only stricter base64 decoding (RFC 4648) [#658](https://github.com/jwt/ruby-jwt/pull/658) ([@anakinj](https://github.com/anakinj)) -- Custom algorithms are required to include `JWT::JWA::SigningAlgorithm` [#660](https://github.com/jwt/ruby-jwt/pull/560) ([@anakinj](https://github.com/anakinj)) +- Custom algorithms are required to include `JWT::JWA::SigningAlgorithm` [#660](https://github.com/jwt/ruby-jwt/pull/660) ([@anakinj](https://github.com/anakinj)) +- Require RSA keys to be at least 2048 bits [#661](https://github.com/jwt/ruby-jwt/pull/661) ([@anakinj](https://github.com/anakinj)) Take a look at the [upgrade guide](UPGRADING.md) for more details. diff --git a/lib/jwt/jwa/ps.rb b/lib/jwt/jwa/ps.rb index 547a5f9b..85ef615a 100644 --- a/lib/jwt/jwa/ps.rb +++ b/lib/jwt/jwa/ps.rb @@ -13,6 +13,7 @@ def initialize(alg) def sign(data:, signing_key:) raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance.") unless signing_key.is_a?(::OpenSSL::PKey::RSA) + raise_sign_error!('The key length must be greater than or equal to 2048 bits') if signing_key.n.num_bits < 2048 signing_key.sign_pss(digest_algorithm, data, salt_length: :digest, mgf1_hash: digest_algorithm) end diff --git a/lib/jwt/jwa/rsa.rb b/lib/jwt/jwa/rsa.rb index d9ab925f..349baefe 100644 --- a/lib/jwt/jwa/rsa.rb +++ b/lib/jwt/jwa/rsa.rb @@ -13,6 +13,7 @@ def initialize(alg) def sign(data:, signing_key:) raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance") unless signing_key.is_a?(OpenSSL::PKey::RSA) + raise_sign_error!('The key length must be greater than or equal to 2048 bits') if signing_key.n.num_bits < 2048 signing_key.sign(digest, data) end diff --git a/spec/jwt/jwa/ps_spec.rb b/spec/jwt/jwa/ps_spec.rb index 53b57433..13d4d087 100644 --- a/spec/jwt/jwa/ps_spec.rb +++ b/spec/jwt/jwa/ps_spec.rb @@ -42,6 +42,16 @@ end.to raise_error(JWT::EncodeError, /The given key is a String. It has to be an OpenSSL::PKey::RSA instance./) end end + + context 'with a key length less than 2048 bits' do + let(:rsa_key) { OpenSSL::PKey::RSA.generate(1024) } + + it 'raises an error' do + expect do + ps256_instance.sign(data: data, signing_key: rsa_key) + end.to raise_error(JWT::EncodeError, 'The key length must be greater than or equal to 2048 bits') + end + end end describe '#verify' do diff --git a/spec/jwt/jwa/rsa_spec.rb b/spec/jwt/jwa/rsa_spec.rb index ea73c93d..edd7f1cf 100644 --- a/spec/jwt/jwa/rsa_spec.rb +++ b/spec/jwt/jwa/rsa_spec.rb @@ -20,6 +20,16 @@ end end + context 'with a key length less than 2048 bits' do + let(:rsa_key) { OpenSSL::PKey::RSA.generate(1024) } + + it 'raises an error' do + expect do + rsa_instance.sign(data: data, signing_key: rsa_key) + end.to raise_error(JWT::EncodeError, 'The key length must be greater than or equal to 2048 bits') + end + end + context 'with an invalid key' do it 'raises an error' do expect do