Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
**Features:**

- Add support for x5t header parameter for X.509 certificate thumbprint verification [#669](https://github.com/jwt/ruby-jwt/pull/669) ([@hieuk09](https://github.com/hieuk09))
- Raise an error if the ECDSA signing or verification key is not an instance of `OpenSSL::PKey::EC` [#688](https://github.com/jwt/ruby-jwt/pull/688) ([@anakinj](https://github.com/anakinj))
- Your contribution here

**Fixes and enhancements:**
Expand Down
5 changes: 5 additions & 0 deletions lib/jwt/jwa/ecdsa.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ def initialize(alg, digest)
end

def sign(data:, signing_key:)
raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::EC instance.") unless signing_key.is_a?(::OpenSSL::PKey::EC)

curve_definition = curve_by_name(signing_key.group.curve_name)
key_algorithm = curve_definition[:algorithm]

raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} signing key was provided" if alg != key_algorithm

asn1_to_raw(signing_key.dsa_sign_asn1(digest.digest(data)), signing_key)
end

def verify(data:, signature:, verification_key:)
raise_verify_error!("The given key is a #{verification_key.class}. It has to be an OpenSSL::PKey::EC instance.") unless verification_key.is_a?(::OpenSSL::PKey::EC)

curve_definition = curve_by_name(verification_key.group.curve_name)
key_algorithm = curve_definition[:algorithm]
raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} verification key was provided" if alg != key_algorithm
Expand Down
35 changes: 35 additions & 0 deletions spec/jwt/jwa/ecdsa_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,40 @@
end.to raise_error(JWT::VerificationError, 'Signature verification raised')
end
end

context 'when the verification key is not an OpenSSL::PKey::EC instance' do
it 'raises a JWT::DecodeError' do
expect do
instance.verify(data: data, signature: '', verification_key: 'not_a_key')
end.to raise_error(JWT::DecodeError, 'The given key is a String. It has to be an OpenSSL::PKey::EC instance.')
end
end
end

describe '#sign' do
context 'when the signing key is valid' do
it 'returns a valid signature' do
signature = instance.sign(data: data, signing_key: ecdsa_key)
expect(signature).to be_a(String)
expect(signature.length).to be > 0
end
end

context 'when the signing key is not an OpenSSL::PKey::EC instance' do
it 'raises a JWT::DecodeError' do
expect do
instance.sign(data: data, signing_key: 'not_a_key')
end.to raise_error(JWT::EncodeError, 'The given key is a String. It has to be an OpenSSL::PKey::EC instance.')
end
end

context 'when the signing key is invalid' do
it 'raises a JWT::DecodeError' do
invalid_key = OpenSSL::PKey::EC.generate('sect571r1')
expect do
instance.sign(data: data, signing_key: invalid_key)
end.to raise_error(JWT::DecodeError, "The ECDSA curve 'sect571r1' is not supported")
end
end
end
end
2 changes: 1 addition & 1 deletion spec/jwt/jwk/decode_with_jwk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@

it 'fails in some way' do
expect { described_class.decode(signed_token, nil, true, algorithms: ['ES384'], jwks: jwks) }.to(
raise_error(NoMethodError, /undefined method .*group/)
raise_error(JWT::DecodeError, 'The given key is a String. It has to be an OpenSSL::PKey::EC instance.')
)
end
end
Expand Down
16 changes: 16 additions & 0 deletions spec/jwt/jwk/ec_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,22 @@
end
end

describe '.to_openssl_curve' do
context 'when a valid curve name is given' do
it 'returns the corresponding OpenSSL curve name' do
expect(JWT::JWK::EC.to_openssl_curve('P-256')).to eq('prime256v1')
expect(JWT::JWK::EC.to_openssl_curve('P-384')).to eq('secp384r1')
expect(JWT::JWK::EC.to_openssl_curve('P-521')).to eq('secp521r1')
expect(JWT::JWK::EC.to_openssl_curve('P-256K')).to eq('secp256k1')
end
end
context 'when an invalid curve name is given' do
it 'raises an error' do
expect { JWT::JWK::EC.to_openssl_curve('invalid-curve') }.to raise_error(JWT::JWKError, 'Invalid curve provided')
end
end
end

describe '.import' do
subject { described_class.import(params) }
let(:include_private) { false }
Expand Down
4 changes: 0 additions & 4 deletions spec/jwt/jwt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@
}
end

after(:each) do
expect(OpenSSL.errors).to be_empty
end

context 'alg: NONE' do
let(:alg) { 'none' }
let(:encoded_token) { data['NONE'] }
Expand Down
Loading