jwt-eddsa 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +3 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +26 -1
- data/LICENSE +1 -1
- data/README.md +6 -2
- data/Rakefile +9 -0
- data/lib/jwt/eddsa/algo.rb +34 -0
- data/lib/jwt/eddsa/jwk/okp.rb +121 -0
- data/lib/jwt/eddsa/version.rb +2 -2
- data/lib/jwt/eddsa.rb +3 -29
- data/release-please-config.json +9 -0
- metadata +23 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a9054ac4598241fed14b327b76854fb9dd57034947c2dc94d7ffd70a3b9667f
|
4
|
+
data.tar.gz: 79ace7fb4cde12fa7fef53cdec3631be1b1be4c7f9e2acd40976b15228050152
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55ffed5f3d15b636699d1eb8c20058a9d99c5f854de01efe1b06481aacee9f8e086fea6700c4ebc5e19e62139e3d4c9b31c81b160eab7e240cb2244c8a8e15da
|
7
|
+
data.tar.gz: d5f6976cba0e2eec62baae85abdad9c175937c90787a74d627b950e57a641869e2a562ef6e246b9b32e34379ab411e1e55d726d1130644eee667e637844485e1
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.5.0](https://github.com/anakinj/jwt-eddsa/compare/v0.4.0...v0.5.0) (2024-08-02)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Initial release ([d7ce4d3](https://github.com/anakinj/jwt-eddsa/commit/d7ce4d3885a1fbe0e268a672a52d4ed8b7c558d2))
|
9
|
+
* Release using release-please ([d450241](https://github.com/anakinj/jwt-eddsa/commit/d45024107095270ad6bafc0a638f154c0cb4d763))
|
10
|
+
* Still trying to configure release-please ([fcfe5cc](https://github.com/anakinj/jwt-eddsa/commit/fcfe5cc0c5ff18ea296a64d78db3fe073d667190))
|
11
|
+
|
12
|
+
## [0.4.0](https://github.com/anakinj/jwt-eddsa/compare/jwt-eddsa-v0.3.0...jwt-eddsa/v0.4.0) (2024-08-02)
|
13
|
+
|
14
|
+
|
15
|
+
### Features
|
16
|
+
|
17
|
+
* Initial release ([d7ce4d3](https://github.com/anakinj/jwt-eddsa/commit/d7ce4d3885a1fbe0e268a672a52d4ed8b7c558d2))
|
18
|
+
* Release using release-please ([d450241](https://github.com/anakinj/jwt-eddsa/commit/d45024107095270ad6bafc0a638f154c0cb4d763))
|
19
|
+
* Still trying to configure release-please ([fcfe5cc](https://github.com/anakinj/jwt-eddsa/commit/fcfe5cc0c5ff18ea296a64d78db3fe073d667190))
|
20
|
+
|
21
|
+
## [0.3.0](https://github.com/anakinj/jwt-eddsa/compare/v0.2.0...v0.3.0) (2024-08-02)
|
22
|
+
|
23
|
+
|
24
|
+
### Features
|
25
|
+
|
26
|
+
* Initial release ([d7ce4d3](https://github.com/anakinj/jwt-eddsa/commit/d7ce4d3885a1fbe0e268a672a52d4ed8b7c558d2))
|
27
|
+
|
3
28
|
## [v0.0.1](https://github.com/anakinj/jwt-eddsa/tree/v0.0.1) (NEXT)
|
4
29
|
|
5
30
|
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.2...main)
|
@@ -11,4 +36,4 @@
|
|
11
36
|
|
12
37
|
**Fixes and enhancements:**
|
13
38
|
|
14
|
-
- Your contribution here
|
39
|
+
- Your contribution here
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# jwt-eddsa
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/jwt-eddsa)
|
4
|
+
[](https://github.com/jwt/ruby-jwt/actions)
|
5
|
+
|
6
|
+
A library extending the ruby-jwt gem with EdDSA algorithms. Based on [RFC 8037](https://datatracker.ietf.org/doc/html/rfc8037).
|
4
7
|
|
5
8
|
**NOTE: This gem is still WIP**
|
6
9
|
|
@@ -13,6 +16,7 @@ Plan is to replace rbnacl with something else in the near future.
|
|
13
16
|
Will only work with the WIP branch, so adding the following to your the Gemfile should do the trick:
|
14
17
|
```
|
15
18
|
gem "jwt", github: "anakinj/ruby-jwt", branch: "extendable-algos"
|
19
|
+
gem "jwt-eddsa"
|
16
20
|
```
|
17
21
|
|
18
22
|
```
|
@@ -31,7 +35,7 @@ payload, header = JWT.decode(token, private_key.verify_key, true, algorithm: "Ed
|
|
31
35
|
|
32
36
|
```
|
33
37
|
bundle install
|
34
|
-
bundle exec
|
38
|
+
bundle exec rake
|
35
39
|
```
|
36
40
|
|
37
41
|
## Contributing
|
data/Rakefile
CHANGED
@@ -10,3 +10,12 @@ require "rubocop/rake_task"
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
12
12
|
task default: %i[spec rubocop]
|
13
|
+
|
14
|
+
task :check_version do
|
15
|
+
require_relative "lib/jwt/eddsa/version"
|
16
|
+
version = ENV.fetch("GEM_VERSION", nil)
|
17
|
+
|
18
|
+
raise "Version mismatch: #{JWT::EdDSA::VERSION} != #{version}" if version != JWT::EdDSA::VERSION
|
19
|
+
end
|
20
|
+
|
21
|
+
Rake::Task[:build].enhance([:check_version]) if ENV["CI"]
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module EdDSA
|
5
|
+
# EdDSA algorithm implementation
|
6
|
+
module Algo
|
7
|
+
include JWT::JWA::Algorithm
|
8
|
+
|
9
|
+
register_algorithm("EdDSA")
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def sign(_algorithm, msg, key)
|
13
|
+
unless key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
|
14
|
+
raise_sign_error!("Key given is a #{key.class} but needs to be a " \
|
15
|
+
"RbNaCl::Signatures::Ed25519::SigningKey")
|
16
|
+
end
|
17
|
+
|
18
|
+
key.sign(msg)
|
19
|
+
end
|
20
|
+
|
21
|
+
def verify(_algorithm, public_key, signing_input, signature)
|
22
|
+
unless public_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
|
23
|
+
raise_verify_error!("Key given is a #{public_key.class} but needs to be a " \
|
24
|
+
"RbNaCl::Signatures::Ed25519::VerifyKey")
|
25
|
+
end
|
26
|
+
|
27
|
+
public_key.verify(signature, signing_input)
|
28
|
+
rescue RbNaCl::CryptoError
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module EdDSA
|
5
|
+
module JWK
|
6
|
+
# https://datatracker.ietf.org/doc/html/rfc8037
|
7
|
+
class OKP < ::JWT::JWK::KeyBase
|
8
|
+
KTY = "OKP"
|
9
|
+
KTYS = [KTY, JWT::EdDSA::JWK::OKP, RbNaCl::Signatures::Ed25519::SigningKey,
|
10
|
+
RbNaCl::Signatures::Ed25519::VerifyKey].freeze
|
11
|
+
OKP_PUBLIC_KEY_ELEMENTS = %i[kty n x].freeze
|
12
|
+
OKP_PRIVATE_KEY_ELEMENTS = %i[d].freeze
|
13
|
+
|
14
|
+
def initialize(key, params = nil, options = {})
|
15
|
+
params ||= {}
|
16
|
+
# For backwards compatibility when kid was a String
|
17
|
+
params = { kid: params } if params.is_a?(String)
|
18
|
+
|
19
|
+
key_params = extract_key_params(key)
|
20
|
+
|
21
|
+
params = params.transform_keys(&:to_sym)
|
22
|
+
check_jwk_params!(key_params, params)
|
23
|
+
super(options, key_params.merge(params))
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_key
|
27
|
+
return @verify_key if defined?(@verify_key)
|
28
|
+
|
29
|
+
@verify_key = verify_key_from_parameters
|
30
|
+
end
|
31
|
+
|
32
|
+
def signing_key
|
33
|
+
return @signing_key if defined?(@signing_key)
|
34
|
+
|
35
|
+
@signing_key = signing_key_from_parameters
|
36
|
+
end
|
37
|
+
|
38
|
+
def key_digest
|
39
|
+
::JWT::JWK::Thumbprint.new(self).to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def private?
|
43
|
+
!signing_key.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def members
|
47
|
+
OKP_PUBLIC_KEY_ELEMENTS.each_with_object({}) { |i, h| h[i] = self[i] }
|
48
|
+
end
|
49
|
+
|
50
|
+
def export(options = {})
|
51
|
+
exported = parameters.clone
|
52
|
+
unless private? && options[:include_private] == true
|
53
|
+
exported.reject! do |k, _|
|
54
|
+
OKP_PRIVATE_KEY_ELEMENTS.include?(k)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
exported
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def extract_key_params(key) # rubocop:disable Metrics/MethodLength
|
63
|
+
case key
|
64
|
+
when JWT::JWK::KeyBase
|
65
|
+
key.export(include_private: true)
|
66
|
+
when RbNaCl::Signatures::Ed25519::SigningKey
|
67
|
+
@signing_key = key
|
68
|
+
@verify_key = key.verify_key
|
69
|
+
parse_okp_key_params(@verify_key, @signing_key)
|
70
|
+
when RbNaCl::Signatures::Ed25519::VerifyKey
|
71
|
+
@signing_key = nil
|
72
|
+
@verify_key = key
|
73
|
+
parse_okp_key_params(@verify_key)
|
74
|
+
when Hash
|
75
|
+
key.transform_keys(&:to_sym)
|
76
|
+
else
|
77
|
+
raise ArgumentError,
|
78
|
+
"key must be of type RbNaCl::Signatures::Ed25519::SigningKey, " \
|
79
|
+
"RbNaCl::Signatures::Ed25519::VerifyKey " \
|
80
|
+
"or Hash with key parameters"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def check_jwk_params!(key_params, _given_params)
|
85
|
+
return if key_params[:kty] == KTY
|
86
|
+
|
87
|
+
raise JWT::JWKError,
|
88
|
+
"Incorrect 'kty' value: #{key_params[:kty]}, expected #{KTY}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_okp_key_params(verify_key, signing_key = nil)
|
92
|
+
params = {
|
93
|
+
kty: KTY,
|
94
|
+
crv: "Ed25519",
|
95
|
+
x: ::Base64.urlsafe_encode64(verify_key.to_bytes, padding: false)
|
96
|
+
}
|
97
|
+
|
98
|
+
params[:d] = ::Base64.urlsafe_encode64(signing_key.to_bytes, padding: false) if signing_key
|
99
|
+
|
100
|
+
params
|
101
|
+
end
|
102
|
+
|
103
|
+
def verify_key_from_parameters
|
104
|
+
RbNaCl::Signatures::Ed25519::VerifyKey.new(::Base64.urlsafe_decode64(self[:x]))
|
105
|
+
end
|
106
|
+
|
107
|
+
def signing_key_from_parameters
|
108
|
+
return nil unless self[:d]
|
109
|
+
|
110
|
+
RbNaCl::Signatures::Ed25519::SigningKey.new(::Base64.urlsafe_decode64(self[:d]))
|
111
|
+
end
|
112
|
+
|
113
|
+
class << self
|
114
|
+
def import(jwk_data)
|
115
|
+
new(jwk_data)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/jwt/eddsa/version.rb
CHANGED
data/lib/jwt/eddsa.rb
CHANGED
@@ -1,33 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "jwt"
|
4
|
-
require_relative "eddsa/version"
|
5
|
-
|
6
|
-
module JWT
|
7
|
-
# EdDSA algorithm implementation
|
8
|
-
module Eddsa
|
9
|
-
include JWT::JWA::Algorithm
|
10
|
-
|
11
|
-
register_algorithm("EdDSA")
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def sign(_algorithm, msg, key)
|
15
|
-
unless key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
|
16
|
-
raise_sign_error!("Key given is a #{key.class} but needs to be a RbNaCl::Signatures::Ed25519::SigningKey")
|
17
|
-
end
|
18
4
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def verify(_algorithm, public_key, signing_input, signature)
|
23
|
-
unless public_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
|
24
|
-
raise_verify_error!("Key given is a #{public_key.class} but needs to be a RbNaCl::Signatures::Ed25519::VerifyKey")
|
25
|
-
end
|
26
|
-
|
27
|
-
public_key.verify(signature, signing_input)
|
28
|
-
rescue RbNaCl::CryptoError
|
29
|
-
false
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
5
|
+
require_relative "eddsa/version"
|
6
|
+
require_relative "eddsa/jwk/okp"
|
7
|
+
require_relative "eddsa/algo"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt-eddsa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joakim Antman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: base64
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: jwt
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,13 +52,14 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '6.0'
|
41
|
-
description:
|
55
|
+
description: Extends the ruby-jwt gem with EdDSA signing, verification and JWK importing/exporting
|
42
56
|
email:
|
43
57
|
- antmanj@gmail.com
|
44
58
|
executables: []
|
45
59
|
extensions: []
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
62
|
+
- ".release-please-manifest.json"
|
48
63
|
- ".rspec"
|
49
64
|
- ".rubocop.yml"
|
50
65
|
- ".ruby-version"
|
@@ -54,14 +69,17 @@ files:
|
|
54
69
|
- README.md
|
55
70
|
- Rakefile
|
56
71
|
- lib/jwt/eddsa.rb
|
72
|
+
- lib/jwt/eddsa/algo.rb
|
73
|
+
- lib/jwt/eddsa/jwk/okp.rb
|
57
74
|
- lib/jwt/eddsa/version.rb
|
75
|
+
- release-please-config.json
|
58
76
|
homepage: https://github.com/anakinj/jwt-eddsa
|
59
77
|
licenses:
|
60
78
|
- MIT
|
61
79
|
metadata:
|
62
80
|
homepage_uri: https://github.com/anakinj/jwt-eddsa
|
63
81
|
source_code_uri: https://github.com/anakinj/jwt-eddsa
|
64
|
-
changelog_uri: https://github.com/anakinj/jwt-
|
82
|
+
changelog_uri: https://github.com/anakinj/jwt-eddsa/blob/v0.5.0/CHANGELOG.md
|
65
83
|
rubygems_mfa_required: 'true'
|
66
84
|
post_install_message:
|
67
85
|
rdoc_options: []
|
@@ -81,5 +99,5 @@ requirements: []
|
|
81
99
|
rubygems_version: 3.5.11
|
82
100
|
signing_key:
|
83
101
|
specification_version: 4
|
84
|
-
summary:
|
102
|
+
summary: jwt EdDSA algorithm extension
|
85
103
|
test_files: []
|