ssh_data 1.2.0 → 2.0.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/lib/ssh_data/encoding.rb +55 -1
- data/lib/ssh_data/private_key/dsa.rb +13 -1
- data/lib/ssh_data/private_key/ecdsa.rb +1 -1
- data/lib/ssh_data/private_key/rsa.rb +2 -2
- data/lib/ssh_data/public_key/dsa.rb +1 -1
- data/lib/ssh_data/public_key/ecdsa.rb +1 -1
- data/lib/ssh_data/public_key/ed25519.rb +1 -1
- data/lib/ssh_data/public_key/rsa.rb +7 -1
- data/lib/ssh_data/public_key/security_key.rb +40 -0
- data/lib/ssh_data/public_key/skecdsa.rb +20 -2
- data/lib/ssh_data/public_key/sked25519.rb +26 -3
- data/lib/ssh_data/public_key.rb +1 -0
- data/lib/ssh_data/signature.rb +126 -0
- data/lib/ssh_data/version.rb +1 -1
- data/lib/ssh_data.rb +1 -0
- metadata +34 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a33f8e3096dba56186df0bf3288d36c0fda79f75d7a02e6a58c585b468d4cd76
|
4
|
+
data.tar.gz: 3f5f652b61e4fbbb06bc24154c51683e97be194a70565d993ee27ff87ec8eb2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6b1324539e847dd7e7d858cd0f64a8c369de781bdb8f5fcde7667ad9a61748e347209f7d6f06f7e5400d9147e67a9289f6f99aa187ec368bfc4a38ddccc22b9
|
7
|
+
data.tar.gz: 7c1a063701138b853aebff7adb7f7a9d8bccabdf04d58d81dffb16ab2a499706401355ac01f2f4e8e91789140fd051569ecf8056eae27a76d0ae1425128e62c7
|
data/lib/ssh_data/encoding.rb
CHANGED
@@ -3,6 +3,19 @@ module SSHData
|
|
3
3
|
# Fields in an OpenSSL private key
|
4
4
|
# https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
5
5
|
OPENSSH_PRIVATE_KEY_MAGIC = "openssh-key-v1\x00"
|
6
|
+
|
7
|
+
OPENSSH_SIGNATURE_MAGIC = "SSHSIG"
|
8
|
+
OPENSSH_SIGNATURE_VERSION = 0x01
|
9
|
+
|
10
|
+
OPENSSH_SIGNATURE_FIELDS = [
|
11
|
+
[:sigversion, :uint32],
|
12
|
+
[:publickey, :string],
|
13
|
+
[:namespace, :string],
|
14
|
+
[:reserved, :string],
|
15
|
+
[:hash_algorithm, :string],
|
16
|
+
[:signature, :string],
|
17
|
+
]
|
18
|
+
|
6
19
|
OPENSSH_PRIVATE_KEY_FIELDS = [
|
7
20
|
[:ciphername, :string],
|
8
21
|
[:kdfname, :string],
|
@@ -313,6 +326,21 @@ module SSHData
|
|
313
326
|
[key, str_read]
|
314
327
|
end
|
315
328
|
|
329
|
+
def decode_openssh_signature(raw, offset=0)
|
330
|
+
total_read = 0
|
331
|
+
|
332
|
+
magic = raw.byteslice(offset, OPENSSH_SIGNATURE_MAGIC.bytesize)
|
333
|
+
unless magic == OPENSSH_SIGNATURE_MAGIC
|
334
|
+
raise DecodeError, "bad OpenSSH signature"
|
335
|
+
end
|
336
|
+
|
337
|
+
total_read += OPENSSH_SIGNATURE_MAGIC.bytesize
|
338
|
+
offset += total_read
|
339
|
+
data, read = decode_fields(raw, OPENSSH_SIGNATURE_FIELDS, offset)
|
340
|
+
total_read += read
|
341
|
+
[data, total_read]
|
342
|
+
end
|
343
|
+
|
316
344
|
# Decode the fields in a certificate.
|
317
345
|
#
|
318
346
|
# raw - Binary String certificate as described by RFC4253 section 6.6.
|
@@ -396,7 +424,7 @@ module SSHData
|
|
396
424
|
[hash, total_read]
|
397
425
|
end
|
398
426
|
|
399
|
-
# Encode the series of
|
427
|
+
# Encode the series of fields into a binary string.
|
400
428
|
#
|
401
429
|
# fields - A series of Arrays, each containing a Symbol type and a value to
|
402
430
|
# encode.
|
@@ -680,6 +708,32 @@ module SSHData
|
|
680
708
|
[value].pack("L>")
|
681
709
|
end
|
682
710
|
|
711
|
+
# Read a uint8 from the provided raw data.
|
712
|
+
#
|
713
|
+
# raw - A binary String.
|
714
|
+
# offset - The offset into raw at which to read (default 0).
|
715
|
+
#
|
716
|
+
# Returns an Array including the decoded uint8 as an Integer and the
|
717
|
+
# Integer number of bytes read.
|
718
|
+
def decode_uint8(raw, offset=0)
|
719
|
+
if raw.bytesize < offset + 1
|
720
|
+
raise DecodeError, "data too short"
|
721
|
+
end
|
722
|
+
|
723
|
+
uint8 = raw.byteslice(offset, 1).unpack("C").first
|
724
|
+
|
725
|
+
[uint8, 1]
|
726
|
+
end
|
727
|
+
|
728
|
+
# Encoding an integer as a uint8.
|
729
|
+
#
|
730
|
+
# value - The Integer value to encode.
|
731
|
+
#
|
732
|
+
# Returns an encoded representation of the value.
|
733
|
+
def encode_uint8(value)
|
734
|
+
[value].pack("C")
|
735
|
+
end
|
736
|
+
|
683
737
|
extend self
|
684
738
|
end
|
685
739
|
end
|
@@ -7,7 +7,19 @@
|
|
7
7
|
#
|
8
8
|
# Returns a PublicKey::Base subclass instance.
|
9
9
|
def self.generate
|
10
|
-
|
10
|
+
openssl_key =
|
11
|
+
if defined?(OpenSSL::PKey.generate_parameters)
|
12
|
+
dsa_parameters = OpenSSL::PKey.generate_parameters("DSA", {
|
13
|
+
dsa_paramgen_bits: 1024,
|
14
|
+
dsa_paramgen_q_bits: 160
|
15
|
+
})
|
16
|
+
|
17
|
+
OpenSSL::PKey.generate_key(dsa_parameters)
|
18
|
+
else
|
19
|
+
OpenSSL::PKey::DSA.generate(1024)
|
20
|
+
end
|
21
|
+
|
22
|
+
from_openssl(openssl_key)
|
11
23
|
end
|
12
24
|
|
13
25
|
# Import an openssl private key.
|
@@ -13,7 +13,7 @@ module SSHData
|
|
13
13
|
openssl_curve = PublicKey::ECDSA::OPENSSL_CURVE_NAME_FOR_CURVE[curve]
|
14
14
|
raise AlgorithmError, "unknown curve: #{curve}" if openssl_curve.nil?
|
15
15
|
|
16
|
-
openssl_key = OpenSSL::PKey::EC.
|
16
|
+
openssl_key = OpenSSL::PKey::EC.generate(openssl_curve)
|
17
17
|
from_openssl(openssl_key)
|
18
18
|
end
|
19
19
|
|
@@ -21,9 +21,9 @@ module SSHData
|
|
21
21
|
|
22
22
|
# Import an openssl private key.
|
23
23
|
#
|
24
|
-
# key - An OpenSSL::PKey::
|
24
|
+
# key - An OpenSSL::PKey::RSA instance.
|
25
25
|
#
|
26
|
-
# Returns a
|
26
|
+
# Returns a RSA instance.
|
27
27
|
def self.from_openssl(key)
|
28
28
|
new(
|
29
29
|
algo: PublicKey::ALGO_RSA,
|
@@ -67,7 +67,7 @@ module SSHData
|
|
67
67
|
# Verify an SSH signature.
|
68
68
|
#
|
69
69
|
# signed_data - The String message that the signature was calculated over.
|
70
|
-
# signature - The
|
70
|
+
# signature - The binary String signature with SSH encoding.
|
71
71
|
#
|
72
72
|
# Returns boolean.
|
73
73
|
def verify(signed_data, signature)
|
@@ -93,7 +93,7 @@ module SSHData
|
|
93
93
|
# Verify an SSH signature.
|
94
94
|
#
|
95
95
|
# signed_data - The String message that the signature was calculated over.
|
96
|
-
# signature - The
|
96
|
+
# signature - The binary String signature with SSH encoding.
|
97
97
|
#
|
98
98
|
# Returns boolean.
|
99
99
|
def verify(signed_data, signature)
|
@@ -37,7 +37,7 @@ module SSHData
|
|
37
37
|
# Verify an SSH signature.
|
38
38
|
#
|
39
39
|
# signed_data - The String message that the signature was calculated over.
|
40
|
-
# signature - The
|
40
|
+
# signature - The binary String signature with SSH encoding.
|
41
41
|
#
|
42
42
|
# Returns boolean.
|
43
43
|
def verify(signed_data, signature)
|
@@ -26,7 +26,7 @@ module SSHData
|
|
26
26
|
# Verify an SSH signature.
|
27
27
|
#
|
28
28
|
# signed_data - The String message that the signature was calculated over.
|
29
|
-
# signature - The
|
29
|
+
# signature - The binary String signature with SSH encoding.
|
30
30
|
#
|
31
31
|
# Returns boolean.
|
32
32
|
def verify(signed_data, signature)
|
@@ -37,6 +37,12 @@ module SSHData
|
|
37
37
|
raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}"
|
38
38
|
end
|
39
39
|
|
40
|
+
# OpenSSH compatibility: if a the number of bytes in the signature is less than the number of bytes of the RSA
|
41
|
+
# modulus, prepend the signature with zeros.
|
42
|
+
# See https://github.com/openssh/openssh-portable/blob/ac383f3a5c6f529a2e8a5bc44af79a08c7da294e/ssh-rsa.c#L531
|
43
|
+
difference = n.num_bytes - raw_sig.bytesize
|
44
|
+
raw_sig = "\0" * difference + raw_sig if difference.positive?
|
45
|
+
|
40
46
|
openssl.verify(digest.new, raw_sig, signed_data)
|
41
47
|
end
|
42
48
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SSHData
|
2
|
+
module PublicKey
|
3
|
+
module SecurityKey
|
4
|
+
|
5
|
+
# Defaults to match OpenSSH, user presence is required by verification is not.
|
6
|
+
DEFAULT_SK_VERIFY_OPTS = {
|
7
|
+
user_presence_required: true,
|
8
|
+
user_verification_required: false
|
9
|
+
}
|
10
|
+
|
11
|
+
SK_FLAG_USER_PRESENCE = 0b001
|
12
|
+
SK_FLAG_USER_VERIFICATION = 0b100
|
13
|
+
|
14
|
+
def build_signing_blob(application, signed_data, signature)
|
15
|
+
read = 0
|
16
|
+
sig_algo, raw_sig, signature_read = Encoding.decode_signature(signature)
|
17
|
+
read += signature_read
|
18
|
+
sk_flags, sk_flags_read = Encoding.decode_uint8(signature, read)
|
19
|
+
read += sk_flags_read
|
20
|
+
counter, counter_read = Encoding.decode_uint32(signature, read)
|
21
|
+
read += counter_read
|
22
|
+
|
23
|
+
if read != signature.bytesize
|
24
|
+
raise DecodeError, "unexpected trailing data"
|
25
|
+
end
|
26
|
+
|
27
|
+
application_hash = OpenSSL::Digest::SHA256.digest(application)
|
28
|
+
message_hash = OpenSSL::Digest::SHA256.digest(signed_data)
|
29
|
+
|
30
|
+
blob =
|
31
|
+
application_hash +
|
32
|
+
Encoding.encode_uint8(sk_flags) +
|
33
|
+
Encoding.encode_uint32(counter) +
|
34
|
+
message_hash
|
35
|
+
|
36
|
+
[sig_algo, raw_sig, sk_flags, blob]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module SSHData
|
2
2
|
module PublicKey
|
3
3
|
class SKECDSA < ECDSA
|
4
|
+
include SecurityKey
|
4
5
|
attr_reader :application
|
5
6
|
|
6
7
|
OPENSSL_CURVE_NAME_FOR_CURVE = {
|
@@ -34,8 +35,25 @@ module SSHData
|
|
34
35
|
)
|
35
36
|
end
|
36
37
|
|
37
|
-
def verify(signed_data, signature)
|
38
|
-
|
38
|
+
def verify(signed_data, signature, **opts)
|
39
|
+
opts = DEFAULT_SK_VERIFY_OPTS.merge(opts)
|
40
|
+
unknown_opts = opts.keys - DEFAULT_SK_VERIFY_OPTS.keys
|
41
|
+
raise UnsupportedError, "Verification options #{unknown_opts.inspect} are not supported." unless unknown_opts.empty?
|
42
|
+
|
43
|
+
sig_algo, raw_sig, sk_flags, blob = build_signing_blob(application, signed_data, signature)
|
44
|
+
self.class.check_algorithm!(sig_algo, curve)
|
45
|
+
|
46
|
+
openssl_sig = self.class.openssl_signature(raw_sig)
|
47
|
+
digest = DIGEST_FOR_CURVE[curve]
|
48
|
+
|
49
|
+
result = openssl.verify(digest.new, openssl_sig, blob)
|
50
|
+
|
51
|
+
# We don't know that the flags are correct until after we've validated the signature
|
52
|
+
# which embeds the flags, so always verify the signature first.
|
53
|
+
return false if opts[:user_presence_required] && (sk_flags & SK_FLAG_USER_PRESENCE != SK_FLAG_USER_PRESENCE)
|
54
|
+
return false if opts[:user_verification_required] && (sk_flags & SK_FLAG_USER_VERIFICATION != SK_FLAG_USER_VERIFICATION)
|
55
|
+
|
56
|
+
result
|
39
57
|
end
|
40
58
|
|
41
59
|
def ==(other)
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module SSHData
|
2
2
|
module PublicKey
|
3
3
|
class SKED25519 < ED25519
|
4
|
+
include SecurityKey
|
4
5
|
attr_reader :application
|
5
6
|
|
6
7
|
def initialize(algo:, pk:, application:)
|
7
8
|
@application = application
|
8
9
|
super(algo: algo, pk: pk)
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
def self.algorithm_identifier
|
12
13
|
ALGO_SKED25519
|
13
14
|
end
|
@@ -23,8 +24,30 @@ module SSHData
|
|
23
24
|
)
|
24
25
|
end
|
25
26
|
|
26
|
-
def verify(signed_data, signature)
|
27
|
-
|
27
|
+
def verify(signed_data, signature, **opts)
|
28
|
+
self.class.ed25519_gem_required!
|
29
|
+
opts = DEFAULT_SK_VERIFY_OPTS.merge(opts)
|
30
|
+
unknown_opts = opts.keys - DEFAULT_SK_VERIFY_OPTS.keys
|
31
|
+
raise UnsupportedError, "Verification options #{unknown_opts.inspect} are not supported." unless unknown_opts.empty?
|
32
|
+
|
33
|
+
sig_algo, raw_sig, sk_flags, blob = build_signing_blob(application, signed_data, signature)
|
34
|
+
|
35
|
+
if sig_algo != self.class.algorithm_identifier
|
36
|
+
raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}"
|
37
|
+
end
|
38
|
+
|
39
|
+
result = begin
|
40
|
+
ed25519_key.verify(raw_sig, blob)
|
41
|
+
rescue Ed25519::VerifyError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# We don't know that the flags are correct until after we've validated the signature
|
46
|
+
# which embeds the flags, so always verify the signature first.
|
47
|
+
return false if opts[:user_presence_required] && (sk_flags & SK_FLAG_USER_PRESENCE != SK_FLAG_USER_PRESENCE)
|
48
|
+
return false if opts[:user_verification_required] && (sk_flags & SK_FLAG_USER_VERIFICATION != SK_FLAG_USER_VERIFICATION)
|
49
|
+
|
50
|
+
result
|
28
51
|
end
|
29
52
|
|
30
53
|
def ==(other)
|
data/lib/ssh_data/public_key.rb
CHANGED
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SSHData
|
4
|
+
class Signature
|
5
|
+
PEM_TYPE = "SSH SIGNATURE"
|
6
|
+
SIGNATURE_PREAMBLE = "SSHSIG"
|
7
|
+
MIN_SUPPORTED_VERSION = 1
|
8
|
+
MAX_SUPPORTED_VERSION = 1
|
9
|
+
|
10
|
+
# Spec: no SHA1 or SHA384. In practice, OpenSSH is always going to use SHA512.
|
11
|
+
# Note the actual signing / verify primitive may use a different hash algorithm.
|
12
|
+
# https://github.com/openssh/openssh-portable/blob/b7ffbb17e37f59249c31f1ff59d6c5d80888f689/PROTOCOL.sshsig#L67
|
13
|
+
SUPPORTED_HASH_ALGORITHMS = {
|
14
|
+
"sha256" => OpenSSL::Digest::SHA256,
|
15
|
+
"sha512" => OpenSSL::Digest::SHA512,
|
16
|
+
}
|
17
|
+
|
18
|
+
PERMITTED_RSA_SIGNATURE_ALGORITHMS = [
|
19
|
+
PublicKey::ALGO_RSA_SHA2_256,
|
20
|
+
PublicKey::ALGO_RSA_SHA2_512,
|
21
|
+
]
|
22
|
+
|
23
|
+
attr_reader :sigversion, :namespace, :signature, :reserved, :hash_algorithm
|
24
|
+
|
25
|
+
# Parses a PEM armored SSH signature.
|
26
|
+
# pem - A PEM encoded SSH signature.
|
27
|
+
#
|
28
|
+
# Returns a Signature instance.
|
29
|
+
def self.parse_pem(pem)
|
30
|
+
pem_type = Encoding.pem_type(pem)
|
31
|
+
|
32
|
+
if pem_type != PEM_TYPE
|
33
|
+
raise DecodeError, "Mismatched PEM type. Expecting '#{PEM_TYPE}', actually '#{pem_type}'."
|
34
|
+
end
|
35
|
+
|
36
|
+
blob = Encoding.decode_pem(pem, pem_type)
|
37
|
+
self.parse_blob(blob)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse_blob(blob)
|
41
|
+
data, read = Encoding.decode_openssh_signature(blob)
|
42
|
+
|
43
|
+
if read != blob.bytesize
|
44
|
+
raise DecodeError, "unexpected trailing data"
|
45
|
+
end
|
46
|
+
|
47
|
+
new(**data)
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(sigversion:, publickey:, namespace:, reserved:, hash_algorithm:, signature:)
|
51
|
+
if sigversion > MAX_SUPPORTED_VERSION || sigversion < MIN_SUPPORTED_VERSION
|
52
|
+
raise UnsupportedError, "Signature version is not supported"
|
53
|
+
end
|
54
|
+
|
55
|
+
unless SUPPORTED_HASH_ALGORITHMS.has_key?(hash_algorithm)
|
56
|
+
raise UnsupportedError, "Hash algorithm #{hash_algorithm} is not supported."
|
57
|
+
end
|
58
|
+
|
59
|
+
# Spec: empty namespaces are not permitted.
|
60
|
+
# https://github.com/openssh/openssh-portable/blob/b7ffbb17e37f59249c31f1ff59d6c5d80888f689/PROTOCOL.sshsig#L57
|
61
|
+
raise UnsupportedError, "A namespace is required." if namespace.empty?
|
62
|
+
|
63
|
+
# Spec: ignore 'reserved', don't need to validate that it is empty.
|
64
|
+
|
65
|
+
@sigversion = sigversion
|
66
|
+
@publickey = publickey
|
67
|
+
@namespace = namespace
|
68
|
+
@reserved = reserved
|
69
|
+
@hash_algorithm = hash_algorithm
|
70
|
+
@signature = signature
|
71
|
+
end
|
72
|
+
|
73
|
+
def verify(signed_data, **opts)
|
74
|
+
signing_key = public_key
|
75
|
+
|
76
|
+
# Unwrap the signing key if this signature was created from a certificate.
|
77
|
+
key = signing_key.is_a?(Certificate) ? signing_key.public_key : signing_key
|
78
|
+
|
79
|
+
digest_algorithm = SUPPORTED_HASH_ALGORITHMS[@hash_algorithm]
|
80
|
+
|
81
|
+
if key.is_a?(PublicKey::RSA)
|
82
|
+
sig_algo, * = Encoding.decode_signature(@signature)
|
83
|
+
|
84
|
+
# Spec: If the signature is an RSA signature, the legacy 'ssh-rsa'
|
85
|
+
# identifer is not permitted.
|
86
|
+
# https://github.com/openssh/openssh-portable/blob/b7ffbb17e37f59249c31f1ff59d6c5d80888f689/PROTOCOL.sshsig#L72
|
87
|
+
unless PERMITTED_RSA_SIGNATURE_ALGORITHMS.include?(sig_algo)
|
88
|
+
raise UnsupportedError, "RSA signature #{sig_algo} is not supported."
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
message_digest = digest_algorithm.digest(signed_data)
|
93
|
+
blob =
|
94
|
+
SIGNATURE_PREAMBLE +
|
95
|
+
Encoding.encode_string(@namespace) +
|
96
|
+
Encoding.encode_string(@reserved || "") +
|
97
|
+
Encoding.encode_string(@hash_algorithm) +
|
98
|
+
Encoding.encode_string(message_digest)
|
99
|
+
|
100
|
+
if key.class.include?(::SSHData::PublicKey::SecurityKey)
|
101
|
+
key.verify(blob, @signature, **opts)
|
102
|
+
else
|
103
|
+
key.verify(blob, @signature)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Gets the public key from the signature.
|
108
|
+
# If the signature was created from a certificate, this will be an
|
109
|
+
# SSHData::Certificate. Otherwise, this will be a PublicKey algorithm.
|
110
|
+
def public_key
|
111
|
+
@data_public_key ||= load_public_key
|
112
|
+
end
|
113
|
+
|
114
|
+
private def load_public_key
|
115
|
+
public_key_algorithm, _ = Encoding.decode_string(@publickey)
|
116
|
+
|
117
|
+
if PublicKey::ALGOS.include?(public_key_algorithm)
|
118
|
+
PublicKey.parse_rfc4253(@publickey)
|
119
|
+
elsif Certificate::ALGOS.include?(public_key_algorithm)
|
120
|
+
Certificate.parse_rfc4253(@publickey)
|
121
|
+
else
|
122
|
+
raise UnsupportedError, "Public key algorithm #{public_key_algorithm} is not supported."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/ssh_data/version.rb
CHANGED
data/lib/ssh_data.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssh_data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mastahyeti
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-06 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: base64
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0.1'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0.1'
|
13
26
|
- !ruby/object:Gem::Dependency
|
14
27
|
name: ed25519
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +65,20 @@ dependencies:
|
|
52
65
|
- - "~>"
|
53
66
|
- !ruby/object:Gem::Version
|
54
67
|
version: '3.10'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rspec-parameterized
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.0'
|
55
82
|
- !ruby/object:Gem::Dependency
|
56
83
|
name: rspec-mocks
|
57
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +93,6 @@ dependencies:
|
|
66
93
|
- - "~>"
|
67
94
|
- !ruby/object:Gem::Version
|
68
95
|
version: '3.10'
|
69
|
-
description:
|
70
96
|
email: opensource+ssh_data@github.com
|
71
97
|
executables: []
|
72
98
|
extensions: []
|
@@ -89,14 +115,15 @@ files:
|
|
89
115
|
- "./lib/ssh_data/public_key/ecdsa.rb"
|
90
116
|
- "./lib/ssh_data/public_key/ed25519.rb"
|
91
117
|
- "./lib/ssh_data/public_key/rsa.rb"
|
118
|
+
- "./lib/ssh_data/public_key/security_key.rb"
|
92
119
|
- "./lib/ssh_data/public_key/skecdsa.rb"
|
93
120
|
- "./lib/ssh_data/public_key/sked25519.rb"
|
121
|
+
- "./lib/ssh_data/signature.rb"
|
94
122
|
- "./lib/ssh_data/version.rb"
|
95
123
|
homepage: https://github.com/github/ssh_data
|
96
124
|
licenses:
|
97
125
|
- MIT
|
98
126
|
metadata: {}
|
99
|
-
post_install_message:
|
100
127
|
rdoc_options: []
|
101
128
|
require_paths:
|
102
129
|
- lib
|
@@ -104,15 +131,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
131
|
requirements:
|
105
132
|
- - ">="
|
106
133
|
- !ruby/object:Gem::Version
|
107
|
-
version: '
|
134
|
+
version: '3.1'
|
108
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
136
|
requirements:
|
110
137
|
- - ">="
|
111
138
|
- !ruby/object:Gem::Version
|
112
139
|
version: '0'
|
113
140
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
115
|
-
signing_key:
|
141
|
+
rubygems_version: 3.6.2
|
116
142
|
specification_version: 4
|
117
143
|
summary: Library for parsing SSH certificates
|
118
144
|
test_files: []
|