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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +55 -50
  4. data/lib/paseto/asn1/ecdsa_signature.rb +2 -2
  5. data/lib/paseto/asymmetric_key.rb +7 -4
  6. data/lib/paseto/configuration/decode_configuration.rb +7 -7
  7. data/lib/paseto/interface/key.rb +5 -2
  8. data/lib/paseto/interface/pbkd.rb +4 -20
  9. data/lib/paseto/interface/pie.rb +5 -26
  10. data/lib/paseto/interface/pke.rb +15 -51
  11. data/lib/paseto/interface/version.rb +30 -117
  12. data/lib/paseto/operations/id/i_dv3.rb +1 -1
  13. data/lib/paseto/operations/id/i_dv4.rb +1 -1
  14. data/lib/paseto/operations/pbkd/p_b_k_dv3.rb +4 -5
  15. data/lib/paseto/operations/pbkd/p_b_k_dv4.rb +3 -4
  16. data/lib/paseto/operations/pbkw.rb +6 -6
  17. data/lib/paseto/operations/pke/p_k_ev3.rb +23 -25
  18. data/lib/paseto/operations/pke/p_k_ev4.rb +33 -34
  19. data/lib/paseto/operations/pke.rb +9 -10
  20. data/lib/paseto/operations/wrap.rb +1 -1
  21. data/lib/paseto/paserk.rb +1 -1
  22. data/lib/paseto/paserk_types.rb +2 -2
  23. data/lib/paseto/protocol/version3.rb +17 -16
  24. data/lib/paseto/protocol/version4.rb +17 -16
  25. data/lib/paseto/symmetric_key.rb +16 -10
  26. data/lib/paseto/token.rb +17 -15
  27. data/lib/paseto/token_types.rb +2 -2
  28. data/lib/paseto/util.rb +1 -1
  29. data/lib/paseto/v3/local.rb +1 -1
  30. data/lib/paseto/v3/public.rb +5 -4
  31. data/lib/paseto/v4/local.rb +3 -3
  32. data/lib/paseto/v4/public.rb +3 -6
  33. data/lib/paseto/validator.rb +1 -1
  34. data/lib/paseto/version.rb +1 -1
  35. data/lib/paseto/versions.rb +2 -2
  36. data/lib/paseto/wrappers/pie/pie_v3.rb +18 -21
  37. data/lib/paseto/wrappers/pie/pie_v4.rb +17 -20
  38. data/lib/paseto/wrappers/pie.rb +3 -17
  39. data/lib/paseto.rb +2 -5
  40. data/paseto.gemspec +5 -5
  41. data/sorbet/rbi/annotations/.gitattributes +1 -0
  42. data/sorbet/rbi/annotations/rainbow.rbi +4 -4
  43. data/sorbet/rbi/gems/.gitattributes +1 -0
  44. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1 -1
  45. data/sorbet/rbi/gems/docile@1.4.0.rbi +1 -1
  46. data/sorbet/rbi/gems/{ffi@1.15.5.rbi → ffi@1.16.3.rbi} +260 -117
  47. data/sorbet/rbi/gems/{oj@3.14.2.rbi → oj@3.16.1.rbi} +26 -37
  48. data/sorbet/rbi/gems/{rake@13.0.6.rbi → rake@13.1.0.rbi} +75 -69
  49. data/sorbet/rbi/gems/rbnacl@7.1.1.rbi +2 -2
  50. data/sorbet/rbi/gems/{rspec-core@3.12.1.rbi → rspec-core@3.12.2.rbi} +1 -1
  51. data/sorbet/rbi/gems/{rspec-expectations@3.12.2.rbi → rspec-expectations@3.12.3.rbi} +27 -33
  52. data/sorbet/rbi/gems/{rspec-mocks@3.12.4.rbi → rspec-mocks@3.12.6.rbi} +60 -61
  53. data/sorbet/rbi/gems/{rspec-support@3.12.0.rbi → rspec-support@3.12.1.rbi} +35 -43
  54. data/sorbet/rbi/gems/rspec@3.12.0.rbi +22 -28
  55. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +41 -44
  56. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +232 -2
  57. data/sorbet/rbi/gems/{timecop@0.9.6.rbi → timecop@0.9.8.rbi} +13 -16
  58. data/sorbet/rbi/shims/multi_json.rbi +2 -0
  59. data/sorbet/rbi/shims/openssl.rbi +0 -8
  60. data/sorbet/rbi/todo.rbi +5 -1
  61. metadata +19 -42
  62. data/sorbet/rbi/gems/ast@2.4.2.rbi +0 -584
  63. data/sorbet/rbi/gems/io-console@0.6.0.rbi +0 -8
  64. data/sorbet/rbi/gems/irb@1.6.3.rbi +0 -342
  65. data/sorbet/rbi/gems/json@2.6.3.rbi +0 -1541
  66. data/sorbet/rbi/gems/multi_json@1.15.0.rbi +0 -267
  67. data/sorbet/rbi/gems/netrc@0.11.0.rbi +0 -158
  68. data/sorbet/rbi/gems/openssl@3.1.0.rbi +0 -1739
  69. data/sorbet/rbi/gems/parallel@1.22.1.rbi +0 -277
  70. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +0 -407
  71. data/sorbet/rbi/gems/regexp_parser@2.7.0.rbi +0 -3580
  72. data/sorbet/rbi/gems/reline@0.3.2.rbi +0 -8
  73. data/sorbet/rbi/gems/rexml@3.2.5.rbi +0 -4717
  74. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +0 -1317
  75. data/sorbet/rbi/gems/thor@1.2.1.rbi +0 -3956
  76. data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +0 -65
  77. data/sorbet/rbi/gems/webrick@1.7.0.rbi +0 -2555
  78. data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +0 -441
  79. data/sorbet/rbi/gems/yard@0.9.28.rbi +0 -17816
  80. data/sorbet/rbi/gems/zeitwerk@2.6.7.rbi +0 -8
@@ -8,144 +8,57 @@ module Paseto
8
8
  extend T::Helpers
9
9
 
10
10
  include Comparable
11
- include Kernel
12
11
 
13
12
  abstract!
14
13
 
15
- module ClassMethods
16
- extend T::Sig
17
- extend T::Helpers
14
+ sig { abstract.params(key: String, nonce: String, payload: String).returns(String) }
15
+ def crypt(key:, nonce:, payload:); end
18
16
 
19
- interface!
17
+ sig { abstract.params(data: String, digest_size: Integer).returns(String) }
18
+ def digest(data, digest_size:); end
20
19
 
21
- sig { abstract.params(key: String, nonce: String, payload: String).returns(String) }
22
- def crypt(key:, nonce:, payload:); end
20
+ sig { abstract.returns(Integer) }
21
+ def digest_bytes; end
23
22
 
24
- sig { abstract.params(data: String, digest_size: Integer).returns(String) }
25
- def digest(data, digest_size:); end
23
+ sig { abstract.params(data: String, key: String, digest_size: Integer).returns(String) }
24
+ def hmac(data, key:, digest_size: nil); end
26
25
 
27
- sig { abstract.returns(Integer) }
28
- def digest_bytes; end
26
+ sig { abstract.returns(Interface::ID) }
27
+ def id; end
29
28
 
30
- sig { abstract.params(data: String, key: String, digest_size: Integer).returns(String) }
31
- def hmac(data, key:, digest_size:); end
32
-
33
- sig { abstract.returns(Interface::ID) }
34
- def id; end
35
-
36
- sig do
37
- abstract.params(
38
- password: String,
39
- salt: String,
40
- length: Integer,
41
- parameters: Integer
42
- ).returns(String)
43
- end
44
- def kdf(password, salt:, length:, **parameters); end
45
-
46
- sig { abstract.returns(String) }
47
- def paserk_version; end
48
-
49
- sig { abstract.returns(String) }
50
- def pbkd_local_header; end
51
-
52
- sig { abstract.returns(String) }
53
- def pbkd_secret_header; end
54
-
55
- sig { abstract.params(password: String).returns(Interface::PBKD) }
56
- def pbkw(password); end
57
-
58
- sig { abstract.params(key: SymmetricKey).returns(Interface::PIE) }
59
- def pie(key); end
60
-
61
- sig { abstract.params(key: AsymmetricKey).returns(Interface::PKE) }
62
- def pke(key); end
63
-
64
- sig { abstract.params(size: Integer).returns(String) }
65
- def random(size); end
66
-
67
- sig { abstract.returns(String) }
68
- def version; end
69
- end
70
-
71
- mixes_in_class_methods(ClassMethods)
72
-
73
- sig(:final) { params(key: String, nonce: String, payload: String).returns(String) }
74
- def crypt(key:, nonce:, payload:)
75
- self.class.crypt(key: key, nonce: nonce, payload: payload)
76
- end
77
-
78
- sig(:final) { params(data: String, digest_size: T.nilable(Integer)).returns(String) }
79
- def digest(data, digest_size: nil)
80
- self.class.digest(data, digest_size: digest_size || digest_bytes)
81
- end
82
-
83
- sig(:final) { returns(Integer) }
84
- def digest_bytes
85
- self.class.digest_bytes
86
- end
87
-
88
- sig(:final) { params(data: String, key: String, digest_size: T.nilable(Integer)).returns(String) }
89
- def hmac(data, key:, digest_size: nil)
90
- self.class.hmac(data, key: key, digest_size: digest_size || digest_bytes)
91
- end
92
-
93
- sig(:final) { returns(Interface::ID) }
94
- def id
95
- self.class.id
96
- end
97
-
98
- sig(:final) do
99
- params(
29
+ sig do
30
+ abstract.params(
100
31
  password: String,
101
32
  salt: String,
102
33
  length: Integer,
103
- parameters: T.any(Symbol, Integer)
34
+ parameters: Integer
104
35
  ).returns(String)
105
36
  end
106
- def kdf(password, salt:, length:, **parameters)
107
- self.class.kdf(password, salt: salt, length: length, **parameters)
108
- end
37
+ def kdf(password, salt:, length:, **parameters); end
109
38
 
110
- sig(:final) { returns(String) }
111
- def paserk_version
112
- self.class.paserk_version
113
- end
39
+ sig { abstract.returns(String) }
40
+ def paserk_version; end
114
41
 
115
- sig(:final) { returns(String) }
116
- def pbkd_local_header
117
- self.class.pbkd_local_header
118
- end
42
+ sig { abstract.returns(String) }
43
+ def pbkd_local_header; end
119
44
 
120
- sig(:final) { returns(String) }
121
- def pbkd_secret_header
122
- self.class.pbkd_secret_header
123
- end
45
+ sig { abstract.returns(String) }
46
+ def pbkd_secret_header; end
124
47
 
125
- sig(:final) { params(password: String).returns(Interface::PBKD) }
126
- def pbkw(password)
127
- self.class.pbkw(password)
128
- end
48
+ sig { abstract.params(password: String).returns(Interface::PBKD) }
49
+ def pbkw(password); end
129
50
 
130
- sig(:final) { params(key: SymmetricKey).returns(Interface::PIE) }
131
- def pie(key)
132
- self.class.pie(key)
133
- end
51
+ sig { abstract.params(key: SymmetricKey).returns(Interface::PIE) }
52
+ def pie(key); end
134
53
 
135
- sig(:final) { params(key: AsymmetricKey).returns(Interface::PKE) }
136
- def pke(key)
137
- self.class.pke(key)
138
- end
54
+ sig { abstract.params(key: AsymmetricKey).returns(Interface::PKE) }
55
+ def pke(key); end
139
56
 
140
- sig(:final) { params(size: Integer).returns(String) }
141
- def random(size)
142
- self.class.random(size)
143
- end
57
+ sig { abstract.params(size: Integer).returns(String) }
58
+ def random(size); end
144
59
 
145
- sig(:final) { returns(String) }
146
- def version
147
- self.class.version
148
- end
60
+ sig { abstract.returns(String) }
61
+ def version; end
149
62
 
150
63
  sig(:final) { params(other: T.untyped).returns(T.nilable(Integer)) }
151
64
  def <=>(other)
@@ -12,7 +12,7 @@ module Paseto
12
12
 
13
13
  sig { override.returns(Protocol::Version3) }
14
14
  def self.protocol
15
- Protocol::Version3.new
15
+ Protocol::Version3.instance
16
16
  end
17
17
  end
18
18
  end
@@ -12,7 +12,7 @@ module Paseto
12
12
 
13
13
  sig { override.returns(Protocol::Version4) }
14
14
  def self.protocol
15
- Protocol::Version4.new
15
+ Protocol::Version4.instance
16
16
  end
17
17
  end
18
18
  end
@@ -11,13 +11,12 @@ module Paseto
11
11
  include Interface::PBKD
12
12
 
13
13
  sig { override.returns(Protocol::Version3) }
14
- def self.protocol
15
- Protocol::Version3.new
16
- end
14
+ attr_reader :protocol
17
15
 
18
16
  sig { params(password: String).void }
19
17
  def initialize(password)
20
18
  @password = password
19
+ @protocol = T.let(Protocol::Version3.instance, Protocol::Version3)
21
20
  end
22
21
 
23
22
  sig do
@@ -43,7 +42,7 @@ module Paseto
43
42
  sig { override.params(salt: String, params: T::Hash[Symbol, Integer]).returns(String) }
44
43
  def pre_key(salt:, params:)
45
44
  iterations = T.must(params[:iterations])
46
- protocol.kdf(@password, salt: salt, length: 32, iterations: iterations)
45
+ protocol.kdf(@password, salt:, length: 32, iterations:)
47
46
  end
48
47
 
49
48
  sig { override.returns(String) }
@@ -76,7 +75,7 @@ module Paseto
76
75
  nonce: T.must(data.byteslice(36, 16)),
77
76
  edk: T.must(data.byteslice(52, edk_len)),
78
77
  tag: T.must(data.byteslice(-48, 48)),
79
- params: { iterations: iterations }
78
+ params: { iterations: }
80
79
  }
81
80
  end
82
81
  end
@@ -11,13 +11,12 @@ module Paseto
11
11
  include Interface::PBKD
12
12
 
13
13
  sig { override.returns(Protocol::Version4) }
14
- def self.protocol
15
- Protocol::Version4.new
16
- end
14
+ attr_reader :protocol
17
15
 
18
16
  sig { params(password: String).void }
19
17
  def initialize(password)
20
18
  @password = password
19
+ @protocol = T.let(Protocol::Version4.instance, Protocol::Version4)
21
20
  end
22
21
 
23
22
  sig do
@@ -49,7 +48,7 @@ module Paseto
49
48
  def pre_key(salt:, params:)
50
49
  opslimit = T.must(params[:opslimit])
51
50
  memlimit = T.must(params[:memlimit])
52
- protocol.kdf(@password, salt: salt, length: 32, opslimit: opslimit, memlimit: memlimit)
51
+ protocol.kdf(@password, salt:, length: 32, opslimit:, memlimit:)
53
52
  end
54
53
 
55
54
  sig { override.returns(String) }
@@ -30,11 +30,11 @@ module Paseto
30
30
  salt = @coder.random_salt
31
31
  nonce = @coder.random_nonce
32
32
 
33
- pre_key = @coder.pre_key(salt: salt, params: opts)
33
+ pre_key = @coder.pre_key(salt:, params: opts)
34
34
 
35
- edk = @coder.crypt(payload: key.to_bytes, key: pre_key, nonce: nonce)
35
+ edk = @coder.crypt(payload: key.to_bytes, key: pre_key, nonce:)
36
36
 
37
- message, t = @coder.authenticate(header: h, pre_key: pre_key, salt: salt, nonce: nonce, edk: edk, params: opts)
37
+ message, t = @coder.authenticate(header: h, pre_key:, salt:, nonce:, edk:, params: opts)
38
38
 
39
39
  data = Util.encode64("#{message}#{t}")
40
40
  "#{h}.#{data}"
@@ -49,12 +49,12 @@ module Paseto
49
49
 
50
50
  @coder.decode(data) => {salt:, nonce:, edk:, tag:, params:}
51
51
 
52
- pre_key = @coder.pre_key(salt: salt, params: params)
52
+ pre_key = @coder.pre_key(salt:, params:)
53
53
 
54
- _, t2 = @coder.authenticate(header: header, pre_key: pre_key, salt: salt, nonce: nonce, edk: edk, params: params)
54
+ _, t2 = @coder.authenticate(header:, pre_key:, salt:, nonce:, edk:, params:)
55
55
  raise InvalidAuthenticator unless Util.constant_compare(t2, tag)
56
56
 
57
- ptk = @coder.crypt(payload: edk, key: pre_key, nonce: nonce)
57
+ ptk = @coder.crypt(payload: edk, key: pre_key, nonce:)
58
58
  PaserkTypes.deserialize(header).generate(ptk)
59
59
  end
60
60
 
@@ -10,28 +10,24 @@ module Paseto
10
10
 
11
11
  include Interface::PKE
12
12
 
13
- sig { override.params(esk: OpenSSL::PKey::EC).returns(String) }
14
- def self.epk_bytes_from_esk(esk)
15
- esk.public_key.to_octet_string(:compressed)
16
- end
13
+ sig { override.returns(Protocol::Version3) }
14
+ attr_reader :protocol
17
15
 
18
- sig(:final) { override.returns(OpenSSL::PKey::EC) }
19
- def self.generate_ephemeral_key
20
- OpenSSL::PKey::EC.generate('secp384r1')
21
- end
16
+ sig { override.returns(String) }
17
+ attr_reader :header
22
18
 
23
- sig(:final) { override.returns(String) }
24
- def self.header
25
- 'k3.seal.'
26
- end
19
+ sig { params(sealing_key: AsymmetricKey).void }
20
+ def initialize(sealing_key)
21
+ raise LucidityError unless sealing_key.is_a? V3::Public
27
22
 
28
- sig { override.returns(Protocol::Version3) }
29
- def self.protocol
30
- Protocol::Version3.new
23
+ @header = T.let('k3.seal.', String)
24
+ @protocol = T.let(Protocol::Version3.instance, Protocol::Version3)
25
+ @sealing_key = T.let(sealing_key, V3::Public)
26
+ @pk = T.let(@sealing_key.public_bytes, String)
31
27
  end
32
28
 
33
29
  sig { override.params(encoded_data: String).returns([String, OpenSSL::PKey::EC::Point, String]) }
34
- def self.split(encoded_data)
30
+ def split(encoded_data)
35
31
  data = Util.decode64(encoded_data)
36
32
 
37
33
  t = T.must(data.slice(0, 48))
@@ -44,14 +40,6 @@ module Paseto
44
40
  [t, epk, edk]
45
41
  end
46
42
 
47
- sig { params(sealing_key: AsymmetricKey).void }
48
- def initialize(sealing_key)
49
- raise LucidityError unless sealing_key.is_a? V3::Public
50
-
51
- @sealing_key = T.let(sealing_key, V3::Public)
52
- @pk = T.let(@sealing_key.public_bytes, String)
53
- end
54
-
55
43
  sig { override.params(message: String, ek: String, n: String).returns(SymmetricKey) }
56
44
  def decrypt(message:, ek:, n:)
57
45
  pdk = protocol.crypt(key: ek, nonce: n, payload: message)
@@ -67,7 +55,7 @@ module Paseto
67
55
  ek = T.must(x[0, 32])
68
56
  n = T.must(x[32, 16])
69
57
 
70
- { ek: ek, n: n }
58
+ { ek:, n: }
71
59
  end
72
60
 
73
61
  sig { override.params(xk: String, epk: OpenSSL::PKey::EC::Point).returns(String) }
@@ -81,6 +69,16 @@ module Paseto
81
69
  protocol.crypt(payload: message, key: ek, nonce: n)
82
70
  end
83
71
 
72
+ sig { override.params(esk: OpenSSL::PKey::EC).returns(String) }
73
+ def epk_bytes_from_esk(esk)
74
+ esk.public_key.to_octet_string(:compressed)
75
+ end
76
+
77
+ sig(:final) { override.returns(OpenSSL::PKey::EC) }
78
+ def generate_ephemeral_key
79
+ OpenSSL::PKey::EC.generate('secp384r1')
80
+ end
81
+
84
82
  sig { override.params(ak: String, epk: OpenSSL::PKey::EC::Point, edk: String).returns(String) }
85
83
  def tag(ak:, epk:, edk:)
86
84
  epk_bytes = epk.to_octet_string(:compressed)
@@ -10,44 +10,18 @@ module Paseto
10
10
 
11
11
  include Interface::PKE
12
12
 
13
- sig { override.params(esk: RbNaCl::PrivateKey).returns(String) }
14
- def self.epk_bytes_from_esk(esk)
15
- esk.public_key.to_bytes
16
- end
17
-
18
- sig(:final) { override.returns(RbNaCl::PrivateKey) }
19
- def self.generate_ephemeral_key
20
- RbNaCl::PrivateKey.generate
21
- end
22
-
23
- sig(:final) { override.returns(String) }
24
- def self.header
25
- 'k4.seal.'
26
- end
13
+ sig { override.returns(String) }
14
+ attr_reader :header
27
15
 
28
16
  sig { override.returns(Protocol::Version4) }
29
- def self.protocol
30
- Protocol::Version4.new
31
- end
32
-
33
- sig { override.params(encoded_data: String).returns([String, RbNaCl::PublicKey, String]) }
34
- def self.split(encoded_data)
35
- data = Util.decode64(encoded_data)
36
-
37
- t = T.must(data.slice(0, 32))
38
-
39
- epk_bytes = T.must(data.slice(32, 32))
40
- epk = RbNaCl::PublicKey.new(epk_bytes)
41
-
42
- edk = T.must(data.slice(64, 32))
43
-
44
- [t, epk, edk]
45
- end
17
+ attr_reader :protocol
46
18
 
47
19
  sig { params(sealing_key: AsymmetricKey).void }
48
20
  def initialize(sealing_key)
49
21
  raise LucidityError unless sealing_key.is_a? V4::Public
50
22
 
23
+ @header = T.let('k4.seal.', String)
24
+ @protocol = T.let(Protocol::Version4.instance, Protocol::Version4)
51
25
  @sealing_key = T.let(sealing_key, V4::Public)
52
26
  @pk = T.let(@sealing_key.x25519_public_key, RbNaCl::PublicKey)
53
27
  @pk_bytes = T.let(@pk.to_bytes, String)
@@ -61,13 +35,14 @@ module Paseto
61
35
 
62
36
  sig { override.params(xk: String, epk: RbNaCl::PublicKey).returns({ ek: String, n: String }) }
63
37
  def derive_ek_n(xk:, epk:)
38
+ epk_bytes = epk.to_bytes
64
39
  ek = protocol.digest(
65
- "#{DOMAIN_SEPARATOR_ENCRYPT}#{header}#{xk}#{epk.to_bytes}#{@pk_bytes}",
40
+ "#{DOMAIN_SEPARATOR_ENCRYPT}#{header}#{xk}#{epk_bytes}#{@pk_bytes}",
66
41
  digest_size: 32
67
42
  )
68
- n = protocol.digest("#{epk.to_bytes}#{@pk_bytes}", digest_size: 24)
43
+ n = protocol.digest("#{epk_bytes}#{@pk_bytes}", digest_size: 24)
69
44
 
70
- { ek: ek, n: n }
45
+ { ek:, n: }
71
46
  end
72
47
 
73
48
  sig { override.params(xk: String, epk: RbNaCl::PublicKey).returns(String) }
@@ -80,6 +55,30 @@ module Paseto
80
55
  protocol.crypt(payload: message, key: ek, nonce: n)
81
56
  end
82
57
 
58
+ sig { override.params(esk: RbNaCl::PrivateKey).returns(String) }
59
+ def epk_bytes_from_esk(esk)
60
+ esk.public_key.to_bytes
61
+ end
62
+
63
+ sig(:final) { override.returns(RbNaCl::PrivateKey) }
64
+ def generate_ephemeral_key
65
+ RbNaCl::PrivateKey.generate
66
+ end
67
+
68
+ sig { override.params(encoded_data: String).returns([String, RbNaCl::PublicKey, String]) }
69
+ def split(encoded_data)
70
+ data = Util.decode64(encoded_data)
71
+
72
+ t = T.must(data.slice(0, 32))
73
+
74
+ epk_bytes = T.must(data.slice(32, 32))
75
+ epk = RbNaCl::PublicKey.new(epk_bytes)
76
+
77
+ edk = T.must(data.slice(64, 32))
78
+
79
+ [t, epk, edk]
80
+ end
81
+
83
82
  sig { override.params(ak: String, epk: RbNaCl::PublicKey, edk: String).returns(String) }
84
83
  def tag(ak:, epk:, edk:)
85
84
  protocol.hmac("#{header}#{epk.to_bytes}#{edk}", key: ak, digest_size: 32)
@@ -22,12 +22,12 @@ module Paseto
22
22
 
23
23
  xk = @sealing_key.ecdh(esk)
24
24
 
25
- @coder.derive_ek_n(xk: xk, epk: epk) => {ek:, n:}
25
+ @coder.derive_ek_n(xk:, epk:) => {ek:, n:}
26
26
 
27
- edk = @coder.encrypt(message: key.to_bytes, ek: ek, n: n)
27
+ edk = @coder.encrypt(message: key.to_bytes, ek:, n:)
28
28
 
29
- ak = @coder.derive_ak(xk: xk, epk: epk)
30
- t = @coder.tag(ak: ak, epk: epk, edk: edk)
29
+ ak = @coder.derive_ak(xk:, epk:)
30
+ t = @coder.tag(ak:, epk:, edk:)
31
31
 
32
32
  epk_bytes = @coder.epk_bytes_from_esk(esk)
33
33
  data = Util.encode64("#{t}#{epk_bytes}#{edk}")
@@ -37,20 +37,19 @@ module Paseto
37
37
  sig { params(paserk: String).returns(Interface::Key) }
38
38
  def unseal(paserk)
39
39
  paserk.split('.') => [version, type, encoded_data]
40
- raise LucidityError unless version == @sealing_key.paserk_version
41
- raise LucidityError unless type == 'seal'
40
+ raise LucidityError unless version == @sealing_key.paserk_version && type == 'seal'
42
41
 
43
42
  t, epk, edk = @coder.split(encoded_data)
44
43
 
45
44
  xk = @sealing_key.ecdh(epk)
46
45
 
47
- ak = @coder.derive_ak(xk: xk, epk: epk)
48
- t2 = @coder.tag(ak: ak, epk: epk, edk: edk)
46
+ ak = @coder.derive_ak(xk:, epk:)
47
+ t2 = @coder.tag(ak:, epk:, edk:)
49
48
  raise InvalidAuthenticator unless Util.constant_compare(t, t2)
50
49
 
51
- @coder.derive_ek_n(xk: xk, epk: epk) => {ek:, n:}
50
+ @coder.derive_ek_n(xk:, epk:) => {ek:, n:}
52
51
 
53
- @coder.decrypt(message: edk, ek: ek, n: n)
52
+ @coder.decrypt(message: edk, ek:, n:)
54
53
  end
55
54
  end
56
55
  end
@@ -22,7 +22,7 @@ module Paseto
22
22
 
23
23
  sig { params(key: Interface::Key, wrapping_key: SymmetricKey, nonce: T.nilable(String)).returns(String) }
24
24
  def self.wrap(key, wrapping_key:, nonce: nil)
25
- Wrappers::PIE.new(wrapping_key).encode(key, nonce: nonce)
25
+ Wrappers::PIE.new(wrapping_key).encode(key, nonce:)
26
26
  end
27
27
  end
28
28
  end
data/lib/paseto/paserk.rb CHANGED
@@ -39,7 +39,7 @@ module Paseto
39
39
 
40
40
  sig { params(key: Interface::Key, wrapping_key: SymmetricKey, nonce: T.nilable(String)).returns(String) }
41
41
  def self.wrap(key:, wrapping_key:, nonce: nil)
42
- Operations::Wrap.wrap(key, wrapping_key: wrapping_key, nonce: nonce)
42
+ Operations::Wrap.wrap(key, wrapping_key:, nonce:)
43
43
  end
44
44
 
45
45
  sig { params(key: Interface::Key, password: String, options: T::Hash[Symbol, T.any(Integer, Symbol)]).returns(String) }
@@ -32,9 +32,9 @@ module Paseto
32
32
  V3::Public.from_scalar_bytes(input)
33
33
  in K3Public
34
34
  V3::Public.from_public_bytes(input)
35
- in K4LocalWrap | K4LocalPBKW | K4Local if Paseto.rbnacl? && input.bytesize == 32
35
+ in K4LocalWrap | K4LocalPBKW | K4Local if Paseto::HAS_RBNACL && input.bytesize == 32
36
36
  V4::Local.new(ikm: input)
37
- in K4SecretWrap | K4SecretPBKW | K4Secret if Paseto.rbnacl? && input.bytesize == 64
37
+ in K4SecretWrap | K4SecretPBKW | K4Secret if Paseto::HAS_RBNACL && input.bytesize == 64
38
38
  V4::Public.from_keypair(input)
39
39
  in K4Public
40
40
  V4::Public.from_public_bytes(input)
@@ -8,10 +8,11 @@ module Paseto
8
8
  extend T::Sig
9
9
  extend T::Helpers
10
10
 
11
+ include Singleton
11
12
  include Interface::Version
12
13
 
13
14
  sig(:final) { override.params(key: String, nonce: String, payload: String).returns(String) }
14
- def self.crypt(key:, nonce:, payload:)
15
+ def crypt(key:, nonce:, payload:)
15
16
  cipher = OpenSSL::Cipher.new('aes-256-ctr')
16
17
  cipher.key = key
17
18
  cipher.iv = nonce
@@ -19,22 +20,22 @@ module Paseto
19
20
  end
20
21
 
21
22
  sig(:final) { override.params(data: String, digest_size: Integer).returns(String) }
22
- def self.digest(data, digest_size:)
23
+ def digest(data, digest_size: 48)
23
24
  T.must(OpenSSL::Digest.digest('SHA384', data).byteslice(0, digest_size))
24
25
  end
25
26
 
26
27
  sig(:final) { override.returns(Integer) }
27
- def self.digest_bytes
28
+ def digest_bytes
28
29
  48
29
30
  end
30
31
 
31
32
  sig(:final) { override.params(data: String, key: String, digest_size: Integer).returns(String) }
32
- def self.hmac(data, key:, digest_size:)
33
+ def hmac(data, key:, digest_size: 48)
33
34
  T.must(OpenSSL::HMAC.digest('SHA384', key, data).byteslice(0, digest_size))
34
35
  end
35
36
 
36
37
  sig(:final) { override.returns(T.class_of(Operations::ID::IDv3)) }
37
- def self.id
38
+ def id
38
39
  Operations::ID::IDv3
39
40
  end
40
41
 
@@ -46,53 +47,53 @@ module Paseto
46
47
  parameters: Integer
47
48
  ).returns(String)
48
49
  end
49
- def self.kdf(password, salt:, length:, **parameters)
50
+ def kdf(password, salt:, length:, **parameters)
50
51
  OpenSSL::KDF.pbkdf2_hmac(
51
52
  password,
52
- salt: salt,
53
- length: length,
53
+ salt:,
54
+ length:,
54
55
  iterations: T.must(parameters[:iterations]),
55
56
  hash: 'SHA384'
56
57
  )
57
58
  end
58
59
 
59
60
  sig(:final) { override.returns(String) }
60
- def self.paserk_version
61
+ def paserk_version
61
62
  'k3'
62
63
  end
63
64
 
64
65
  sig(:final) { override.returns(String) }
65
- def self.pbkd_local_header
66
+ def pbkd_local_header
66
67
  'k3.local-pw'
67
68
  end
68
69
 
69
70
  sig(:final) { override.returns(String) }
70
- def self.pbkd_secret_header
71
+ def pbkd_secret_header
71
72
  'k3.secret-pw'
72
73
  end
73
74
 
74
75
  sig(:final) { override.params(password: String).returns(Operations::PBKD::PBKDv3) }
75
- def self.pbkw(password)
76
+ def pbkw(password)
76
77
  Operations::PBKD::PBKDv3.new(password)
77
78
  end
78
79
 
79
80
  sig(:final) { override.params(key: SymmetricKey).returns(Wrappers::PIE::PieV3) }
80
- def self.pie(key)
81
+ def pie(key)
81
82
  Wrappers::PIE::PieV3.new(key)
82
83
  end
83
84
 
84
85
  sig(:final) { override.params(key: AsymmetricKey).returns(Operations::PKE::PKEv3) }
85
- def self.pke(key)
86
+ def pke(key)
86
87
  Operations::PKE::PKEv3.new(key)
87
88
  end
88
89
 
89
90
  sig(:final) { override.params(size: Integer).returns(String) }
90
- def self.random(size)
91
+ def random(size)
91
92
  SecureRandom.random_bytes(size)
92
93
  end
93
94
 
94
95
  sig(:final) { override.returns(String) }
95
- def self.version
96
+ def version
96
97
  'v3'
97
98
  end
98
99
  end