ruby-paseto 0.1.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 (116) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +8 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +549 -0
  6. data/lib/paseto/asn1/algorithm_identifier.rb +17 -0
  7. data/lib/paseto/asn1/curve_private_key.rb +22 -0
  8. data/lib/paseto/asn1/ec_private_key.rb +27 -0
  9. data/lib/paseto/asn1/ecdsa_full_r.rb +26 -0
  10. data/lib/paseto/asn1/ecdsa_sig_value.rb +23 -0
  11. data/lib/paseto/asn1/ecdsa_signature.rb +49 -0
  12. data/lib/paseto/asn1/ed25519_identifier.rb +15 -0
  13. data/lib/paseto/asn1/named_curve.rb +17 -0
  14. data/lib/paseto/asn1/one_asymmetric_key.rb +32 -0
  15. data/lib/paseto/asn1/private_key.rb +17 -0
  16. data/lib/paseto/asn1/private_key_algorithm_identifier.rb +17 -0
  17. data/lib/paseto/asn1/public_key.rb +17 -0
  18. data/lib/paseto/asn1/subject_public_key_info.rb +28 -0
  19. data/lib/paseto/asn1.rb +101 -0
  20. data/lib/paseto/asymmetric_key.rb +100 -0
  21. data/lib/paseto/configuration/box.rb +23 -0
  22. data/lib/paseto/configuration/decode_configuration.rb +68 -0
  23. data/lib/paseto/configuration.rb +18 -0
  24. data/lib/paseto/interface/i_d.rb +23 -0
  25. data/lib/paseto/interface/key.rb +113 -0
  26. data/lib/paseto/interface/pbkd.rb +83 -0
  27. data/lib/paseto/interface/pie.rb +59 -0
  28. data/lib/paseto/interface/pke.rb +86 -0
  29. data/lib/paseto/interface/serializer.rb +19 -0
  30. data/lib/paseto/interface/version.rb +161 -0
  31. data/lib/paseto/interface/wrapper.rb +20 -0
  32. data/lib/paseto/operations/i_d.rb +48 -0
  33. data/lib/paseto/operations/id/i_dv3.rb +20 -0
  34. data/lib/paseto/operations/id/i_dv4.rb +20 -0
  35. data/lib/paseto/operations/pbkd/p_b_k_dv3.rb +85 -0
  36. data/lib/paseto/operations/pbkd/p_b_k_dv4.rb +94 -0
  37. data/lib/paseto/operations/pbkw.rb +73 -0
  38. data/lib/paseto/operations/pke/p_k_ev3.rb +97 -0
  39. data/lib/paseto/operations/pke/p_k_ev4.rb +95 -0
  40. data/lib/paseto/operations/pke.rb +57 -0
  41. data/lib/paseto/operations/wrap.rb +29 -0
  42. data/lib/paseto/paserk.rb +55 -0
  43. data/lib/paseto/paserk_types.rb +46 -0
  44. data/lib/paseto/protocol/version3.rb +100 -0
  45. data/lib/paseto/protocol/version4.rb +99 -0
  46. data/lib/paseto/result.rb +9 -0
  47. data/lib/paseto/serializer/optional_json.rb +30 -0
  48. data/lib/paseto/serializer/raw.rb +23 -0
  49. data/lib/paseto/sodium/curve_25519.rb +46 -0
  50. data/lib/paseto/sodium/safe_ed25519_loader.rb +19 -0
  51. data/lib/paseto/sodium/stream/base.rb +82 -0
  52. data/lib/paseto/sodium/stream/x_cha_cha20_xor.rb +31 -0
  53. data/lib/paseto/sodium.rb +5 -0
  54. data/lib/paseto/symmetric_key.rb +119 -0
  55. data/lib/paseto/token.rb +127 -0
  56. data/lib/paseto/token_types.rb +29 -0
  57. data/lib/paseto/util.rb +105 -0
  58. data/lib/paseto/v3/local.rb +63 -0
  59. data/lib/paseto/v3/public.rb +204 -0
  60. data/lib/paseto/v4/local.rb +56 -0
  61. data/lib/paseto/v4/public.rb +169 -0
  62. data/lib/paseto/validator.rb +154 -0
  63. data/lib/paseto/verifiers/footer.rb +30 -0
  64. data/lib/paseto/verifiers/payload.rb +42 -0
  65. data/lib/paseto/verify.rb +48 -0
  66. data/lib/paseto/version.rb +6 -0
  67. data/lib/paseto/versions.rb +25 -0
  68. data/lib/paseto/wrappers/pie/pie_v3.rb +72 -0
  69. data/lib/paseto/wrappers/pie/pie_v4.rb +72 -0
  70. data/lib/paseto/wrappers/pie.rb +71 -0
  71. data/lib/paseto.rb +99 -0
  72. data/paseto.gemspec +58 -0
  73. data/sorbet/config +3 -0
  74. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  75. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  76. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
  77. data/sorbet/rbi/gems/docile@1.4.0.rbi +376 -0
  78. data/sorbet/rbi/gems/ffi@1.15.5.rbi +1994 -0
  79. data/sorbet/rbi/gems/io-console@0.5.11.rbi +8 -0
  80. data/sorbet/rbi/gems/irb@1.5.1.rbi +342 -0
  81. data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
  82. data/sorbet/rbi/gems/multi_json@1.15.0.rbi +267 -0
  83. data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  84. data/sorbet/rbi/gems/oj@3.13.23.rbi +603 -0
  85. data/sorbet/rbi/gems/openssl@3.0.1.rbi +1735 -0
  86. data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  87. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +407 -0
  88. data/sorbet/rbi/gems/rake@13.0.6.rbi +3021 -0
  89. data/sorbet/rbi/gems/rbnacl@7.1.1.rbi +3218 -0
  90. data/sorbet/rbi/gems/regexp_parser@2.6.1.rbi +3481 -0
  91. data/sorbet/rbi/gems/reline@0.3.1.rbi +8 -0
  92. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
  93. data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10887 -0
  94. data/sorbet/rbi/gems/rspec-expectations@3.12.0.rbi +8090 -0
  95. data/sorbet/rbi/gems/rspec-mocks@3.12.0.rbi +5300 -0
  96. data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1617 -0
  97. data/sorbet/rbi/gems/rspec@3.12.0.rbi +88 -0
  98. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +1239 -0
  99. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +219 -0
  100. data/sorbet/rbi/gems/simplecov@0.21.2.rbi +2135 -0
  101. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +8 -0
  102. data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
  103. data/sorbet/rbi/gems/timecop@0.9.6.rbi +350 -0
  104. data/sorbet/rbi/gems/unicode-display_width@2.3.0.rbi +48 -0
  105. data/sorbet/rbi/gems/webrick@1.7.0.rbi +2555 -0
  106. data/sorbet/rbi/gems/yard-sorbet@0.7.0.rbi +391 -0
  107. data/sorbet/rbi/gems/yard@0.9.28.rbi +17816 -0
  108. data/sorbet/rbi/gems/zeitwerk@2.6.6.rbi +950 -0
  109. data/sorbet/rbi/shims/multi_json.rbi +19 -0
  110. data/sorbet/rbi/shims/openssl.rbi +111 -0
  111. data/sorbet/rbi/shims/rbnacl.rbi +65 -0
  112. data/sorbet/rbi/shims/zeitwerk.rbi +6 -0
  113. data/sorbet/rbi/todo.rbi +7 -0
  114. data/sorbet/tapioca/config.yml +30 -0
  115. data/sorbet/tapioca/require.rb +12 -0
  116. metadata +376 -0
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class AlgorithmIdentifier < T::Struct
7
+ extend T::Sig
8
+
9
+ const :algorithm, NamedCurve
10
+
11
+ sig { returns(OpenSSL::ASN1::Sequence) }
12
+ def build
13
+ OpenSSL::ASN1::Sequence.new(algorithm.build)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class CurvePrivateKey < T::Struct
7
+ extend T::Sig
8
+
9
+ const :private_key, String
10
+
11
+ sig { returns(OpenSSL::ASN1::OctetString) }
12
+ def build
13
+ OpenSSL::ASN1::OctetString.new(private_key)
14
+ end
15
+
16
+ sig { returns(String) }
17
+ def to_der
18
+ build.to_der
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class ECPrivateKey < T::Struct
7
+ extend T::Sig
8
+
9
+ const :private_key, String
10
+
11
+ sig { returns(OpenSSL::ASN1::Sequence) }
12
+ def build
13
+ OpenSSL::ASN1::Sequence.new(
14
+ [
15
+ OpenSSL::ASN1::Integer.new(1),
16
+ OpenSSL::ASN1::OctetString.new(private_key)
17
+ ]
18
+ )
19
+ end
20
+
21
+ sig { returns(String) }
22
+ def to_der
23
+ build.to_der
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class ECDSAFullR < T::Struct
7
+ extend T::Sig
8
+
9
+ const :r, OpenSSL::PKey::EC::Point
10
+ const :s, OpenSSL::BN
11
+
12
+ sig { returns(OpenSSL::ASN1::Sequence) }
13
+ def build
14
+ # Unsupported by OpenSSL 3.0
15
+ # :nocov:
16
+ OpenSSL::ASN1::Sequence.new(
17
+ [
18
+ OpenSSL::ASN1::OctetString.new(r.to_octet_string(:compressed)),
19
+ OpenSSL::ASN1::Integer.new(s)
20
+ ]
21
+ )
22
+ # :nocov:
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class ECDSASigValue < T::Struct
7
+ extend T::Sig
8
+
9
+ const :r, OpenSSL::BN
10
+ const :s, OpenSSL::BN
11
+
12
+ sig { returns(OpenSSL::ASN1::Sequence) }
13
+ def build
14
+ OpenSSL::ASN1::Sequence.new(
15
+ [
16
+ OpenSSL::ASN1::Integer.new(r),
17
+ OpenSSL::ASN1::Integer.new(s)
18
+ ]
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class ECDSASignature < T::Struct
7
+ extend T::Sig
8
+
9
+ const :signature, T.any(ECDSASigValue, ECDSAFullR)
10
+
11
+ sig { params(bytes: String, part_len: Integer).returns(ECDSASignature) }
12
+ def self.from_rs(bytes, part_len)
13
+ r = OpenSSL::BN.new(T.must(bytes[0, part_len]), 2)
14
+ s = OpenSSL::BN.new(T.must(bytes[-part_len, part_len]), 2)
15
+ new(signature: ECDSASigValue.new(r: r, s: s))
16
+ end
17
+
18
+ sig { params(sig: String).returns(ECDSASignature) }
19
+ def self.from_asn1(sig)
20
+ r, s = OpenSSL::ASN1.decode(sig).value.map(&:value)
21
+ new(signature: ECDSASigValue.new(r: r, s: s))
22
+ end
23
+
24
+ sig { returns(OpenSSL::ASN1::Sequence) }
25
+ def build
26
+ signature.build
27
+ end
28
+
29
+ sig { returns(String) }
30
+ def to_der
31
+ build.to_der
32
+ end
33
+
34
+ sig { params(part_len: Integer).returns(String) }
35
+ def to_rs(part_len)
36
+ case signature
37
+ when ECDSASigValue
38
+ r = T.cast(signature.r, OpenSSL::BN).to_s(2).rjust(part_len, "\x00")
39
+ when ECDSAFullR
40
+ # :nocov:
41
+ r = T.cast(signature.r, OpenSSL::PKey::EC::Point).to_octet_string(:compressed).rjust(part_len, "\x00")
42
+ # :nocov:
43
+ end
44
+ s = signature.s.to_s(2).rjust(part_len, "\x00")
45
+ [r, s].join
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class Ed25519Identifier < T::Struct
7
+ extend T::Sig
8
+
9
+ sig { returns([OpenSSL::ASN1::ObjectId]) }
10
+ def build
11
+ [OpenSSL::ASN1::ObjectId('ED25519')]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class NamedCurve < T::Struct
7
+ extend T::Sig
8
+
9
+ const :curve_name, String
10
+
11
+ sig { returns([OpenSSL::ASN1::ObjectId, OpenSSL::ASN1::ObjectId]) }
12
+ def build
13
+ [OpenSSL::ASN1::ObjectId('id-ecPublicKey'), OpenSSL::ASN1::ObjectId(curve_name)]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class OneAsymmetricKey < T::Struct
7
+ extend T::Sig
8
+
9
+ const :version, OpenSSL::BN
10
+ const :algorithm, PrivateKeyAlgorithmIdentifier
11
+ const :private_key, PrivateKey
12
+ const :public_key, T.nilable(PublicKey)
13
+
14
+ sig { returns(OpenSSL::ASN1::Sequence) }
15
+ def build
16
+ OpenSSL::ASN1::Sequence.new(
17
+ [
18
+ OpenSSL::ASN1::Integer.new(version),
19
+ algorithm.build,
20
+ private_key.build
21
+ # public_key&.build
22
+ ].compact
23
+ )
24
+ end
25
+
26
+ sig { returns(String) }
27
+ def to_der
28
+ build.to_der
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class PrivateKey < T::Struct
7
+ extend T::Sig
8
+
9
+ const :private_key, T.any(ECPrivateKey, CurvePrivateKey)
10
+
11
+ sig { returns(OpenSSL::ASN1::OctetString) }
12
+ def build
13
+ OpenSSL::ASN1::OctetString.new(private_key.to_der)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class PrivateKeyAlgorithmIdentifier < T::Struct
7
+ extend T::Sig
8
+
9
+ const :parameters, T.any(Ed25519Identifier, NamedCurve)
10
+
11
+ sig { returns(OpenSSL::ASN1::Sequence) }
12
+ def build
13
+ OpenSSL::ASN1::Sequence.new(parameters.build)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class PublicKey < T::Struct
7
+ extend T::Sig
8
+
9
+ const :public_key, String
10
+
11
+ sig { returns(OpenSSL::ASN1::BitString) }
12
+ def build
13
+ OpenSSL::ASN1::BitString.new(public_key)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ class SubjectPublicKeyInfo < T::Struct
7
+ extend T::Sig
8
+
9
+ const :algorithm_identifier, AlgorithmIdentifier
10
+ const :public_key, PublicKey
11
+
12
+ sig { returns(OpenSSL::ASN1::Sequence) }
13
+ def build
14
+ OpenSSL::ASN1::Sequence.new(
15
+ [
16
+ algorithm_identifier.build,
17
+ public_key.build
18
+ ]
19
+ )
20
+ end
21
+
22
+ sig { returns(String) }
23
+ def to_der
24
+ build.to_der
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,101 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module ASN1
6
+ # References:
7
+ # https://www.rfc-editor.org/rfc/rfc5208 PKCS #8: Private-Key Information Syntax Specification Version 1.2
8
+ # https://www.rfc-editor.org/rfc/rfc5480 Elliptic Curve Cryptography Subject Public Key Information
9
+ # https://www.rfc-editor.org/rfc/rfc5915 Elliptic Curve Private Key Structure
10
+ # https://www.rfc-editor.org/rfc/rfc5958 Asymmetric Key Packages (obsoletes PKCS#8)
11
+ # https://www.rfc-editor.org/rfc/rfc8018 PKCS #5: Password-Based Cryptography Specification Version 2.1
12
+ # https://www.secg.org/sec1-v2.pdf
13
+
14
+ extend T::Sig
15
+
16
+ sig { params(bytes: String).returns(String) }
17
+ def self.p384_scalar_bytes_to_oak_der(bytes)
18
+ OneAsymmetricKey.new(
19
+ version: OpenSSL::BN.new(1),
20
+ algorithm: PrivateKeyAlgorithmIdentifier.new(
21
+ parameters: NamedCurve.new(curve_name: 'secp384r1')
22
+ ),
23
+ private_key: PrivateKey.new(
24
+ private_key: ECPrivateKey.new(
25
+ private_key: bytes
26
+ )
27
+ )
28
+ ).to_der
29
+ end
30
+
31
+ sig { params(bytes: String).returns(String) }
32
+ def self.p384_public_bytes_to_spki_der(bytes)
33
+ SubjectPublicKeyInfo.new(
34
+ algorithm_identifier: AlgorithmIdentifier.new(
35
+ algorithm: NamedCurve.new(curve_name: 'secp384r1')
36
+ ),
37
+ public_key: PublicKey.new(
38
+ public_key: bytes
39
+ )
40
+ ).to_der
41
+ end
42
+
43
+ # RbNaCl::SigningKey.keypair_bytes returns the 32-byte private scalar and group element
44
+ # as (s || g), so we repack that into an ASN1 structure and then Base64 the resulting DER
45
+ # to get a PEM.
46
+ sig { params(bytes: String).returns(String) }
47
+ def self.ed25519_rs_to_oak_der(bytes)
48
+ OneAsymmetricKey.new(
49
+ version: OpenSSL::BN.new(0),
50
+ algorithm: PrivateKeyAlgorithmIdentifier.new(
51
+ parameters: Ed25519Identifier.new
52
+ ),
53
+ private_key: PrivateKey.new(
54
+ private_key: CurvePrivateKey.new(
55
+ private_key: T.must(bytes.byteslice(0, 32))
56
+ )
57
+ )
58
+ ).to_der
59
+ end
60
+
61
+ sig { params(bytes: String).returns(String) }
62
+ def self.ed25519_rs_to_oak_pem(bytes)
63
+ der_to_private_pem(ed25519_rs_to_oak_der(bytes))
64
+ end
65
+
66
+ sig { params(verify_key: String).returns(String) }
67
+ def self.ed25519_pubkey_nacl_to_der(verify_key)
68
+ OpenSSL::ASN1::Sequence.new(
69
+ [
70
+ OpenSSL::ASN1::Sequence.new(
71
+ [OpenSSL::ASN1::ObjectId.new('ED25519')]
72
+ ),
73
+ OpenSSL::ASN1::BitString.new(verify_key)
74
+ ]
75
+ ).to_der
76
+ end
77
+
78
+ sig { params(verify_key: String).returns(String) }
79
+ def self.ed25519_pubkey_nacl_to_pem(verify_key)
80
+ der_to_public_pem(ed25519_pubkey_nacl_to_der(verify_key))
81
+ end
82
+
83
+ sig { params(der: String).returns(String) }
84
+ def self.der_to_public_pem(der)
85
+ <<~PEM
86
+ -----BEGIN PUBLIC KEY-----
87
+ #{Base64.strict_encode64(der)}
88
+ -----END PUBLIC KEY-----
89
+ PEM
90
+ end
91
+
92
+ sig { params(der: String).returns(String) }
93
+ def self.der_to_private_pem(der)
94
+ <<~PEM
95
+ -----BEGIN PRIVATE KEY-----
96
+ #{Base64.strict_encode64(der)}
97
+ -----END PRIVATE KEY-----
98
+ PEM
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,100 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ class AsymmetricKey < Interface::Key
6
+ extend T::Sig
7
+ extend T::Helpers
8
+
9
+ abstract!
10
+
11
+ sig(:final) { override.returns(String) }
12
+ attr_reader :id, :paserk
13
+
14
+ sig(:final) { returns(String) }
15
+ attr_reader :pid, :public_paserk
16
+
17
+ sig { params(_key: T.untyped).void }
18
+ def initialize(_key)
19
+ @public_paserk = T.let("#{paserk_version}.public.#{Util.encode64(public_bytes)}".freeze, String)
20
+
21
+ @pid = T.let(Operations::ID.pid(self).freeze, String)
22
+
23
+ if private?
24
+ @paserk = T.let("#{paserk_version}.secret.#{Util.encode64(to_bytes)}".freeze, String)
25
+ @id = T.let(Operations::ID.sid(self).freeze, String)
26
+ else
27
+ @paserk = @public_paserk
28
+ @id = T.let(@pid, String)
29
+ end
30
+ end
31
+
32
+ sig { abstract.params(message: String, footer: String, implicit_assertion: String).returns(Token) }
33
+ def sign(message:, footer: '', implicit_assertion: ''); end
34
+
35
+ sig { abstract.params(token: Token, implicit_assertion: String).returns(String) }
36
+ def verify(token:, implicit_assertion: ''); end
37
+
38
+ sig { abstract.returns(String) }
39
+ def public_to_pem; end
40
+
41
+ sig { abstract.returns(String) }
42
+ def private_to_pem; end
43
+
44
+ sig { abstract.returns(T::Boolean) }
45
+ def private?; end
46
+
47
+ sig { abstract.returns(String) }
48
+ def public_bytes; end
49
+
50
+ sig { abstract.params(other: T.untyped).returns(String) }
51
+ def ecdh(other); end
52
+
53
+ sig(:final) do
54
+ override.params(
55
+ payload: T::Hash[String, T.untyped],
56
+ footer: String,
57
+ implicit_assertion: String,
58
+ options: T.nilable(T.any(String, Integer, Symbol, T::Boolean))
59
+ ).returns(String)
60
+ end
61
+ def encode!(payload, footer: '', implicit_assertion: '', **options)
62
+ MultiJson.dump(payload, options)
63
+ .then { |json| sign(message: json, footer: footer, implicit_assertion: implicit_assertion) }
64
+ .then(&:to_s)
65
+ end
66
+
67
+ sig(:final) do
68
+ override.params(
69
+ payload: String,
70
+ implicit_assertion: String,
71
+ options: T.nilable(T.any(Proc, String, Integer, Symbol, T::Boolean))
72
+ ).returns(Result)
73
+ end
74
+ def decode!(payload, implicit_assertion: '', **options)
75
+ token = Token.parse(payload)
76
+
77
+ verify(token: token, implicit_assertion: implicit_assertion)
78
+ .then { |json| MultiJson.load(json, **options) }
79
+ .then { |claims| Result.new(claims: claims, footer: token.footer) }
80
+ end
81
+
82
+ sig(:final) { override.returns(String) }
83
+ def pbkw_header = protocol.pbkd_secret_header
84
+
85
+ sig(:final) { override.returns(String) }
86
+ def purpose = 'public'
87
+
88
+ sig(:final) { returns(Interface::PKE) }
89
+ def pke = protocol.pke(self)
90
+
91
+ sig(:final) { returns(String) }
92
+ def sid = @sid ||= T.let(Operations::ID.sid(self), T.nilable(String))
93
+
94
+ sig(:final) { params(other: SymmetricKey).returns(String) }
95
+ def seal(other) = Paserk.seal(sealing_key: self, key: other)
96
+
97
+ sig(:final) { params(paserk: String).returns(SymmetricKey) }
98
+ def unseal(paserk) = Paserk.from_paserk(paserk: paserk, unsealing_key: self)
99
+ end
100
+ end
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module Configuration
6
+ class Box
7
+ extend T::Sig
8
+
9
+ sig { returns(DecodeConfiguration) }
10
+ attr_accessor :decode
11
+
12
+ sig { void }
13
+ def initialize
14
+ @decode = T.let(DecodeConfiguration.new, DecodeConfiguration)
15
+ end
16
+
17
+ sig { void }
18
+ def reset!
19
+ @decode = DecodeConfiguration.new
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,68 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module Configuration
6
+ class DecodeConfiguration
7
+ extend T::Sig
8
+
9
+ sig { returns(Interface::Serializer) }
10
+ attr_accessor :footer_serializer
11
+
12
+ sig { returns(T::Boolean) }
13
+ attr_accessor :verify_exp, :verify_nbf, :verify_iat
14
+
15
+ sig { returns(T.any(FalseClass, String)) }
16
+ attr_accessor :verify_sub
17
+
18
+ sig { returns(T.any(FalseClass, T::Array[String])) }
19
+ attr_accessor :verify_aud
20
+
21
+ sig { returns(T.any(T::Array[T.any(String, Regexp, T.proc.params(issuer: String).returns(T::Boolean))], FalseClass)) }
22
+ attr_accessor :verify_iss
23
+
24
+ sig do
25
+ returns(T.any(
26
+ T::Boolean,
27
+ T.proc.params(jti: String).returns(T::Boolean)
28
+ ))
29
+ end
30
+ attr_accessor :verify_jti
31
+
32
+ sig { void }
33
+ def initialize # rubocop:disable Metrics/AbcSize
34
+ @footer_serializer = T.let(Serializer::OptionalJson, Interface::Serializer)
35
+ @verify_exp = T.let(true, T::Boolean)
36
+ @verify_nbf = T.let(true, T::Boolean)
37
+ @verify_iat = T.let(true, T::Boolean)
38
+
39
+ @verify_iss = T.let(false, T.any(FalseClass,
40
+ T::Array[
41
+ T.any(String, Regexp, T.proc.params(issuer: String).returns(T::Boolean))
42
+ ]))
43
+
44
+ @verify_aud = T.let(false, T.any(FalseClass, T::Array[String]))
45
+
46
+ @verify_sub = T.let(false, T.any(FalseClass, String))
47
+
48
+ @verify_jti = T.let(false, T.any(
49
+ T::Boolean,
50
+ T.proc.params(jti: String).returns(T::Boolean)
51
+ ))
52
+ end
53
+
54
+ sig { returns(T::Hash[Symbol, T.untyped]) }
55
+ def to_h
56
+ {
57
+ verify_exp: verify_exp,
58
+ verify_nbf: verify_nbf,
59
+ verify_iss: verify_iss,
60
+ verify_iat: verify_iat,
61
+ verify_jti: verify_jti,
62
+ verify_aud: verify_aud,
63
+ verify_sub: verify_sub
64
+ }
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module Configuration
6
+ extend T::Sig
7
+
8
+ sig { params(blk: T.proc.params(config: Paseto::Configuration::Box).void).void }
9
+ def configure(&blk) # rubocop:disable Lint/UnusedMethodArgument
10
+ yield(config)
11
+ end
12
+
13
+ sig { returns(Paseto::Configuration::Box) }
14
+ def config
15
+ @config ||= T.let(Configuration::Box.new, T.nilable(Paseto::Configuration::Box))
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Paseto
5
+ module Interface
6
+ module ID
7
+ extend T::Sig
8
+ extend T::Helpers
9
+
10
+ abstract!
11
+
12
+ sig(:final) { params(type: String, paserk: String).returns(String) }
13
+ def encode(type, paserk)
14
+ header = "#{protocol.paserk_version}.#{type}."
15
+ d = protocol.digest("#{header}#{paserk}", digest_size: 33)
16
+ "#{header}#{Util.encode64(d)}"
17
+ end
18
+
19
+ sig { abstract.returns(Interface::Version) }
20
+ def protocol; end
21
+ end
22
+ end
23
+ end