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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5a6ccf377d7535330c1b0bf829685b548afc257e9a4e6b24b746e3e311485f2
4
- data.tar.gz: ce2ebaa4d4d354cbc6c1145aa129e4b143f352b6346bff34462c6c729b2b9951
3
+ metadata.gz: a58c81dd9d66d7512b70184c48f9dce92e1f3a798d0a1dccc7b795e09becc048
4
+ data.tar.gz: 48064247e0d0dbaa082ca8b602f89bcf5728d923169f51c0a079bb2f1302731f
5
5
  SHA512:
6
- metadata.gz: 68befb60265a2a408f6066aebafd118477eaeaa6c0161b120e1550199e473b27713ba68c2e042f3e13e338aca648edfbc198b7584ae513b4c9b3a78cedd282ba
7
- data.tar.gz: 8e3ed014b61f2b71e9f04a0b9ab06fd6d5485735f33670ee4d75e92425e4905072d73cc9271808601d64537192c218b2429f65166069257f31f187355770e4fd
6
+ metadata.gz: c21dedaf0227394479b5258ee07acacf2135e1e3be4c86f3e838f95cd8827713a086b575af0c93b27237c7b73492f15ac576b8828b27ba6735c8bc6fbcd16b9f
7
+ data.tar.gz: fb379b133bdcd64cd09cecefc3edd507a6627291c5b02dece8ab5ab10d64870b2dcc0c8a04a92481e11d692eee1d55af8c8d57711719a76675d010b3ef2fc5bf
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ - Minimum ruby version 3.0 -> 3.1
4
+ - Remove support for OpenSSL 1.1.1
5
+ - Remove support for ruby/openssl 3.0.x
6
+ - Refactor how version protocols are implemented to greatly improve sorbet coverage
7
+ - `Paseto.rbnacl?` is replaced by `Paseto::HAS_RBNACL`
8
+ - Fix decoding of multibyte characters in payloads, #216 thanks to @pelted @levicole
9
+
3
10
  ## [0.1.2]
4
11
 
5
12
  - Fixed versioning in 0.1.1 changelog
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Paseto
2
+
2
3
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rubystyle.guide) [![CircleCI](https://dl.circleci.com/status-badge/img/gh/bannable/paseto/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/bannable/paseto/tree/main) [![Maintainability](https://api.codeclimate.com/v1/badges/0bc8fcc6751880b68a9c/maintainability)](https://codeclimate.com/github/bannable/paseto/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/0bc8fcc6751880b68a9c/test_coverage)](https://codeclimate.com/github/bannable/paseto/test_coverage)
3
4
 
4
5
  This is an implementation of the [PASETO token protocol](https://github.com/paseto-standard/paseto-spec), written in Ruby, which supports versions [v3](https://github.com/paseto-standard/paseto-spec/tree/master/docs/01-Protocol-Versions#version-3-nist-modern) and [v4](https://github.com/paseto-standard/paseto-spec/tree/master/docs/01-Protocol-Versions#version-4-sodium-modern). This library passes all [official test vectors](https://github.com/paseto-standard/test-vectors) for supported versions and purposes.
@@ -11,14 +12,15 @@ Additionally, the library uses [Sorbet](https://sorbet.org) to enforce types at
11
12
 
12
13
  **Optional for v4.local tokens support**: Handling v4.local tokens requires [`RbNaCl`](https://github.com/RubyCrypto/rbnacl) with `libsodium 1.0.0` or newer.
13
14
 
14
- You can find instructions for obtaining libsodium at https://libsodium.org.
15
+ You can find instructions for obtaining libsodium at [libsodium.org](https://libsodium.org).
15
16
 
16
17
  If you do not intend to create or parse `v4.local` tokens, feel free to skip this dependency.
17
18
 
18
- ### Using Bundler:
19
+ ### Using Bundler
19
20
 
20
21
  Add the following to your Gemfile:
21
- ```
22
+
23
+ ```ruby
22
24
  gem 'ruby-paseto'
23
25
  # and optionally:
24
26
  gem 'rbnacl', '~> 7.1.1'
@@ -29,26 +31,26 @@ Then, run `bundle install` and `require 'paseto'`.
29
31
  ## Supported PASETO versions
30
32
 
31
33
  `paseto` supports these PASETO versions and purposes:
32
- | purpose | v4 | v3 |
33
- | ---------| ---- | ---- |
34
- | `local` | | |
35
- | `public` | | |
34
+ | purpose | v4 | v3 |
35
+ | -------- | --- | --- |
36
+ | `local` | | |
37
+ | `public` | | |
36
38
 
37
39
  ## Support for PASERK types
38
40
 
39
- | | v4 | v3 |
40
- | ------------- | ---- | ---- |
41
- | [`lid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/lid.md) | | |
42
- | [`sid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/sid.md) | | |
43
- | [`pid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/pid.md) | | |
44
- | [`local`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local.md) | | |
45
- | [`secret`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret.md) | | |
46
- | [`public`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/public.md) | | |
47
- | [`seal`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/seal.md) | | |
48
- | [`local-wrap`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local-wrap.md) | | |
49
- | [`secret-wrap`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret-wrap.md) | | |
50
- | [`local-pw`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local-pw.md) | | |
51
- | [`secret-pw`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret-pw.md) | | |
41
+ | | v4 | v3 |
42
+ | ----------------------------------------------------------------------------------------------------------------------------- | --- | --- |
43
+ | [`lid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/lid.md) | | |
44
+ | [`sid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/sid.md) | | |
45
+ | [`pid`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/pid.md) | | |
46
+ | [`local`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local.md) | | |
47
+ | [`secret`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret.md) | | |
48
+ | [`public`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/public.md) | | |
49
+ | [`seal`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/seal.md) | | |
50
+ | [`local-wrap`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local-wrap.md) | | |
51
+ | [`secret-wrap`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret-wrap.md) | | |
52
+ | [`local-pw`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/local-pw.md) | | |
53
+ | [`secret-pw`](https://github.com/paseto-standard/paserk/blob/8cc4934687a3c9235387d005fb79eec33f43166d/types/secret-pw.md) | | |
52
54
 
53
55
  ## Implementation Guideline compliance
54
56
 
@@ -167,6 +169,7 @@ signer.pid # => "k4.pid.5g4..." (PASERK Type pid)
167
169
  verifier.pid # => same as above!
168
170
  verifier.id # => same as above
169
171
  ```
172
+
170
173
  ## PASETO/PASERK v4, Sodium Modern
171
174
 
172
175
  [Description](https://github.com/paseto-standard/paseto-spec/tree/master/docs/01-Protocol-Versions#version-4-nist-modern) and [Specification](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md).
@@ -310,8 +313,8 @@ key == secret_key
310
313
 
311
314
  ### Version 4, Argon2id Parameters
312
315
 
313
- | param | allowed values | default |
314
- | :--------: | :---------: | :-----: |
316
+ | param | allowed values | default |
317
+ | :--------: | :---------------: | :------------: |
315
318
  | `opslimit` | Symbol \| Integer | `:interactive` |
316
319
  | `memlimit` | Symbol \| Integer | `:interactive` |
317
320
 
@@ -319,12 +322,11 @@ Allowed symbol values are `:interactive`, `:moderate` and `:sensitive` as descri
319
322
 
320
323
  You most likely do not want to use the `:interactive` default in production. See [libsodium's documentation](https://libsodium.gitbook.io/doc/~/revisions/-LL5wcLSbESuQhMZUBZo/password_hashing/the_argon2i_function#guidelines-for-choosing-the-parameters) for parameter guidance.
321
324
 
322
-
323
325
  ### Version 3, PBKDF2 Parameters
324
326
 
325
- | param | allowed values | default |
326
- | :--------: | :---------: | :-----: |
327
- | `iterations` | Integer | `100_000` |
327
+ | param | allowed values | default |
328
+ | :----------: | :------------: | :-------: |
329
+ | `iterations` | Integer | `100_000` |
328
330
 
329
331
  As with the Version 4 parameters above, you most likely do not want to use the default value and should pick an `iterations` value with time objectives similar to the argon2 guidance.
330
332
 
@@ -332,13 +334,14 @@ As with the Version 4 parameters above, you most likely do not want to use the d
332
334
 
333
335
  PASETO [reserves some claim names](https://github.com/paseto-standard/paseto-spec/blob/master/docs/02-Implementation-Guide/04-Claims.md) for particular use in the protocol, and this gem supports verification of all reserved claims.
334
336
 
335
- In the default configuration, the follow claims are verified when present: `exp`, `nbf` and `iat`
337
+ In the default configuration, the following claims are verified when present: `exp`, `nbf` and `iat`
336
338
 
337
339
  Verification behavior can be controlled by passing a kwarg for the setting to `decode` calls, or through library-level configuration.
338
340
 
339
341
  ## Default Configuration
340
342
 
341
343
  See the appropriate section below for more information on configuring each `verify_foo`.
344
+
342
345
  ```ruby
343
346
  Paseto.configure do |config|
344
347
  # Controls the behavior of footer deserialization in Result objects.
@@ -359,9 +362,9 @@ end
359
362
 
360
363
  ## Audience Claim
361
364
 
362
- | claim type | config type | default |
363
- | :--------: | :---------: | :-----: |
364
- | String | False \| String \| Array[String] | `false` |
365
+ | claim type | config type | default |
366
+ | :--------: | :------------------------------: | :-----: |
367
+ | String | False \| String \| Array[String] | `false` |
365
368
 
366
369
  ```ruby
367
370
  crypt = Paseto::V4::Local.generate
@@ -379,7 +382,7 @@ crypt.decode(payload, verify_aud: audience) # => { 'aud' => ... }
379
382
 
380
383
  | claim type | config type | default |
381
384
  | :--------: | :---------: | :-----: |
382
- | DateTime | Boolean | `true` |
385
+ | DateTime | Boolean | `true` |
383
386
 
384
387
  ```ruby
385
388
  crypt = Paseto::V4::Local.generate
@@ -396,7 +399,7 @@ crypt.decode(payload, verify_exp: false) # { 'exp' => ... }
396
399
 
397
400
  | claim type | config type | default |
398
401
  | :--------: | :---------: | :-----: |
399
- | DateTime | Boolean | `true` |
402
+ | DateTime | Boolean | `true` |
400
403
 
401
404
  ```ruby
402
405
  crypt = Paseto::V4::Local.generate
@@ -411,9 +414,9 @@ crypt.decode(payload, verify_iat: false) # { 'iat' => ... }
411
414
 
412
415
  ### Issuer Claim
413
416
 
414
- | claim type | config type | default |
415
- | :--------: | :---------: | :-----: |
416
- | String | Boolean \| String \| Regexp \| Proc | `false` |
417
+ | claim type | config type | default |
418
+ | :--------: | :---------------------------------: | :-----: |
419
+ | String | Boolean \| String \| Regexp \| Proc | `false` |
417
420
 
418
421
  ```ruby
419
422
  crypt = Paseto::V4::Local.generate
@@ -440,7 +443,7 @@ crypt.decode(payload, verify_issuer: true) # { 'iss' => ... }
440
443
 
441
444
  | claim type | config type | default |
442
445
  | :--------: | :---------: | :-----: |
443
- | DateTime | Boolean | `true` |
446
+ | DateTime | Boolean | `true` |
444
447
 
445
448
  ```ruby
446
449
  crypt = Paseto::V4::Local.generate
@@ -454,9 +457,9 @@ crypt.decode(payload, verify_nbf: false) # => { 'nbf' => ... }
454
457
 
455
458
  ### Subject Claim
456
459
 
457
- | claim type | config type | default |
458
- | :--------: | :---------: | :-----: |
459
- | String | False \| String | `false` |
460
+ | claim type | config type | default |
461
+ | :--------: | :-------------: | :-----: |
462
+ | String | False \| String | `false` |
460
463
 
461
464
  ```ruby
462
465
  crypt = Paseto::V4::Local.generate
@@ -469,9 +472,9 @@ crypt.decode(payload, verify_sub: 'example.org') # => Paseto::InvalidSubject
469
472
 
470
473
  ### Token Identifier Claim
471
474
 
472
- | claim type | config type | default |
473
- | :--------: | :---------: | :-----: |
474
- | String | Boolean \| String \| Proc | `false` |
475
+ | claim type | config type | default |
476
+ | :--------: | :-----------------------: | :-----: |
477
+ | String | Boolean \| String \| Proc | `false` |
475
478
 
476
479
  ```ruby
477
480
  crypt = Paseto::V4::Local.generate
@@ -479,17 +482,17 @@ hash = { data: 'data' }
479
482
  payload = crypt.encode(hash)
480
483
 
481
484
  # Require presence
482
- crypt.decode(payload, verify_jti: true)) # => Paseto::InvalidTokenIdentifier
485
+ crypt.decode(payload, verify_jti: true) # => Paseto::InvalidTokenIdentifier
483
486
 
484
487
  # Require exact value
485
488
  hash[:jti] = 'foo'
486
489
  payload = crypt.encode(payload: hash)
487
- crypt.decode(payload, verify_jti: 'foo')) # { 'data' => ... }
488
- crypt.decode(payload, verify_jti: 'bar')) # Paseto::InvalidTokenIdentifier
490
+ crypt.decode(payload, verify_jti: 'foo') # { 'data' => ... }
491
+ crypt.decode(payload, verify_jti: 'bar') # Paseto::InvalidTokenIdentifier
489
492
 
490
493
  # Or something more complex
491
494
  jti_proc = ->(jti) { jti == 'bar'}
492
- crypt.decode(payload, verify_jti: jti_proc)) # Paseto::InvalidTokenIdentifier
495
+ crypt.decode(payload, verify_jti: jti_proc) # Paseto::InvalidTokenIdentifier
493
496
  ```
494
497
 
495
498
  ## Development
@@ -512,7 +515,7 @@ You can learn more over at the `sorbet` [documentation](https://sorbet.org/docs/
512
515
 
513
516
  The tests are written with rspec. [Appraisal](https://github.com/thoughtbot/appraisal) is used to ensure compatibility with 3rd party dependencies providing cryptographic features.
514
517
 
515
- ```
518
+ ```sh
516
519
  bundle install
517
520
  appraisal install
518
521
  # in parallel
@@ -524,19 +527,21 @@ appraisal rake specs
524
527
  ### Updating RBI Files
525
528
 
526
529
  To check that RBI files for gems are up-to-date:
527
- ```
530
+
531
+ ```sh
528
532
  appraisal rbnacl bin/tapioca gems --verify
529
533
  ```
530
534
 
531
535
  To update RBI files for gems:
532
- ```
536
+
537
+ ```sh
533
538
  appraisal rbnacl bin/tapioca gems
534
539
  appraisal rbnacl bin/tapioca annotations
535
540
  ```
536
541
 
537
542
  ## Contributing
538
543
 
539
- Bug reports and pull requests are welcome on GitHub at https://github.com/bannable/paseto.
544
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/bannable/paseto).
540
545
 
541
546
  This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](CODE_OF_CONDUCT.md).
542
547
 
@@ -12,13 +12,13 @@ module Paseto
12
12
  def self.from_rs(bytes, part_len)
13
13
  r = OpenSSL::BN.new(T.must(bytes[0, part_len]), 2)
14
14
  s = OpenSSL::BN.new(T.must(bytes[-part_len, part_len]), 2)
15
- new(signature: ECDSASigValue.new(r: r, s: s))
15
+ new(signature: ECDSASigValue.new(r:, s:))
16
16
  end
17
17
 
18
18
  sig { params(sig: String).returns(ECDSASignature) }
19
19
  def self.from_asn1(sig)
20
20
  r, s = OpenSSL::ASN1.decode(sig).value.map(&:value)
21
- new(signature: ECDSASigValue.new(r: r, s: s))
21
+ new(signature: ECDSASigValue.new(r:, s:))
22
22
  end
23
23
 
24
24
  sig { returns(OpenSSL::ASN1::Sequence) }
@@ -60,7 +60,7 @@ module Paseto
60
60
  end
61
61
  def encode!(payload, footer: '', implicit_assertion: '', **options)
62
62
  MultiJson.dump(payload, options)
63
- .then { |json| sign(message: json, footer: footer, implicit_assertion: implicit_assertion) }
63
+ .then { |json| sign(message: json, footer:, implicit_assertion:) }
64
64
  .then(&:to_s)
65
65
  end
66
66
 
@@ -74,14 +74,17 @@ module Paseto
74
74
  def decode!(payload, implicit_assertion: '', **options)
75
75
  token = Token.parse(payload)
76
76
 
77
- verify(token: token, implicit_assertion: implicit_assertion)
77
+ verify(token:, implicit_assertion:)
78
78
  .then { |json| MultiJson.load(json, **options) }
79
- .then { |claims| Result.new(claims: claims, footer: token.footer) }
79
+ .then { |claims| Result.new(claims:, footer: token.footer) }
80
80
  end
81
81
 
82
82
  sig(:final) { override.returns(String) }
83
83
  def pbkw_header = protocol.pbkd_secret_header
84
84
 
85
+ sig(:final) { override.returns(String) }
86
+ def pie_header = "#{paserk_version}.secret-wrap.pie."
87
+
85
88
  sig(:final) { override.returns(String) }
86
89
  def purpose = 'public'
87
90
 
@@ -95,6 +98,6 @@ module Paseto
95
98
  def seal(other) = Paserk.seal(sealing_key: self, key: other)
96
99
 
97
100
  sig(:final) { params(paserk: String).returns(SymmetricKey) }
98
- def unseal(paserk) = Paserk.from_paserk(paserk: paserk, unsealing_key: self)
101
+ def unseal(paserk) = Paserk.from_paserk(paserk:, unsealing_key: self)
99
102
  end
100
103
  end
@@ -54,13 +54,13 @@ module Paseto
54
54
  sig { returns(T::Hash[Symbol, T.untyped]) }
55
55
  def to_h
56
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
57
+ verify_exp:,
58
+ verify_nbf:,
59
+ verify_iss:,
60
+ verify_iat:,
61
+ verify_jti:,
62
+ verify_aud:,
63
+ verify_sub:
64
64
  }
65
65
  end
66
66
  end
@@ -41,6 +41,9 @@ module Paseto
41
41
  sig { abstract.returns(String) }
42
42
  def pbkw_header; end
43
43
 
44
+ sig { abstract.returns(String) }
45
+ def pie_header; end
46
+
44
47
  sig { abstract.returns(Version) }
45
48
  def protocol; end
46
49
 
@@ -58,7 +61,7 @@ module Paseto
58
61
  ).returns(Result)
59
62
  end
60
63
  def decode(payload, implicit_assertion: '', **options)
61
- decode!(payload, **T.unsafe(implicit_assertion: implicit_assertion, **options))
64
+ decode!(payload, **T.unsafe(implicit_assertion:, **options))
62
65
  .then { |result| Verify.verify(result, options) }
63
66
  end
64
67
 
@@ -83,7 +86,7 @@ module Paseto
83
86
  def encode(payload, footer: '', implicit_assertion: '', **options)
84
87
  footer = MultiJson.dump(footer, mode: :object) if footer.is_a?(Hash)
85
88
  default_claims.merge(payload)
86
- .then { |claims| encode!(claims, footer: footer, implicit_assertion: implicit_assertion, **options) }
89
+ .then { |claims| encode!(claims, footer:, implicit_assertion:, **options) }
87
90
  end
88
91
 
89
92
  sig(:final) { params(other: T.untyped).returns(T::Boolean) }
@@ -7,22 +7,8 @@ module Paseto
7
7
  extend T::Sig
8
8
  extend T::Helpers
9
9
 
10
- include Kernel
11
-
12
10
  abstract!
13
11
 
14
- module ClassMethods
15
- extend T::Sig
16
- extend T::Helpers
17
-
18
- interface!
19
-
20
- sig { abstract.returns(Interface::Version) }
21
- def protocol; end
22
- end
23
-
24
- mixes_in_class_methods(ClassMethods)
25
-
26
12
  sig do
27
13
  abstract.params(
28
14
  header: String,
@@ -33,13 +19,13 @@ module Paseto
33
19
  params: T::Hash[Symbol, Integer]
34
20
  ).returns([String, String])
35
21
  end
36
- def authenticate(header:, pre_key:, salt:, nonce:, edk:, params:); end # rubocop:disable Metrics/ParameterLists
22
+ def authenticate(header:, pre_key:, salt:, nonce:, edk:, params:); end # rubocop:disable Metrics/ParameterLists
37
23
 
38
24
  sig(:final) { params(payload: String, key: String, nonce: String).returns(String) }
39
25
  def crypt(payload:, key:, nonce:)
40
26
  ek = protocol.digest("#{Operations::PBKW::DOMAIN_SEPARATOR_ENCRYPT}#{key}", digest_size: 32)
41
27
 
42
- protocol.crypt(key: ek, nonce: nonce, payload: payload)
28
+ protocol.crypt(key: ek, nonce:, payload:)
43
29
  end
44
30
 
45
31
  sig do
@@ -63,10 +49,8 @@ module Paseto
63
49
  protocol.paserk_version
64
50
  end
65
51
 
66
- sig(:final) { returns(Interface::Version) }
67
- def protocol
68
- self.class.protocol
69
- end
52
+ sig { abstract.returns(Interface::Version) }
53
+ def protocol; end
70
54
 
71
55
  sig { abstract.returns(String) }
72
56
  def random_nonce; end
@@ -8,25 +8,8 @@ module Paseto
8
8
  extend T::Sig
9
9
  extend T::Helpers
10
10
 
11
- include Kernel
12
-
13
11
  abstract!
14
12
 
15
- module ClassMethods
16
- extend T::Sig
17
- extend T::Helpers
18
-
19
- interface!
20
-
21
- sig { abstract.params(data: String).returns({ t: String, n: String, c: String }) }
22
- def decode_and_split(data); end
23
-
24
- sig { abstract.returns(Interface::Version) }
25
- def protocol; end
26
- end
27
-
28
- mixes_in_class_methods(ClassMethods)
29
-
30
13
  sig { abstract.params(nonce: String).returns(String) }
31
14
  def authentication_key(nonce:); end
32
15
 
@@ -36,24 +19,20 @@ module Paseto
36
19
  sig { abstract.params(nonce: String, payload: String).returns(String) }
37
20
  def crypt(nonce:, payload:); end
38
21
 
39
- sig { params(data: String).returns({ t: String, n: String, c: String }) }
40
- def decode_and_split(data)
41
- self.class.decode_and_split(data)
42
- end
22
+ sig { abstract.params(data: String).returns({ t: String, n: String, c: String }) }
23
+ def decode_and_split(data); end
43
24
 
44
25
  sig { abstract.returns(String) }
45
26
  def local_header; end
46
27
 
28
+ sig { abstract.returns(Interface::Version) }
29
+ def protocol; end
30
+
47
31
  sig { abstract.returns(String) }
48
32
  def random_nonce; end
49
33
 
50
34
  sig { abstract.returns(String) }
51
35
  def secret_header; end
52
-
53
- sig(:final) { returns(Interface::Version) }
54
- def protocol
55
- self.class.protocol
56
- end
57
36
  end
58
37
  end
59
38
  end
@@ -8,40 +8,11 @@ module Paseto
8
8
  extend T::Sig
9
9
  extend T::Helpers
10
10
 
11
- include Kernel
12
-
13
11
  abstract!
14
12
 
15
13
  DOMAIN_SEPARATOR_ENCRYPT = "\x01"
16
14
  DOMAIN_SEPARATOR_AUTH = "\x02"
17
15
 
18
- module ClassMethods
19
- extend T::Sig
20
- extend T::Helpers
21
-
22
- interface!
23
-
24
- sig { abstract.params(esk: T.untyped).returns(String) }
25
- def epk_bytes_from_esk(esk); end
26
-
27
- sig { abstract.returns(T.untyped) }
28
- def generate_ephemeral_key; end
29
-
30
- sig { abstract.returns(String) }
31
- def header; end
32
-
33
- sig { abstract.returns(Interface::Version) }
34
- def protocol; end
35
-
36
- sig { abstract.params(encoded_data: String).returns([String, T.untyped, String]) }
37
- def split(encoded_data); end
38
- end
39
-
40
- mixes_in_class_methods(ClassMethods)
41
-
42
- sig { abstract.returns(AsymmetricKey) }
43
- def sealing_key; end
44
-
45
16
  sig { abstract.params(xk: String, epk: T.untyped).returns(String) }
46
17
  def derive_ak(xk:, epk:); end
47
18
 
@@ -54,33 +25,26 @@ module Paseto
54
25
  sig { abstract.params(message: String, ek: String, n: String).returns(String) }
55
26
  def encrypt(message:, ek:, n:); end
56
27
 
57
- sig { abstract.params(ak: String, epk: T.untyped, edk: String).returns(String) }
58
- def tag(ak:, epk:, edk:); end
28
+ sig { abstract.params(esk: T.untyped).returns(String) }
29
+ def epk_bytes_from_esk(esk); end
59
30
 
60
- sig(:final) { params(esk: T.untyped).returns(String) }
61
- def epk_bytes_from_esk(esk)
62
- self.class.epk_bytes_from_esk(esk)
63
- end
31
+ sig { abstract.returns(T.untyped) }
32
+ def generate_ephemeral_key; end
64
33
 
65
- sig(:final) { returns(T.untyped) }
66
- def generate_ephemeral_key
67
- self.class.generate_ephemeral_key
68
- end
34
+ sig { abstract.returns(Interface::Version) }
35
+ def protocol; end
69
36
 
70
- sig(:final) { returns(String) }
71
- def header
72
- self.class.header
73
- end
37
+ sig { abstract.returns(String) }
38
+ def header; end
74
39
 
75
- sig(:final) { returns(Interface::Version) }
76
- def protocol
77
- self.class.protocol
78
- end
40
+ sig { abstract.returns(AsymmetricKey) }
41
+ def sealing_key; end
42
+
43
+ sig { abstract.params(encoded_data: String).returns([String, T.untyped, String]) }
44
+ def split(encoded_data); end
79
45
 
80
- sig(:final) { params(encoded_data: String).returns([String, T.untyped, String]) }
81
- def split(encoded_data)
82
- self.class.split(encoded_data)
83
- end
46
+ sig { abstract.params(ak: String, epk: T.untyped, edk: String).returns(String) }
47
+ def tag(ak:, epk:, edk:); end
84
48
  end
85
49
  end
86
50
  end