Skip to content

Commit

Permalink
Algorithm cleanup.
Browse files Browse the repository at this point in the history
 - Algos module renamed to JWA
 - Standard HMAC algorithms provided explicitly by OpenSSL (#550)
 - Prepare to remove support for the HS512256 algorithm provided by RbNaCl (#549)
  • Loading branch information
anakinj committed Feb 17, 2024
1 parent 39aa57a commit 13dd333
Show file tree
Hide file tree
Showing 24 changed files with 225 additions and 360 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,8 @@

- Updated rubocop to 1.56 [#573](https://github.com/jwt/ruby-jwt/pull/573) - [@anakinj](https://github.com/anakinj).
- Run CI on Ruby 3.3 [#577](https://github.com/jwt/ruby-jwt/pull/577) - [@anakinj](https://github.com/anakinj).
- Deprecation warning added for the HMAC algorithm HS512256 (HMAC-SHA-512 truncated to 256-bits) [#575](https://github.com/jwt/ruby-jwt/pull/575) ([@anakinj](https://github.com/anakinj)).
- Stop using RbNaCl for standard HMAC algorithms [#575](https://github.com/jwt/ruby-jwt/pull/575) ([@anakinj](https://github.com/anakinj)).
- Your contribution here

**Fixes and enhancements:**
Expand All @@ -19,6 +21,7 @@
- Repair EC x/y coordinates when importing JWK [#585](https://github.com/jwt/ruby-jwt/pull/585) - [@julik](https://github.com/julik).
- Explicit dependency to the base64 gem [#582](https://github.com/jwt/ruby-jwt/pull/582) - [@anakinj](https://github.com/anakinj).
- Deprecation warning for decoding content not compliant with RFC 4648 [#582](https://github.com/jwt/ruby-jwt/pull/582) - [@anakinj](https://github.com/anakinj).
- Algorithms moved under the `::JWT::JWA` module ([@anakinj](https://github.com/anakinj)).
- Your contribution here

## [v2.7.1](https://github.com/jwt/ruby-jwt/tree/v2.8.0) (2023-06-09)
Expand Down
7 changes: 0 additions & 7 deletions README.md
Expand Up @@ -72,7 +72,6 @@ puts decoded_token
### **HMAC**

* HS256 - HMAC using SHA-256 hash algorithm
* HS512256 - HMAC using SHA-512-256 hash algorithm (only available with RbNaCl; see note below)
* HS384 - HMAC using SHA-384 hash algorithm
* HS512 - HMAC using SHA-512 hash algorithm

Expand All @@ -95,12 +94,6 @@ decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' }
puts decoded_token
```

Note: If [RbNaCl](https://github.com/RubyCrypto/rbnacl) is loadable, ruby-jwt will use it for HMAC-SHA256, HMAC-SHA512-256, and HMAC-SHA512. RbNaCl prior to 6.0.0 only support a maximum key size of 32 bytes for these algorithms.

[RbNaCl](https://github.com/RubyCrypto/rbnacl) requires
[libsodium](https://github.com/jedisct1/libsodium), it can be installed
on MacOS with `brew install libsodium`.

### **RSA**

* RS256 - RSA using SHA-256 hash algorithm
Expand Down
66 changes: 0 additions & 66 deletions lib/jwt/algos.rb

This file was deleted.

33 changes: 0 additions & 33 deletions lib/jwt/algos/eddsa.rb

This file was deleted.

53 changes: 0 additions & 53 deletions lib/jwt/algos/hmac_rbnacl.rb

This file was deleted.

52 changes: 0 additions & 52 deletions lib/jwt/algos/hmac_rbnacl_fixed.rb

This file was deleted.

8 changes: 1 addition & 7 deletions lib/jwt/decode.rb
Expand Up @@ -92,13 +92,7 @@ def allowed_algorithms
end

def resolve_allowed_algorithms
algs = given_algorithms.map do |alg|
if Algos.implementation?(alg)
alg
else
Algos.create(alg)
end
end
algs = given_algorithms.map { |alg| JWA.create(alg) }

sort_by_alg_header(algs)
end
Expand Down
10 changes: 2 additions & 8 deletions lib/jwt/encode.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require_relative 'algos'
require_relative 'jwa'
require_relative 'claims_validator'

# JWT::Encode module
Expand All @@ -12,7 +12,7 @@ class Encode
def initialize(options)
@payload = options[:payload]
@key = options[:key]
@algorithm = resolve_algorithm(options[:algorithm])
@algorithm = JWA.create(options[:algorithm])
@headers = options[:headers].transform_keys(&:to_s)
@headers[ALG_KEY] = @algorithm.alg
end
Expand All @@ -24,12 +24,6 @@ def segments

private

def resolve_algorithm(algorithm)
return algorithm if Algos.implementation?(algorithm)

Algos.create(algorithm)
end

def encoded_header
@encoded_header ||= encode_header
end
Expand Down
62 changes: 62 additions & 0 deletions lib/jwt/jwa.rb
@@ -0,0 +1,62 @@
# frozen_string_literal: true

require 'openssl'

begin
require 'rbnacl'
rescue LoadError
raise if defined?(RbNaCl)
end

require_relative 'jwa/hmac'
require_relative 'jwa/eddsa'
require_relative 'jwa/ecdsa'
require_relative 'jwa/rsa'
require_relative 'jwa/ps'
require_relative 'jwa/none'
require_relative 'jwa/unsupported'
require_relative 'jwa/wrapper'

module JWT
module JWA
ALGOS = [Hmac, Ecdsa, Rsa, Eddsa, Ps, None, Unsupported].tap do |l|
if ::JWT.rbnacl_6_or_greater?
require_relative 'jwa/hmac_rbnacl'
l << Algos::HmacRbNaCl
elsif ::JWT.rbnacl?
require_relative 'jwa/hmac_rbnacl_fixed'
l << Algos::HmacRbNaClFixed
end
end.freeze

class << self
def find(algorithm)
indexed[algorithm&.downcase]
end

def create(algorithm)
return algorithm if JWA.implementation?(algorithm)

Wrapper.new(*find(algorithm))
end

def implementation?(algorithm)
(algorithm.respond_to?(:valid_alg?) && algorithm.respond_to?(:verify)) ||
(algorithm.respond_to?(:alg) && algorithm.respond_to?(:sign))
end

private

def indexed
@indexed ||= begin
fallback = [nil, Unsupported]
ALGOS.each_with_object(Hash.new(fallback)) do |cls, hash|
cls.const_get(:SUPPORTED).each do |alg|
hash[alg.downcase] = [alg, cls]
end
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/jwt/algos/ecdsa.rb → lib/jwt/jwa/ecdsa.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module JWT
module Algos
module JWA
module Ecdsa
module_function

Expand Down

0 comments on commit 13dd333

Please sign in to comment.