ruby-paseto 0.1.2 → 0.2.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/CHANGELOG.md +7 -0
- data/README.md +55 -50
- data/lib/paseto/asn1/ecdsa_signature.rb +2 -2
- data/lib/paseto/asymmetric_key.rb +7 -4
- data/lib/paseto/configuration/decode_configuration.rb +7 -7
- data/lib/paseto/interface/key.rb +5 -2
- data/lib/paseto/interface/pbkd.rb +4 -20
- data/lib/paseto/interface/pie.rb +5 -26
- data/lib/paseto/interface/pke.rb +15 -51
- data/lib/paseto/interface/version.rb +30 -117
- data/lib/paseto/operations/id/i_dv3.rb +1 -1
- data/lib/paseto/operations/id/i_dv4.rb +1 -1
- data/lib/paseto/operations/pbkd/p_b_k_dv3.rb +4 -5
- data/lib/paseto/operations/pbkd/p_b_k_dv4.rb +3 -4
- data/lib/paseto/operations/pbkw.rb +6 -6
- data/lib/paseto/operations/pke/p_k_ev3.rb +23 -25
- data/lib/paseto/operations/pke/p_k_ev4.rb +33 -34
- data/lib/paseto/operations/pke.rb +9 -10
- data/lib/paseto/operations/wrap.rb +1 -1
- data/lib/paseto/paserk.rb +1 -1
- data/lib/paseto/paserk_types.rb +2 -2
- data/lib/paseto/protocol/version3.rb +17 -16
- data/lib/paseto/protocol/version4.rb +17 -16
- data/lib/paseto/symmetric_key.rb +16 -10
- data/lib/paseto/token.rb +17 -15
- data/lib/paseto/token_types.rb +2 -2
- data/lib/paseto/util.rb +1 -1
- data/lib/paseto/v3/local.rb +1 -1
- data/lib/paseto/v3/public.rb +5 -4
- data/lib/paseto/v4/local.rb +3 -3
- data/lib/paseto/v4/public.rb +3 -6
- data/lib/paseto/validator.rb +1 -1
- data/lib/paseto/version.rb +1 -1
- data/lib/paseto/versions.rb +2 -2
- data/lib/paseto/wrappers/pie/pie_v3.rb +18 -21
- data/lib/paseto/wrappers/pie/pie_v4.rb +17 -20
- data/lib/paseto/wrappers/pie.rb +3 -17
- data/lib/paseto.rb +2 -5
- data/paseto.gemspec +5 -5
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/rainbow.rbi +4 -4
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1 -1
- data/sorbet/rbi/gems/docile@1.4.0.rbi +1 -1
- data/sorbet/rbi/gems/{ffi@1.15.5.rbi → ffi@1.16.3.rbi} +260 -117
- data/sorbet/rbi/gems/{oj@3.14.2.rbi → oj@3.16.1.rbi} +26 -37
- data/sorbet/rbi/gems/{rake@13.0.6.rbi → rake@13.1.0.rbi} +75 -69
- data/sorbet/rbi/gems/rbnacl@7.1.1.rbi +2 -2
- data/sorbet/rbi/gems/{rspec-core@3.12.1.rbi → rspec-core@3.12.2.rbi} +1 -1
- data/sorbet/rbi/gems/{rspec-expectations@3.12.2.rbi → rspec-expectations@3.12.3.rbi} +27 -33
- data/sorbet/rbi/gems/{rspec-mocks@3.12.4.rbi → rspec-mocks@3.12.6.rbi} +60 -61
- data/sorbet/rbi/gems/{rspec-support@3.12.0.rbi → rspec-support@3.12.1.rbi} +35 -43
- data/sorbet/rbi/gems/rspec@3.12.0.rbi +22 -28
- data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +41 -44
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +232 -2
- data/sorbet/rbi/gems/{timecop@0.9.6.rbi → timecop@0.9.8.rbi} +13 -16
- data/sorbet/rbi/shims/multi_json.rbi +2 -0
- data/sorbet/rbi/shims/openssl.rbi +0 -8
- data/sorbet/rbi/todo.rbi +5 -1
- metadata +19 -42
- data/sorbet/rbi/gems/ast@2.4.2.rbi +0 -584
- data/sorbet/rbi/gems/io-console@0.6.0.rbi +0 -8
- data/sorbet/rbi/gems/irb@1.6.3.rbi +0 -342
- data/sorbet/rbi/gems/json@2.6.3.rbi +0 -1541
- data/sorbet/rbi/gems/multi_json@1.15.0.rbi +0 -267
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +0 -158
- data/sorbet/rbi/gems/openssl@3.1.0.rbi +0 -1739
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +0 -277
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +0 -407
- data/sorbet/rbi/gems/regexp_parser@2.7.0.rbi +0 -3580
- data/sorbet/rbi/gems/reline@0.3.2.rbi +0 -8
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +0 -4717
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +0 -1317
- data/sorbet/rbi/gems/thor@1.2.1.rbi +0 -3956
- data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +0 -65
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +0 -2555
- data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +0 -441
- data/sorbet/rbi/gems/yard@0.9.28.rbi +0 -17816
- data/sorbet/rbi/gems/zeitwerk@2.6.7.rbi +0 -8
@@ -7,30 +7,31 @@ module Paseto
|
|
7
7
|
extend T::Sig
|
8
8
|
extend T::Helpers
|
9
9
|
|
10
|
+
include Singleton
|
10
11
|
include Interface::Version
|
11
12
|
|
12
13
|
sig(:final) { override.params(key: String, nonce: String, payload: String).returns(String) }
|
13
|
-
def
|
14
|
+
def crypt(key:, nonce:, payload:)
|
14
15
|
Paseto::Sodium::Stream::XChaCha20Xor.new(key).encrypt(nonce, payload)
|
15
16
|
end
|
16
17
|
|
17
18
|
sig(:final) { override.params(data: String, digest_size: Integer).returns(String) }
|
18
|
-
def
|
19
|
-
RbNaCl::Hash.blake2b(data, digest_size:
|
19
|
+
def digest(data, digest_size: 32)
|
20
|
+
RbNaCl::Hash.blake2b(data, digest_size:)
|
20
21
|
end
|
21
22
|
|
22
23
|
sig(:final) { override.returns(Integer) }
|
23
|
-
def
|
24
|
+
def digest_bytes
|
24
25
|
32
|
25
26
|
end
|
26
27
|
|
27
28
|
sig(:final) { override.params(data: String, key: String, digest_size: Integer).returns(String) }
|
28
|
-
def
|
29
|
-
RbNaCl::Hash.blake2b(data, key
|
29
|
+
def hmac(data, key:, digest_size: 32)
|
30
|
+
RbNaCl::Hash.blake2b(data, key:, digest_size:)
|
30
31
|
end
|
31
32
|
|
32
33
|
sig(:final) { override.returns(T.class_of(Operations::ID::IDv4)) }
|
33
|
-
def
|
34
|
+
def id
|
34
35
|
Operations::ID::IDv4
|
35
36
|
end
|
36
37
|
|
@@ -42,7 +43,7 @@ module Paseto
|
|
42
43
|
parameters: T.any(Symbol, Integer)
|
43
44
|
).returns(String)
|
44
45
|
end
|
45
|
-
def
|
46
|
+
def kdf(password, salt:, length:, **parameters)
|
46
47
|
memlimit = RbNaCl::PasswordHash::Argon2.memlimit_value(parameters[:memlimit])
|
47
48
|
opslimit = RbNaCl::PasswordHash::Argon2.opslimit_value(parameters[:opslimit])
|
48
49
|
|
@@ -56,42 +57,42 @@ module Paseto
|
|
56
57
|
end
|
57
58
|
|
58
59
|
sig(:final) { override.returns(String) }
|
59
|
-
def
|
60
|
+
def paserk_version
|
60
61
|
'k4'
|
61
62
|
end
|
62
63
|
|
63
64
|
sig(:final) { override.returns(String) }
|
64
|
-
def
|
65
|
+
def pbkd_local_header
|
65
66
|
'k4.local-pw'
|
66
67
|
end
|
67
68
|
|
68
69
|
sig(:final) { override.returns(String) }
|
69
|
-
def
|
70
|
+
def pbkd_secret_header
|
70
71
|
'k4.secret-pw'
|
71
72
|
end
|
72
73
|
|
73
74
|
sig(:final) { override.params(password: String).returns(Operations::PBKD::PBKDv4) }
|
74
|
-
def
|
75
|
+
def pbkw(password)
|
75
76
|
Operations::PBKD::PBKDv4.new(password)
|
76
77
|
end
|
77
78
|
|
78
79
|
sig(:final) { override.params(key: SymmetricKey).returns(Wrappers::PIE::PieV4) }
|
79
|
-
def
|
80
|
+
def pie(key)
|
80
81
|
Wrappers::PIE::PieV4.new(key)
|
81
82
|
end
|
82
83
|
|
83
84
|
sig(:final) { override.params(key: AsymmetricKey).returns(Operations::PKE::PKEv4) }
|
84
|
-
def
|
85
|
+
def pke(key)
|
85
86
|
Operations::PKE::PKEv4.new(key)
|
86
87
|
end
|
87
88
|
|
88
89
|
sig(:final) { override.params(size: Integer).returns(String) }
|
89
|
-
def
|
90
|
+
def random(size)
|
90
91
|
RbNaCl::Random.random_bytes(size)
|
91
92
|
end
|
92
93
|
|
93
94
|
sig(:final) { override.returns(String) }
|
94
|
-
def
|
95
|
+
def version
|
95
96
|
'v4'
|
96
97
|
end
|
97
98
|
end
|
data/lib/paseto/symmetric_key.rb
CHANGED
@@ -34,14 +34,14 @@ module Paseto
|
|
34
34
|
Util.pre_auth_encode(pae_header, n, c, footer, implicit_assertion)
|
35
35
|
.then { |pre_auth| protocol.hmac(pre_auth, key: ak) }
|
36
36
|
.then { |t| "#{n}#{c}#{t}" }
|
37
|
-
.then { |payload| Token.new(payload
|
37
|
+
.then { |payload| Token.new(payload:, version:, purpose:, footer:) }
|
38
38
|
end
|
39
39
|
|
40
40
|
# Verify and decrypt an encrypted Token, with an optional string `implicit_assertion`, and return the plaintext.
|
41
41
|
# If `token` includes a footer, it is treated as authenticated data to be verified but not returned.
|
42
42
|
# `token` must be a `v4.local` type Token.
|
43
43
|
sig(:final) { params(token: Token, implicit_assertion: String).returns(String) }
|
44
|
-
def decrypt(token:, implicit_assertion: '')
|
44
|
+
def decrypt(token:, implicit_assertion: '') # rubocop:disable Metrics/AbcSize
|
45
45
|
raise LucidityError unless header == token.header
|
46
46
|
|
47
47
|
n, c, t = split_payload(token.raw_payload)
|
@@ -52,9 +52,12 @@ module Paseto
|
|
52
52
|
t2 = protocol.hmac(pre_auth, key: ak)
|
53
53
|
raise InvalidAuthenticator unless Util.constant_compare(t, t2)
|
54
54
|
|
55
|
-
protocol.crypt(payload: c, key: ek, nonce: n2)
|
56
|
-
|
57
|
-
|
55
|
+
decrypted = protocol.crypt(payload: c, key: ek, nonce: n2)
|
56
|
+
decrypted.force_encoding('UTF-8')
|
57
|
+
|
58
|
+
raise ParseError, 'invalid payload encoding' unless decrypted.valid_encoding?
|
59
|
+
|
60
|
+
decrypted
|
58
61
|
end
|
59
62
|
|
60
63
|
sig(:final) do
|
@@ -68,7 +71,7 @@ module Paseto
|
|
68
71
|
def encode!(payload, footer: '', implicit_assertion: '', **options)
|
69
72
|
n = T.cast(options.delete(:nonce), T.nilable(String))
|
70
73
|
MultiJson.dump(payload, options)
|
71
|
-
.then { |message| encrypt(message
|
74
|
+
.then { |message| encrypt(message:, footer:, implicit_assertion:, n:) }
|
72
75
|
.then(&:to_s)
|
73
76
|
end
|
74
77
|
|
@@ -82,9 +85,9 @@ module Paseto
|
|
82
85
|
def decode!(payload, implicit_assertion: '', **options)
|
83
86
|
token = Token.parse(payload)
|
84
87
|
|
85
|
-
decrypt(token
|
88
|
+
decrypt(token:, implicit_assertion:)
|
86
89
|
.then { |json| MultiJson.load(json, **options) }
|
87
|
-
.then { |claims| Result.new(claims
|
90
|
+
.then { |claims| Result.new(claims:, footer: token.footer) }
|
88
91
|
end
|
89
92
|
|
90
93
|
sig(:final) { override.returns(String) }
|
@@ -93,6 +96,9 @@ module Paseto
|
|
93
96
|
sig(:final) { override.returns(String) }
|
94
97
|
def pbkw_header = protocol.pbkd_local_header
|
95
98
|
|
99
|
+
sig(:final) { override.returns(String) }
|
100
|
+
def pie_header = "#{paserk_version}.local-wrap.pie."
|
101
|
+
|
96
102
|
sig(:final) { returns(Interface::PIE) }
|
97
103
|
def pie = protocol.pie(self)
|
98
104
|
|
@@ -103,10 +109,10 @@ module Paseto
|
|
103
109
|
def to_bytes = key
|
104
110
|
|
105
111
|
sig(:final) { params(paserk: String).returns(Interface::Key) }
|
106
|
-
def unwrap(paserk) = Paserk.from_paserk(paserk
|
112
|
+
def unwrap(paserk) = Paserk.from_paserk(paserk:, wrapping_key: self)
|
107
113
|
|
108
114
|
sig(:final) { params(key: Interface::Key, nonce: T.nilable(String)).returns(String) }
|
109
|
-
def wrap(key, nonce: nil) = Paserk.wrap(key
|
115
|
+
def wrap(key, nonce: nil) = Paserk.wrap(key:, wrapping_key: self, nonce:)
|
110
116
|
|
111
117
|
private
|
112
118
|
|
data/lib/paseto/token.rb
CHANGED
@@ -34,7 +34,7 @@ module Paseto
|
|
34
34
|
payload = Util.decode64(payload)
|
35
35
|
Util.decode64(footer)
|
36
36
|
.then { |f| serializer.deserialize(f, options) }
|
37
|
-
.then { |f| new(version
|
37
|
+
.then { |f| new(version:, purpose:, payload:, footer: f) }
|
38
38
|
end
|
39
39
|
|
40
40
|
sig { returns(Paseto::Interface::Serializer) }
|
@@ -60,13 +60,14 @@ module Paseto
|
|
60
60
|
.then { |data| "#{version}.#{purpose}.#{data}" }
|
61
61
|
.then(&:freeze)
|
62
62
|
|
63
|
-
@version
|
64
|
-
@purpose
|
65
|
-
@raw_payload = T.let(payload.freeze,
|
66
|
-
@type
|
67
|
-
@footer
|
68
|
-
@raw_footer
|
69
|
-
@str
|
63
|
+
@version = T.let(version.freeze, String)
|
64
|
+
@purpose = T.let(purpose.freeze, String)
|
65
|
+
@raw_payload = T.let(payload.freeze, String)
|
66
|
+
@type = T.let(validate_header, T.class_of(Interface::Key))
|
67
|
+
@footer = T.let(footer, T.any(String, T::Hash[String, T.untyped]))
|
68
|
+
@raw_footer = T.let(raw_footer, String)
|
69
|
+
@str = T.let(paseto, String)
|
70
|
+
@result = T.let(nil, T.nilable(Result))
|
70
71
|
end
|
71
72
|
|
72
73
|
sig do
|
@@ -79,8 +80,8 @@ module Paseto
|
|
79
80
|
def decode!(key, implicit_assertion: '', **options)
|
80
81
|
return @result.claims if @result
|
81
82
|
|
82
|
-
key.decode(@str, implicit_assertion
|
83
|
-
.then { |result| @result =
|
83
|
+
key.decode(@str, implicit_assertion:, **options)
|
84
|
+
.then { |result| @result = result }
|
84
85
|
.then(&:claims)
|
85
86
|
end
|
86
87
|
|
@@ -116,12 +117,13 @@ module Paseto
|
|
116
117
|
|
117
118
|
sig { returns(T.class_of(Interface::Key)) }
|
118
119
|
def validate_header
|
119
|
-
type =
|
120
|
-
|
120
|
+
type = begin
|
121
|
+
TokenTypes.deserialize(header).key_klass
|
122
|
+
rescue KeyError
|
123
|
+
nil
|
124
|
+
end
|
121
125
|
|
122
|
-
raise UnsupportedToken, header
|
123
|
-
rescue KeyError
|
124
|
-
raise UnsupportedToken, header
|
126
|
+
type or raise UnsupportedToken, header
|
125
127
|
end
|
126
128
|
end
|
127
129
|
end
|
data/lib/paseto/token_types.rb
CHANGED
@@ -17,9 +17,9 @@ module Paseto
|
|
17
17
|
case self
|
18
18
|
in V3Local then V3::Local
|
19
19
|
in V3Public then V3::Public
|
20
|
-
in V4Local if Paseto
|
20
|
+
in V4Local if Paseto::HAS_RBNACL
|
21
21
|
V4::Local
|
22
|
-
in V4Public if Paseto
|
22
|
+
in V4Public if Paseto::HAS_RBNACL
|
23
23
|
V4::Public
|
24
24
|
else
|
25
25
|
nil
|
data/lib/paseto/util.rb
CHANGED
@@ -76,7 +76,7 @@ module Paseto
|
|
76
76
|
# Moving the sig out of the conditional triggers a bug in rubocop-sorbet
|
77
77
|
|
78
78
|
# Use a faster comparison when RbNaCl is available
|
79
|
-
if Paseto
|
79
|
+
if Paseto::HAS_RBNACL
|
80
80
|
sig { params(a: String, b: String).returns(T::Boolean) }
|
81
81
|
def self.constant_compare(a, b)
|
82
82
|
h_a = RbNaCl::Hash.blake2b(a)
|
data/lib/paseto/v3/local.rb
CHANGED
data/lib/paseto/v3/public.rb
CHANGED
@@ -50,7 +50,7 @@ module Paseto
|
|
50
50
|
raise LucidityError unless @key.group.curve_name == 'secp384r1'
|
51
51
|
raise InvalidKeyPair unless custom_check_key
|
52
52
|
|
53
|
-
@protocol = T.let(Protocol::Version3.
|
53
|
+
@protocol = T.let(Protocol::Version3.instance, Protocol::Version3)
|
54
54
|
|
55
55
|
super
|
56
56
|
rescue OpenSSL::PKey::ECError => e
|
@@ -68,7 +68,7 @@ module Paseto
|
|
68
68
|
.then { |data| @key.sign_raw(nil, data) }
|
69
69
|
.then { |sig_asn| ASN1::ECDSASignature.from_asn1(sig_asn) }
|
70
70
|
.then { |ecdsa_sig| ecdsa_sig.to_rs(SIGNATURE_PART_LEN) }
|
71
|
-
.then { |sig| Token.new(payload: "#{message}#{sig}", purpose
|
71
|
+
.then { |sig| Token.new(payload: "#{message}#{sig}", purpose:, version:, footer:) }
|
72
72
|
rescue Encoding::CompatibilityError
|
73
73
|
raise ParseError, 'invalid message encoding, must be UTF-8'
|
74
74
|
end
|
@@ -80,9 +80,10 @@ module Paseto
|
|
80
80
|
raise LucidityError unless header == token.header
|
81
81
|
|
82
82
|
payload = token.raw_payload
|
83
|
-
|
83
|
+
signature_end = payload.bytesize - SIGNATURE_BYTE_LEN
|
84
|
+
raise ParseError, 'message too short' if signature_end <= 0
|
84
85
|
|
85
|
-
m = T.must(payload.slice(0,
|
86
|
+
m = T.must(payload.slice(0, signature_end))
|
86
87
|
|
87
88
|
s = T.must(payload.slice(-SIGNATURE_BYTE_LEN, SIGNATURE_BYTE_LEN))
|
88
89
|
.then { |bytes| ASN1::ECDSASignature.from_rs(bytes, SIGNATURE_PART_LEN).to_der }
|
data/lib/paseto/v4/local.rb
CHANGED
@@ -21,7 +21,7 @@ module Paseto
|
|
21
21
|
|
22
22
|
sig(:final) { params(ikm: String).void }
|
23
23
|
def initialize(ikm:)
|
24
|
-
@protocol = T.let(Protocol::Version4.
|
24
|
+
@protocol = T.let(Protocol::Version4.instance, Paseto::Protocol::Version4)
|
25
25
|
|
26
26
|
super(ikm)
|
27
27
|
end
|
@@ -31,10 +31,10 @@ module Paseto
|
|
31
31
|
# Derive an encryption key, nonce, and authentication key from an input nonce.
|
32
32
|
sig(:final) { override.params(nonce: String).returns([String, String, String]) }
|
33
33
|
def calc_keys(nonce)
|
34
|
-
tmp = protocol.hmac("paseto-encryption-key#{nonce}", key
|
34
|
+
tmp = protocol.hmac("paseto-encryption-key#{nonce}", key:, digest_size: 56)
|
35
35
|
ek = T.must(tmp[0, 32])
|
36
36
|
n2 = T.must(tmp[-24, 24])
|
37
|
-
ak = protocol.hmac("paseto-auth-key-for-aead#{nonce}", key
|
37
|
+
ak = protocol.hmac("paseto-auth-key-for-aead#{nonce}", key:, digest_size: 32)
|
38
38
|
[ek, n2, ak]
|
39
39
|
end
|
40
40
|
|
data/lib/paseto/v4/public.rb
CHANGED
@@ -44,7 +44,7 @@ module Paseto
|
|
44
44
|
@key = T.let(key, T.any(RbNaCl::SigningKey, RbNaCl::VerifyKey))
|
45
45
|
|
46
46
|
@private = T.let(@key.is_a?(RbNaCl::SigningKey), T::Boolean)
|
47
|
-
@protocol = T.let(Protocol::Version4.
|
47
|
+
@protocol = T.let(Protocol::Version4.instance, Paseto::Protocol::Version4)
|
48
48
|
|
49
49
|
super
|
50
50
|
end
|
@@ -58,7 +58,7 @@ module Paseto
|
|
58
58
|
Util.pre_auth_encode(pae_header, message, footer, implicit_assertion)
|
59
59
|
.then { |m2| @key.sign(m2) }
|
60
60
|
.then { |sig| "#{message}#{sig}" }
|
61
|
-
.then { |payload| Token.new(payload
|
61
|
+
.then { |payload| Token.new(payload:, purpose:, version:, footer:) }
|
62
62
|
end
|
63
63
|
|
64
64
|
# Verify the signature of `token`, with an optional binding `implicit_assertion`. `token` must be a `v4.public`` type Token.
|
@@ -152,10 +152,7 @@ module Paseto
|
|
152
152
|
def ossl_ed25519_private_key?(key)
|
153
153
|
raise LucidityError, "expected Ed25519 key, got #{key.oid}" unless key.oid == 'ED25519'
|
154
154
|
|
155
|
-
|
156
|
-
return key.to_text != "<INVALID PRIVATE KEY>\n" if Util.openssl?(1, 1, 1)
|
157
|
-
|
158
|
-
false
|
155
|
+
key.to_text.start_with?('ED25519 Private-Key')
|
159
156
|
end
|
160
157
|
|
161
158
|
sig(:final) { returns(RbNaCl::VerifyKey) }
|
data/lib/paseto/validator.rb
CHANGED
@@ -29,7 +29,7 @@ module Paseto
|
|
29
29
|
return unless (aud = options[:verify_aud])
|
30
30
|
|
31
31
|
given = payload['aud']
|
32
|
-
raise InvalidAudience, "Invalid audience. Expected #{aud}, got #{given || '<none>'}"
|
32
|
+
raise InvalidAudience, "Invalid audience. Expected #{aud}, got #{given || '<none>'}" unless [*aud].intersect?([*given])
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
data/lib/paseto/version.rb
CHANGED
data/lib/paseto/versions.rb
CHANGED
@@ -17,8 +17,8 @@ module Paseto
|
|
17
17
|
sig { returns(Interface::Version) }
|
18
18
|
def instance
|
19
19
|
case self
|
20
|
-
when V3Version, V3Str, K3Str then Protocol::Version3.
|
21
|
-
when V4Version, V4Str, K4Str then Protocol::Version4.
|
20
|
+
when V3Version, V3Str, K3Str then Protocol::Version3.instance
|
21
|
+
when V4Version, V4Str, K4Str then Protocol::Version4.instance
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -13,33 +13,20 @@ module Paseto
|
|
13
13
|
DOMAIN_SEPARATOR_AUTH = "\x81"
|
14
14
|
DOMAIN_SEPARATOR_ENCRYPT = "\x80"
|
15
15
|
|
16
|
-
sig { override.
|
17
|
-
|
18
|
-
b = Util.decode64(data)
|
19
|
-
{
|
20
|
-
t: T.must(b.byteslice(0, 48)),
|
21
|
-
n: T.must(b.byteslice(48, 32)),
|
22
|
-
c: T.must(b.byteslice(80..))
|
23
|
-
}
|
24
|
-
end
|
16
|
+
sig { override.returns(String) }
|
17
|
+
attr_reader :local_header
|
25
18
|
|
26
19
|
sig { override.returns(Protocol::Version3) }
|
27
|
-
|
28
|
-
Protocol::Version3.new
|
29
|
-
end
|
20
|
+
attr_reader :protocol
|
30
21
|
|
31
22
|
sig { override.returns(String) }
|
32
|
-
|
33
|
-
'k3.local-wrap.pie.'
|
34
|
-
end
|
35
|
-
|
36
|
-
sig { override.returns(String) }
|
37
|
-
def secret_header
|
38
|
-
'k3.secret-wrap.pie.'
|
39
|
-
end
|
23
|
+
attr_reader :secret_header
|
40
24
|
|
41
25
|
sig { params(wrapping_key: SymmetricKey).void }
|
42
26
|
def initialize(wrapping_key)
|
27
|
+
@local_header = T.let('k3.local-wrap.pie.', String)
|
28
|
+
@protocol = T.let(Protocol::Version3.instance, Protocol::Version3)
|
29
|
+
@secret_header = T.let('k3.secret-wrap.pie.', String)
|
43
30
|
@wrapping_key = wrapping_key
|
44
31
|
end
|
45
32
|
|
@@ -53,6 +40,16 @@ module Paseto
|
|
53
40
|
protocol.hmac(payload, key: auth_key)
|
54
41
|
end
|
55
42
|
|
43
|
+
sig { override.params(data: String).returns({ t: String, n: String, c: String }) }
|
44
|
+
def decode_and_split(data)
|
45
|
+
b = Util.decode64(data)
|
46
|
+
{
|
47
|
+
t: T.must(b.byteslice(0, 48)),
|
48
|
+
n: T.must(b.byteslice(48, 32)),
|
49
|
+
c: T.must(b.byteslice(80..))
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
56
53
|
sig { override.returns(String) }
|
57
54
|
def random_nonce
|
58
55
|
protocol.random(32)
|
@@ -64,7 +61,7 @@ module Paseto
|
|
64
61
|
ek = T.must(x[0, 32])
|
65
62
|
n2 = T.must(x[32..])
|
66
63
|
|
67
|
-
protocol.crypt(key: ek, nonce: n2, payload:
|
64
|
+
protocol.crypt(key: ek, nonce: n2, payload:)
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
@@ -13,33 +13,20 @@ module Paseto
|
|
13
13
|
DOMAIN_SEPARATOR_AUTH = "\x81"
|
14
14
|
DOMAIN_SEPARATOR_ENCRYPT = "\x80"
|
15
15
|
|
16
|
-
sig { override.params(data: String).returns({ t: String, n: String, c: String }) }
|
17
|
-
def self.decode_and_split(data)
|
18
|
-
b = Util.decode64(data)
|
19
|
-
{
|
20
|
-
t: T.must(b.byteslice(0, 32)),
|
21
|
-
n: T.must(b.byteslice(32, 32)),
|
22
|
-
c: T.must(b.byteslice(64..))
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
16
|
sig { override.returns(Protocol::Version4) }
|
27
|
-
|
28
|
-
Protocol::Version4.new
|
29
|
-
end
|
17
|
+
attr_reader :protocol
|
30
18
|
|
31
19
|
sig { override.returns(String) }
|
32
|
-
|
33
|
-
'k4.local-wrap.pie.'
|
34
|
-
end
|
20
|
+
attr_reader :local_header
|
35
21
|
|
36
22
|
sig { override.returns(String) }
|
37
|
-
|
38
|
-
'k4.secret-wrap.pie.'
|
39
|
-
end
|
23
|
+
attr_reader :secret_header
|
40
24
|
|
41
25
|
sig { params(wrapping_key: SymmetricKey).void }
|
42
26
|
def initialize(wrapping_key)
|
27
|
+
@local_header = T.let('k4.local-wrap.pie.', String)
|
28
|
+
@protocol = T.let(Protocol::Version4.instance, Protocol::Version4)
|
29
|
+
@secret_header = T.let('k4.secret-wrap.pie.', String)
|
43
30
|
@wrapping_key = wrapping_key
|
44
31
|
end
|
45
32
|
|
@@ -53,6 +40,16 @@ module Paseto
|
|
53
40
|
protocol.hmac(payload, key: auth_key, digest_size: 32)
|
54
41
|
end
|
55
42
|
|
43
|
+
sig { override.params(data: String).returns({ t: String, n: String, c: String }) }
|
44
|
+
def decode_and_split(data)
|
45
|
+
b = Util.decode64(data)
|
46
|
+
{
|
47
|
+
t: T.must(b.byteslice(0, 32)),
|
48
|
+
n: T.must(b.byteslice(32, 32)),
|
49
|
+
c: T.must(b.byteslice(64..))
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
56
53
|
sig { override.returns(String) }
|
57
54
|
def random_nonce
|
58
55
|
protocol.random(32)
|
@@ -64,7 +61,7 @@ module Paseto
|
|
64
61
|
ek = T.must(x[0, 32])
|
65
62
|
n2 = T.must(x[32..])
|
66
63
|
|
67
|
-
protocol.crypt(key: ek, nonce: n2, payload:
|
64
|
+
protocol.crypt(key: ek, nonce: n2, payload:)
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
data/lib/paseto/wrappers/pie.rb
CHANGED
@@ -20,11 +20,11 @@ module Paseto
|
|
20
20
|
raise LucidityError unless key.version == @wrapping_key.version
|
21
21
|
|
22
22
|
nonce ||= @coder.random_nonce
|
23
|
-
header = pie_header
|
23
|
+
header = key.pie_header
|
24
24
|
|
25
|
-
c = @coder.crypt(nonce
|
25
|
+
c = @coder.crypt(nonce:, payload: key.to_bytes)
|
26
26
|
|
27
|
-
ak = @coder.authentication_key(nonce:
|
27
|
+
ak = @coder.authentication_key(nonce:)
|
28
28
|
t = @coder.authentication_tag(payload: "#{header}#{nonce}#{c}", auth_key: ak)
|
29
29
|
|
30
30
|
[header, Util.encode64("#{t}#{nonce}#{c}")].join
|
@@ -52,20 +52,6 @@ module Paseto
|
|
52
52
|
|
53
53
|
PaserkTypes.deserialize("#{version}.#{type}").generate(ptk)
|
54
54
|
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
sig { params(key: Interface::Key).returns(String) }
|
59
|
-
def pie_header(key)
|
60
|
-
case key
|
61
|
-
when SymmetricKey then @coder.local_header
|
62
|
-
when AsymmetricKey then @coder.secret_header
|
63
|
-
else
|
64
|
-
# :nocov:
|
65
|
-
raise ArgumentError, 'not a valid type of key'
|
66
|
-
# :nocov:
|
67
|
-
end
|
68
|
-
end
|
69
55
|
end
|
70
56
|
end
|
71
57
|
end
|
data/lib/paseto.rb
CHANGED
@@ -42,6 +42,8 @@ module Paseto
|
|
42
42
|
extend T::Sig
|
43
43
|
extend Configuration
|
44
44
|
|
45
|
+
HAS_RBNACL = T.let(!defined?(RbNaCl).nil?, T::Boolean)
|
46
|
+
|
45
47
|
class Error < StandardError; end
|
46
48
|
|
47
49
|
class AlgorithmError < Error; end
|
@@ -89,11 +91,6 @@ module Paseto
|
|
89
91
|
class ParseError < Error; end
|
90
92
|
# Tried to work with a V4 token without RbNaCl loaded
|
91
93
|
class UnsupportedToken < ParseError; end
|
92
|
-
|
93
|
-
sig { returns(T::Boolean) }
|
94
|
-
def self.rbnacl?
|
95
|
-
!!defined?(RbNaCl)
|
96
|
-
end
|
97
94
|
end
|
98
95
|
|
99
96
|
loader.eager_load
|
data/paseto.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
DESCRIPTION
|
18
18
|
spec.homepage = 'https://github.com/bannable/paseto'
|
19
19
|
spec.license = 'MIT'
|
20
|
-
spec.required_ruby_version = '>= 3.
|
20
|
+
spec.required_ruby_version = '>= 3.1.0'
|
21
21
|
|
22
22
|
spec.metadata = {
|
23
23
|
'bug_tracker_uri' => 'https://github.com/bannable/paseto/issues',
|
@@ -37,10 +37,10 @@ Gem::Specification.new do |spec|
|
|
37
37
|
end
|
38
38
|
spec.require_paths = ['lib']
|
39
39
|
|
40
|
-
spec.
|
41
|
-
spec.
|
42
|
-
spec.
|
43
|
-
spec.
|
40
|
+
spec.add_dependency 'multi_json', '~> 1.15.0'
|
41
|
+
spec.add_dependency 'openssl', '~> 3.3'
|
42
|
+
spec.add_dependency 'sorbet-runtime'
|
43
|
+
spec.add_dependency 'zeitwerk'
|
44
44
|
|
45
45
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
46
46
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
**/*.rbi linguist-vendored=true
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: true
|
2
2
|
|
3
3
|
# DO NOT EDIT MANUALLY
|
4
4
|
# This file was pulled from a central RBI files repository.
|
@@ -60,14 +60,14 @@ module Rainbow
|
|
60
60
|
class X11Named < Rainbow::Color::RGB
|
61
61
|
include Rainbow::X11ColorNames
|
62
62
|
|
63
|
+
sig { params(ground: Symbol, name: Symbol).void }
|
64
|
+
def initialize(ground, name); end
|
65
|
+
|
63
66
|
sig { returns(T::Array[Symbol]) }
|
64
67
|
def self.color_names; end
|
65
68
|
|
66
69
|
sig { returns(String) }
|
67
70
|
def self.valid_names; end
|
68
|
-
|
69
|
-
sig { params(ground: Symbol, name: Symbol).void }
|
70
|
-
def initialize(ground, name); end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -0,0 +1 @@
|
|
1
|
+
**/*.rbi linguist-generated=true
|
@@ -522,7 +522,7 @@ Diff::LCS::Change::VALID_ACTIONS = T.let(T.unsafe(nil), Array)
|
|
522
522
|
# elements in the old and the new sequenced enumerables as well as the action
|
523
523
|
# taken.
|
524
524
|
#
|
525
|
-
# source://diff-lcs//lib/diff/lcs/change.rb#
|
525
|
+
# source://diff-lcs//lib/diff/lcs/change.rb#100
|
526
526
|
class Diff::LCS::ContextChange < ::Diff::LCS::Change
|
527
527
|
# @return [ContextChange] a new instance of ContextChange
|
528
528
|
#
|
@@ -253,7 +253,7 @@ Docile::BacktraceFilter::FILTER_PATTERN = T.let(T.unsafe(nil), Regexp)
|
|
253
253
|
# @api private
|
254
254
|
# @see Docile.dsl_eval_immutable
|
255
255
|
#
|
256
|
-
# source://docile//lib/docile/chaining_fallback_context_proxy.rb#
|
256
|
+
# source://docile//lib/docile/chaining_fallback_context_proxy.rb#17
|
257
257
|
class Docile::ChainingFallbackContextProxy < ::Docile::FallbackContextProxy
|
258
258
|
# Proxy methods as in {FallbackContextProxy#method_missing}, replacing
|
259
259
|
# `receiver` with the returned value.
|