linzer 0.2.0 → 0.3.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 +5 -0
- data/README.md +9 -10
- data/lib/linzer/common.rb +27 -0
- data/lib/linzer/ecdsa.rb +20 -0
- data/lib/linzer/ed25519.rb +20 -0
- data/lib/linzer/hmac.rb +20 -0
- data/lib/linzer/key/helper.rb +77 -0
- data/lib/linzer/key.rb +40 -0
- data/lib/linzer/message.rb +1 -26
- data/lib/linzer/rsa.rb +29 -0
- data/lib/linzer/signer.rb +9 -17
- data/lib/linzer/verifier.rb +9 -7
- data/lib/linzer/version.rb +1 -1
- data/lib/linzer.rb +9 -9
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22298d26596b660ac67a7f039ed0d05cc41715a5413c4583a4703ce452e6548c
|
4
|
+
data.tar.gz: 735d31e3752eea02207baa7e093bd18a114281f4c493acf98cd7451d73e03fff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81428b963ffaa3f39e86ed28e52927923998aaeeb07f773a852bb01abe9272f812c8b0a593813293908845f57799c849163da00d4ae4ca2ef62d36687055ce81
|
7
|
+
data.tar.gz: 3f91ef995bd53bda69832e774ce383cf55a8ef903ffe615e8dbb1a586cf437b85a3d98f8082f39311a6757a3bd4f2657ac4b5d73c3270b4a4534ea571b9e8427
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2024-02-28
|
4
|
+
|
5
|
+
- Add support for the following algorithms: Ed25519, HMAC-SHA256 and
|
6
|
+
ECDSA (P-256 and P-384 curves).
|
7
|
+
|
3
8
|
## [0.2.0] - 2024-02-23
|
4
9
|
|
5
10
|
- Add signature signing functionality. RSASSA-PSS using SHA-512 is still the only
|
data/README.md
CHANGED
@@ -17,27 +17,27 @@ Or just `gem install linzer`.
|
|
17
17
|
### To sign a HTTP message:
|
18
18
|
|
19
19
|
```ruby
|
20
|
-
key = Linzer
|
21
|
-
# => #<
|
20
|
+
irb(main):001:0> key = Linzer.generate_ed25519_key
|
21
|
+
# => #<Linzer::Ed25519::Key:0x00000fe13e9bd208
|
22
22
|
|
23
23
|
message = Linzer::Message.new(headers: {"date" => "Fri, 23 Feb 2024 17:57:23 GMT", "x-custom-header" => "foo"})
|
24
24
|
# => #<Linzer::Message:0x0000000111b592a0 @headers={"date"=>"Fri, 23 Feb 2024 17:57:23 GMT", ...
|
25
25
|
|
26
|
-
fields = %w[date x-custom-header]
|
26
|
+
fields = %w[date x-custom-header]
|
27
27
|
signature = Linzer.sign(key, message, fields)
|
28
28
|
# => #<Linzer::Signature:0x0000000111f77ad0 ...
|
29
29
|
|
30
30
|
puts signature.to_h
|
31
31
|
{"signature"=>
|
32
|
-
"sig1=:
|
33
|
-
"signature-input"=>"sig1=(\"date\" \"x-custom-header\");created=
|
32
|
+
"sig1=:8rLY3nFtezwwsK+sqZEMe7wzbNHojZJGEnvp3suKichgwH...",
|
33
|
+
"signature-input"=>"sig1=(\"date\" \"x-custom-header\");created=1709075013;keyid=\"test-key-ed25519\""}
|
34
34
|
```
|
35
35
|
|
36
36
|
### To verify a valid signature:
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
pubkey = Linzer
|
40
|
-
# => #<
|
39
|
+
pubkey = Linzer.new_ed25519_public_key(test_ed25519_key_pub, "some-key-ed25519")
|
40
|
+
# => #<Linzer::Ed25519::Key:0x00000fe19b9384b0
|
41
41
|
|
42
42
|
headers = {"signature-input" => "...", signature => "...", "date" => "Fri, 23 Feb 2024 13:18:15 GMT", "x-custom-header" => "bar"})
|
43
43
|
|
@@ -55,13 +55,12 @@ Linzer.verify(pubkey, message, signature)
|
|
55
55
|
|
56
56
|
```ruby
|
57
57
|
result = Linzer.verify(pubkey, message, signature)
|
58
|
-
|
58
|
+
lib/linzer/verifier.rb:34:in `verify_or_fail': Failed to verify message: Invalid signature. (Linzer::Error)
|
59
59
|
```
|
60
60
|
|
61
61
|
For now, to consult additional details, just take a look at source code and/or the unit tests.
|
62
62
|
|
63
|
-
Please note that is still early days
|
64
|
-
described in the RFC are supported.
|
63
|
+
Please note that is still early days and extensive testing is still ongoing. For now only the following algorithms are supported: RSASSA-PSS using SHA-512, HMAC-SHA256, Ed25519 and ECDSA P-256 curve. ECDSA P-384 curve was also added but not tested yet.
|
65
64
|
|
66
65
|
I'll be expanding the library to cover more functionality specified in the RFC
|
67
66
|
in subsequent releases.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
module Common
|
5
|
+
def signature_base(message, components, parameters)
|
6
|
+
signature_base = components.each_with_object(+"") do |component, base|
|
7
|
+
base << "\"#{component}\": #{message[component]}\n"
|
8
|
+
end
|
9
|
+
|
10
|
+
signature_params =
|
11
|
+
Starry.serialize([Starry::InnerList.new(components, parameters)])
|
12
|
+
|
13
|
+
signature_base << "\"@signature-params\": #{signature_params}"
|
14
|
+
signature_base
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_components(message, components)
|
18
|
+
if components.include?("@signature-params")
|
19
|
+
raise Error.new "Invalid component in signature input"
|
20
|
+
end
|
21
|
+
msg = "Cannot verify signature. Missing component in message: %s"
|
22
|
+
components.each { |c| raise Error.new msg % "\"#{c}\"" unless message.field?(c) }
|
23
|
+
msg = "Invalid signature. Duplicated component in signature input."
|
24
|
+
raise Error.new msg if components.size != components.uniq.size
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/linzer/ecdsa.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
module ECDSA
|
5
|
+
class Key < Linzer::Key
|
6
|
+
def validate
|
7
|
+
super
|
8
|
+
validate_digest
|
9
|
+
end
|
10
|
+
|
11
|
+
def sign(data)
|
12
|
+
material.sign(@params[:digest], data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify(signature, data)
|
16
|
+
material.verify(@params[:digest], signature, data)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ed25519"
|
4
|
+
|
5
|
+
module Linzer
|
6
|
+
module Ed25519
|
7
|
+
class Key < Linzer::Key
|
8
|
+
def sign(data)
|
9
|
+
material.sign(data)
|
10
|
+
end
|
11
|
+
|
12
|
+
def verify(signature, data)
|
13
|
+
verify_key = material.is_a?(::Ed25519::SigningKey) ? material.verify_key : material
|
14
|
+
verify_key.verify(signature, data)
|
15
|
+
rescue ::Ed25519::VerifyError
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/linzer/hmac.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
module HMAC
|
5
|
+
class Key < Linzer::Key
|
6
|
+
def validate
|
7
|
+
super
|
8
|
+
validate_digest
|
9
|
+
end
|
10
|
+
|
11
|
+
def sign(data)
|
12
|
+
OpenSSL::HMAC.digest(@params[:digest], material, data)
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify(signature, data)
|
16
|
+
signature == sign(data)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
class Key
|
5
|
+
module Helper
|
6
|
+
def generate_rsa_pss_sha512_key(size, key_id = nil)
|
7
|
+
material = OpenSSL::PKey::RSA.generate(size)
|
8
|
+
Linzer::RSA::Key.new(material, id: key_id, digest: "SHA512")
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_rsa_pss_sha512_key(material, key_id = nil)
|
12
|
+
key = OpenSSL::PKey.read(material)
|
13
|
+
Linzer::RSA::Key.new(key, id: key_id, digest: "SHA512")
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_rsa_pss_sha512_public_key(material, key_id = nil)
|
17
|
+
key = OpenSSL::PKey::RSA.new(material)
|
18
|
+
Linzer::RSA::Key.new(key, id: key_id, digest: "SHA512")
|
19
|
+
end
|
20
|
+
|
21
|
+
# XXX: to-do
|
22
|
+
# Linzer::RSA::Key
|
23
|
+
# def new_rsa_v1_5_sha256_key
|
24
|
+
# def generate_rsa_v1_5_sha256_key
|
25
|
+
|
26
|
+
def generate_hmac_sha256_key(key_id = nil)
|
27
|
+
material = OpenSSL::Random.random_bytes(64)
|
28
|
+
Linzer::HMAC::Key.new(material, id: key_id, digest: "SHA256")
|
29
|
+
end
|
30
|
+
|
31
|
+
def new_hmac_sha256_key(material, key_id = nil)
|
32
|
+
Linzer::HMAC::Key.new(material, id: key_id, digest: "SHA256")
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_ed25519_key(key_id = nil)
|
36
|
+
material = ::Ed25519::SigningKey.generate
|
37
|
+
Linzer::Ed25519::Key.new(material, id: key_id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def new_ed25519_key(material, key_id = nil)
|
41
|
+
key = ::Ed25519::SigningKey.new(material)
|
42
|
+
Linzer::Ed25519::Key.new(key, id: key_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def new_ed25519_public_key(material, key_id = nil)
|
46
|
+
key = ::Ed25519::VerifyKey.new(material)
|
47
|
+
Linzer::Ed25519::Key.new(key, id: key_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
# https://www.rfc-editor.org/rfc/rfc4492.html#appendix-A
|
51
|
+
# Table 6: Equivalent curves defined by SECG, ANSI, and NIST
|
52
|
+
# secp256r1 | prime256v1 | NIST P-256
|
53
|
+
def generate_ecdsa_p256_sha256_key(key_id = nil)
|
54
|
+
material = OpenSSL::PKey::EC.generate("prime256v1")
|
55
|
+
Linzer::ECDSA::Key.new(material, id: key_id, digest: "SHA256")
|
56
|
+
end
|
57
|
+
|
58
|
+
def new_ecdsa_p256_sha256_key(material, key_id = nil)
|
59
|
+
key = OpenSSL::PKey::EC.new(material)
|
60
|
+
Linzer::ECDSA::Key.new(key, id: key_id, digest: "SHA256")
|
61
|
+
end
|
62
|
+
|
63
|
+
# https://www.rfc-editor.org/rfc/rfc4492.html#appendix-A
|
64
|
+
# Table 6: Equivalent curves defined by SECG, ANSI, and NIST
|
65
|
+
# secp384r1 | | NIST P-384
|
66
|
+
def generate_ecdsa_p384_sha256_key(key_id = nil)
|
67
|
+
material = OpenSSL::PKey::EC.generate("secp384r1")
|
68
|
+
Linzer::ECDSA::Key.new(material, id: key_id, digest: "SHA384")
|
69
|
+
end
|
70
|
+
|
71
|
+
def new_ecdsa_p384_sha384_key(material, key_id = nil)
|
72
|
+
key = OpenSSL::PKey::EC.new(material)
|
73
|
+
Linzer::ECDSA::Key.new(key, id: key_id, digest: "SHA384")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/linzer/key.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
class Key
|
5
|
+
def initialize(material, params = {})
|
6
|
+
@material = material
|
7
|
+
@params = Hash(params).clone.freeze
|
8
|
+
validate
|
9
|
+
freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :material
|
13
|
+
|
14
|
+
def key_id
|
15
|
+
@params[:id]
|
16
|
+
end
|
17
|
+
|
18
|
+
def sign(*args)
|
19
|
+
abstract_error = "Cannot sign data, \"#{self.class}\" is an abstract class."
|
20
|
+
raise Error.new abstract_error
|
21
|
+
end
|
22
|
+
|
23
|
+
def verify(*args)
|
24
|
+
abstract_error = "Cannot verify signature, \"#{self.class}\" is an abstract class."
|
25
|
+
raise Error.new abstract_error
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def validate
|
31
|
+
!material.nil? or raise Error.new "Invalid key. No key material provided."
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_digest
|
35
|
+
no_digest = !@params.key?(:digest) || @params[:digest].nil? || String(@params[:digest]).empty?
|
36
|
+
no_digest_error = "Invalid key definition, no digest algorithm was selected."
|
37
|
+
raise Linzer::Error.new no_digest_error if no_digest
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/linzer/message.rb
CHANGED
@@ -27,25 +27,12 @@ module Linzer
|
|
27
27
|
when "@method" then @http["method"]
|
28
28
|
when "@authority" then @http["host"]
|
29
29
|
when "@path" then @http["path"]
|
30
|
+
when "@status" then @http["status"]
|
30
31
|
else # XXX: improve this and add support for all fields in the RFC
|
31
32
|
raise Error.new "Unknown/unsupported field: \"#{field_name}\""
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
def signature_base(components, parameters)
|
36
|
-
validate_components components
|
37
|
-
|
38
|
-
signature_base = components.each_with_object(+"") do |comp, base|
|
39
|
-
base << "\"#{comp}\": #{self[comp]}\n"
|
40
|
-
end
|
41
|
-
|
42
|
-
signature_params =
|
43
|
-
Starry.serialize([Starry::InnerList.new(components, parameters)])
|
44
|
-
|
45
|
-
signature_base << "\"@signature-params\": #{signature_params}"
|
46
|
-
signature_base
|
47
|
-
end
|
48
|
-
|
49
36
|
class << self
|
50
37
|
def parse_structured_dictionary(str, field_name = nil)
|
51
38
|
Starry.parse_dictionary(str)
|
@@ -53,17 +40,5 @@ module Linzer
|
|
53
40
|
raise Error.new "Cannot parse \"#{field_name}\" field. Bailing out!"
|
54
41
|
end
|
55
42
|
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def validate_components(components)
|
60
|
-
if components.include?("@signature-params")
|
61
|
-
raise Error.new "Invalid component in signature input"
|
62
|
-
end
|
63
|
-
msg = "Cannot verify signature. Missing component in message: %s"
|
64
|
-
components.each { |c| raise Error.new msg % "\"#{c}\"" unless field? c }
|
65
|
-
msg = "Invalid signature. Duplicated component in signature input."
|
66
|
-
raise Error.new msg if components.size != components.uniq.size
|
67
|
-
end
|
68
43
|
end
|
69
44
|
end
|
data/lib/linzer/rsa.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Linzer
|
4
|
+
module RSA
|
5
|
+
class Key < Linzer::Key
|
6
|
+
def validate
|
7
|
+
super
|
8
|
+
validate_digest
|
9
|
+
end
|
10
|
+
|
11
|
+
def sign(data)
|
12
|
+
# XXX: should check if the key is usable for signing
|
13
|
+
@material.sign(@params[:digest], data)
|
14
|
+
end
|
15
|
+
|
16
|
+
def verify(signature, data)
|
17
|
+
# XXX: should check if the key is usable for verifying
|
18
|
+
return true if @material.verify_pss(
|
19
|
+
@params[:digest],
|
20
|
+
signature,
|
21
|
+
data,
|
22
|
+
salt_length: @params[:salt_length] || :auto,
|
23
|
+
mgf1_hash: @params[:digest]
|
24
|
+
)
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/linzer/signer.rb
CHANGED
@@ -5,13 +5,15 @@ module Linzer
|
|
5
5
|
DEFAULT_LABEL = "sig1"
|
6
6
|
|
7
7
|
class << self
|
8
|
+
include Common
|
9
|
+
|
8
10
|
def sign(key, message, components, options = {})
|
9
11
|
validate key, message, components
|
10
12
|
|
11
13
|
parameters = populate_parameters(key, options)
|
12
|
-
signature_base =
|
14
|
+
signature_base = signature_base(message, components, parameters)
|
13
15
|
|
14
|
-
signature =
|
16
|
+
signature = key.sign(signature_base)
|
15
17
|
label = options[:label] || DEFAULT_LABEL
|
16
18
|
|
17
19
|
Linzer::Signature.build(serialize(signature, components, parameters, label))
|
@@ -24,17 +26,12 @@ module Linzer
|
|
24
26
|
private
|
25
27
|
|
26
28
|
def validate(key, message, components)
|
27
|
-
|
28
|
-
raise Error.new
|
29
|
-
|
30
|
-
if components.
|
31
|
-
raise Error.new "Invalid component in signature input"
|
32
|
-
end
|
29
|
+
msg = "Message cannot be signed with null %s"
|
30
|
+
raise Error.new msg % "value" if message.nil?
|
31
|
+
raise Error.new msg % "key" if key.nil?
|
32
|
+
raise Error.new msg % "component" if components.nil?
|
33
33
|
|
34
|
-
|
35
|
-
components.each do |c|
|
36
|
-
raise Error.new component_missing % c unless message.field? c
|
37
|
-
end
|
34
|
+
validate_components message, components
|
38
35
|
end
|
39
36
|
|
40
37
|
def populate_parameters(key, options)
|
@@ -50,11 +47,6 @@ module Linzer
|
|
50
47
|
parameters
|
51
48
|
end
|
52
49
|
|
53
|
-
def _sign(key, data, options)
|
54
|
-
# signature = key.sign_pss("SHA512", signature_base, salt_length: 64, mgf1_hash: "SHA512")
|
55
|
-
key.sign("SHA512", data)
|
56
|
-
end
|
57
|
-
|
58
50
|
def serialize(signature, components, parameters, label)
|
59
51
|
{
|
60
52
|
"signature" => Starry.serialize({label => signature}),
|
data/lib/linzer/verifier.rb
CHANGED
@@ -3,16 +3,17 @@
|
|
3
3
|
module Linzer
|
4
4
|
module Verifier
|
5
5
|
class << self
|
6
|
+
include Common
|
7
|
+
|
6
8
|
def verify(key, message, signature)
|
7
9
|
validate message, key, signature
|
8
10
|
|
9
11
|
parameters = signature.parameters
|
10
12
|
components = signature.components
|
11
13
|
|
12
|
-
signature_base =
|
14
|
+
signature_base = signature_base(message, components, parameters)
|
13
15
|
|
14
|
-
|
15
|
-
raise Error.new "Failed to verify message: Invalid signature."
|
16
|
+
verify_or_fail key, signature.value, signature_base
|
16
17
|
end
|
17
18
|
|
18
19
|
private
|
@@ -28,12 +29,13 @@ module Linzer
|
|
28
29
|
|
29
30
|
raise Error.new "Signature raw value to cannot be null" if signature.value.nil?
|
30
31
|
raise Error.new "Components cannot be null" if signature.components.nil?
|
32
|
+
|
33
|
+
validate_components message, signature.components
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
false
|
36
|
+
def verify_or_fail(key, signature, data)
|
37
|
+
return true if key.verify(signature, data)
|
38
|
+
raise Error.new "Failed to verify message: Invalid signature."
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
data/lib/linzer/version.rb
CHANGED
data/lib/linzer.rb
CHANGED
@@ -4,24 +4,24 @@ require "starry"
|
|
4
4
|
require "openssl"
|
5
5
|
|
6
6
|
require_relative "linzer/version"
|
7
|
+
require_relative "linzer/common"
|
7
8
|
require_relative "linzer/message"
|
8
9
|
require_relative "linzer/signature"
|
10
|
+
require_relative "linzer/key"
|
11
|
+
require_relative "linzer/rsa"
|
12
|
+
require_relative "linzer/hmac"
|
13
|
+
require_relative "linzer/ed25519"
|
14
|
+
require_relative "linzer/ecdsa"
|
15
|
+
require_relative "linzer/key/helper"
|
9
16
|
require_relative "linzer/signer"
|
10
17
|
require_relative "linzer/verifier"
|
11
18
|
|
12
19
|
module Linzer
|
13
20
|
class Error < StandardError; end
|
14
21
|
|
15
|
-
Key = Struct.new("Key", :material, :key_id, keyword_init: true) do |clazz|
|
16
|
-
def sign(*args)
|
17
|
-
# XXX: probably this is going to grow in complexity and will need
|
18
|
-
# to be moved to its own class or dispatch to the signer
|
19
|
-
!material.nil? or raise Error.new "Cannot sign data, key material cannot be null."
|
20
|
-
material.sign(*args)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
22
|
class << self
|
23
|
+
include Key::Helper
|
24
|
+
|
25
25
|
def verify(pubkey, message, signature)
|
26
26
|
Linzer::Verifier.verify(pubkey, message, signature)
|
27
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linzer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Landaeta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ed25519
|
@@ -59,7 +59,14 @@ files:
|
|
59
59
|
- README.md
|
60
60
|
- Rakefile
|
61
61
|
- lib/linzer.rb
|
62
|
+
- lib/linzer/common.rb
|
63
|
+
- lib/linzer/ecdsa.rb
|
64
|
+
- lib/linzer/ed25519.rb
|
65
|
+
- lib/linzer/hmac.rb
|
66
|
+
- lib/linzer/key.rb
|
67
|
+
- lib/linzer/key/helper.rb
|
62
68
|
- lib/linzer/message.rb
|
69
|
+
- lib/linzer/rsa.rb
|
63
70
|
- lib/linzer/signature.rb
|
64
71
|
- lib/linzer/signer.rb
|
65
72
|
- lib/linzer/verifier.rb
|