putty-key 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +7 -0
- data/Gemfile +12 -1
- data/LICENSE +1 -1
- data/lib/putty/key/openssl.rb +279 -48
- data/lib/putty/key/ppk.rb +14 -2
- data/lib/putty/key/version.rb +1 -1
- data/test/test_helper.rb +10 -3
- data.tar.gz.sig +0 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7206dacd7197ee9c1344a8cbf607c72614ab3031241bb72a32648bbe62cd784a
|
4
|
+
data.tar.gz: d2835eaa489968b975a93c7cb89e8d7b1dde7e52dc597cc48b54c2b3d9c59c5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bc6d6331bd8e27ebb082a3bee81b71953cc75e7eea0c80cb6aa3577b4f47a22b379683188a800321848aecffd6e5e6ead37fc1691593c717f9a5b189a03f671
|
7
|
+
data.tar.gz: 5e9b7f92503ba1d3ee96089d42fc20f0ab59203c80c6eca9c2e284df67dacf877356ef6a8bbadca8ac569250f9b965b290f5904bfd6885f9f1648e76c0a39dfc
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changes #
|
2
2
|
|
3
|
+
## Version 1.1.1 - 23-Oct-2022 ##
|
4
|
+
|
5
|
+
* Add support for Ruby 3.2.
|
6
|
+
* Add support for OpenSSL 3 (requires either Ruby 3.1+, or version 3.0.0+ of the
|
7
|
+
openssl gem).
|
8
|
+
|
9
|
+
|
3
10
|
## Version 1.1.0 - 24-May-2021 ##
|
4
11
|
|
5
12
|
* Add support for [format 3 .ppk files](https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ppk3.html)
|
data/Gemfile
CHANGED
@@ -12,6 +12,17 @@ group :test do
|
|
12
12
|
|
13
13
|
# coveralls is no longer maintained, but supports Ruby < 2.3.
|
14
14
|
# coveralls_reborn is maintained, but requires Ruby >= 2.3.
|
15
|
-
gem 'coveralls', '
|
15
|
+
gem 'coveralls', git: 'https://github.com/philr/coveralls-ruby.git', require: false if RUBY_VERSION < '2.3'
|
16
16
|
gem 'coveralls_reborn', '~> 0.13', require: false if RUBY_VERSION >= '2.3'
|
17
|
+
|
18
|
+
# The source version of ffi 1.15.5 is declared as compatible with Ruby >= 2.3.
|
19
|
+
# The binary version of 1.15.5 is declared as compatible with Ruby >= 2.4, so
|
20
|
+
# doesn't get used. The using the source version results in a segmentation
|
21
|
+
# fault during libffi initialization.
|
22
|
+
#
|
23
|
+
# Binaries of 15.5.0 to 15.5.4 are declared as compatible with Ruby >= 2.3,
|
24
|
+
# but don't get used with Bundler 2.3.23 and Ruby 2.3 on Windows.
|
25
|
+
#
|
26
|
+
# Limit to earlier compatible versions.
|
27
|
+
gem 'ffi', '< 1.15.0' if RUBY_VERSION < '2.4' && RUBY_PLATFORM =~ /mingw/
|
17
28
|
end
|
data/LICENSE
CHANGED
data/lib/putty/key/openssl.rb
CHANGED
@@ -25,10 +25,266 @@ module PuTTY
|
|
25
25
|
|
26
26
|
private_constant :SSH_CURVES
|
27
27
|
|
28
|
+
# OpenSSL version helper methods.
|
29
|
+
#
|
30
|
+
# @private
|
31
|
+
module Version
|
32
|
+
class << self
|
33
|
+
# Determines if the Ruby OpenSSL wrapper is using the OpenSSL library
|
34
|
+
# (not LibreSSL and not JRuby) and if the version matches the required
|
35
|
+
# version.
|
36
|
+
#
|
37
|
+
# @param major [Integer] The required major version. `nil` if any
|
38
|
+
# version of OpenSSL is sufficient.
|
39
|
+
# @param minor [Integer] The required minor version.
|
40
|
+
# @param fix [Integer] The required fix version.
|
41
|
+
# @param patch [Integer] The required patch version.
|
42
|
+
# @return [Boolean] `true` if the requirements are met, otherwise
|
43
|
+
# `false`.
|
44
|
+
def openssl?(major = nil, minor = 0, fix = 0, patch = 0)
|
45
|
+
return false if ::OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
|
46
|
+
return false if ::OpenSSL::OPENSSL_VERSION.include?('JRuby')
|
47
|
+
return true unless major
|
48
|
+
required_version = major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10
|
49
|
+
::OpenSSL::OPENSSL_VERSION_NUMBER >= required_version
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
private_constant :Version
|
54
|
+
|
55
|
+
# Methods to build OpenSSL private keys from a {PPK}.
|
56
|
+
#
|
57
|
+
# @private
|
58
|
+
module PKeyBuilding
|
59
|
+
class << self
|
60
|
+
# Creates a new OpenSSL DSA private key for the given DSA {PPK}.
|
61
|
+
#
|
62
|
+
# @param ppk [PPK] A DSA {PPK}.
|
63
|
+
# @return [::OpenSSL::PKey::DSA] The OpenSSL DSA private key.
|
64
|
+
def ppk_to_dsa(ppk)
|
65
|
+
_, p, q, g, pub_key = Util.ssh_unpack(ppk.public_blob, :string, :mpint, :mpint, :mpint, :mpint)
|
66
|
+
priv_key = Util.ssh_unpack(ppk.private_blob, :mpint).first
|
67
|
+
dsa_from_params(p, q, g, pub_key, priv_key)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Creates a new OpenSSL RSA private key for the given RSA {PPK}.
|
71
|
+
#
|
72
|
+
# @param ppk [PPK] An RSA {PPK}.
|
73
|
+
# @return [::OpenSSL::PKey::RSA] The OpenSSL RSA private key.
|
74
|
+
def ppk_to_rsa(ppk)
|
75
|
+
_, e, n = Util.ssh_unpack(ppk.public_blob, :string, :mpint, :mpint)
|
76
|
+
d, p, q, iqmp = Util.ssh_unpack(ppk.private_blob, :mpint, :mpint, :mpint, :mpint)
|
77
|
+
dmp1 = d % (p - 1)
|
78
|
+
dmq1 = d % (q - 1)
|
79
|
+
rsa_from_params(e, n, d, p, q, iqmp, dmp1, dmq1)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Creates a new OpenSSL EC private key for the given EC {PPK}.
|
83
|
+
#
|
84
|
+
# @param ppk [PPK] An EC {PPK}.
|
85
|
+
# @param ppk_curve [String] The PPK curve name extracted from the
|
86
|
+
# PPK algorithm name.
|
87
|
+
# @return [::OpenSSL::PKey::EC] The OpenSSL EC private key.
|
88
|
+
def ppk_to_ec(ppk, ppk_curve)
|
89
|
+
curve = OPENSSL_CURVES[ppk_curve]
|
90
|
+
_, _, pub_key = Util.ssh_unpack(ppk.public_blob, :string, :string, :mpint)
|
91
|
+
priv_key = Util.ssh_unpack(ppk.private_blob, :mpint).first
|
92
|
+
ec_from_params(curve, pub_key, priv_key)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
if Version.openssl?(3)
|
98
|
+
# OpenSSL v3 private keys are immutable. The Ruby OpenSSL wrapper
|
99
|
+
# doesn't provide a method to construct private keys using the
|
100
|
+
# parameters. Build DER (ASN.1) encoded versions of the keys.
|
101
|
+
#
|
102
|
+
# In theory this should be usable universally. However
|
103
|
+
# ::OpenSSL::PKey::EC::Point#to_octet_string is only supported from
|
104
|
+
# Ruby >= 2.4 and there are issues with JRuby's OpenSSL library
|
105
|
+
# (that doesn't make use of OpenSSL).
|
106
|
+
|
107
|
+
# :nocov_no_openssl3:
|
108
|
+
|
109
|
+
# Creates a new OpenSSL DSA private key with the given parameters.
|
110
|
+
#
|
111
|
+
# @param p [::OpenSSL::BN] The p parameter (prime).
|
112
|
+
# @param q [::OpenSSL::BN] The q parameter (prime).
|
113
|
+
# @param g [::OpenSSL::BN] The g parameter.
|
114
|
+
# @param pub_key [::OpenSSL::BN] The public key.
|
115
|
+
# @param priv_key [::OpenSSL::BN] The private key.
|
116
|
+
# @return [::OpenSSL::PKey::DSA] The OpenSSL DSA private key.
|
117
|
+
def dsa_from_params(p, q, g, pub_key, priv_key)
|
118
|
+
# https://www.openssl.org/docs/man3.0/man1/openssl-dsa.html (outform parameter).
|
119
|
+
sequence = [
|
120
|
+
::OpenSSL::ASN1::Integer.new(0),
|
121
|
+
::OpenSSL::ASN1::Integer.new(p),
|
122
|
+
::OpenSSL::ASN1::Integer.new(q),
|
123
|
+
::OpenSSL::ASN1::Integer.new(g),
|
124
|
+
::OpenSSL::ASN1::Integer.new(pub_key),
|
125
|
+
::OpenSSL::ASN1::Integer.new(priv_key)
|
126
|
+
]
|
127
|
+
|
128
|
+
::OpenSSL::PKey::DSA.new(::OpenSSL::ASN1::Sequence.new(sequence).to_der)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Creates a new OpenSSL RSA private key with the given parameters.
|
132
|
+
#
|
133
|
+
# @param e [::OpenSSL::BN] The public key exponent.
|
134
|
+
# @param n [::OpenSSL::BN] The modulus.
|
135
|
+
# @param d [::OpenSSL::BN] The private key exponent.
|
136
|
+
# @param p [::OpenSSL::BN] The p prime.
|
137
|
+
# @param q [::OpenSSL::BN] The q prime.
|
138
|
+
# @param iqmp [::OpenSSL::BN] The inverse of q, mod p.
|
139
|
+
# @param dmp1 [::OpenSSL::BN] `d` mod (`p` - 1).
|
140
|
+
# @param dmq1 [::OpenSSL::BN] `d` mod (`q` - 1).
|
141
|
+
# @return [::OpenSSL::PKey::RSA] The OpenSSL RSA private key.
|
142
|
+
def rsa_from_params(e, n, d, p, q, iqmp, dmp1, dmq1)
|
143
|
+
# RFC 3447 Appendix A.1.2
|
144
|
+
sequence = [
|
145
|
+
::OpenSSL::ASN1::Integer.new(0),
|
146
|
+
::OpenSSL::ASN1::Integer.new(n),
|
147
|
+
::OpenSSL::ASN1::Integer.new(e),
|
148
|
+
::OpenSSL::ASN1::Integer.new(d),
|
149
|
+
::OpenSSL::ASN1::Integer.new(p),
|
150
|
+
::OpenSSL::ASN1::Integer.new(q),
|
151
|
+
::OpenSSL::ASN1::Integer.new(dmp1),
|
152
|
+
::OpenSSL::ASN1::Integer.new(dmq1),
|
153
|
+
::OpenSSL::ASN1::Integer.new(iqmp)
|
154
|
+
]
|
155
|
+
|
156
|
+
::OpenSSL::PKey::RSA.new(::OpenSSL::ASN1::Sequence.new(sequence).to_der)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Creates a new OpenSSL EC private key with the given parameters.
|
160
|
+
#
|
161
|
+
# @param curve [String] The name of the OpenSSL EC curve.
|
162
|
+
# @param pub_key [::OpenSSL::BN] The public key.
|
163
|
+
# @param priv_key [::OpenSSL::BN] The private key.
|
164
|
+
# @return [::OpenSSL::PKey::EC] The OpenSSL EC private key.
|
165
|
+
def ec_from_params(curve, pub_key, priv_key)
|
166
|
+
group = ::OpenSSL::PKey::EC::Group.new(curve)
|
167
|
+
point = ::OpenSSL::PKey::EC::Point.new(group, pub_key)
|
168
|
+
point_string = point.to_octet_string(:uncompressed)
|
169
|
+
|
170
|
+
# RFC 5915 Section 3
|
171
|
+
sequence = [
|
172
|
+
::OpenSSL::ASN1::Integer.new(1),
|
173
|
+
::OpenSSL::ASN1::OctetString.new(priv_key.to_s(2)),
|
174
|
+
::OpenSSL::ASN1::ObjectId.new(curve, 0, :EXPLICIT),
|
175
|
+
::OpenSSL::ASN1::BitString.new(point_string, 1, :EXPLICIT)
|
176
|
+
]
|
177
|
+
|
178
|
+
::OpenSSL::PKey::EC.new(::OpenSSL::ASN1::Sequence.new(sequence).to_der)
|
179
|
+
end
|
180
|
+
# :nocov_no_openssl3:
|
181
|
+
else
|
182
|
+
# :nocov_openssl3:
|
183
|
+
if ::OpenSSL::PKey::DSA.new.respond_to?(:set_key)
|
184
|
+
# :nocov_no_openssl_pkey_dsa_set_key:
|
185
|
+
|
186
|
+
# Creates a new OpenSSL DSA private key with the given parameters.
|
187
|
+
#
|
188
|
+
# @param p [::OpenSSL::BN] The p parameter.
|
189
|
+
# @param q [::OpenSSL::BN] The q parameter.
|
190
|
+
# @param g [::OpenSSL::BN] The g parameter.
|
191
|
+
# @param pub_key [::OpenSSL::BN] The public key.
|
192
|
+
# @param priv_key [::OpenSSL::BN] The private key.
|
193
|
+
# @return [::OpenSSL::PKey::DSA] The OpenSSL DSA private key.
|
194
|
+
def dsa_from_params(p, q, g, pub_key, priv_key)
|
195
|
+
::OpenSSL::PKey::DSA.new.tap do |pkey|
|
196
|
+
pkey.set_key(pub_key, priv_key)
|
197
|
+
pkey.set_pqg(p, q, g)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
# :nocov_no_openssl_pkey_dsa_set_key:
|
201
|
+
else
|
202
|
+
# :nocov_openssl_pkey_dsa_set_key:
|
203
|
+
# Creates a new OpenSSL DSA private key with the given parameters.
|
204
|
+
#
|
205
|
+
# @param p [::OpenSSL::BN] The p parameter.
|
206
|
+
# @param q [::OpenSSL::BN] The q parameter.
|
207
|
+
# @param g [::OpenSSL::BN] The g parameter.
|
208
|
+
# @param pub_key [::OpenSSL::BN] The public key.
|
209
|
+
# @param priv_key [::OpenSSL::BN] The private key.
|
210
|
+
# @return [::OpenSSL::PKey::DSA] The OpenSSL DSA private key.
|
211
|
+
def dsa_from_params(p, q, g, pub_key, priv_key)
|
212
|
+
::OpenSSL::PKey::DSA.new.tap do |pkey|
|
213
|
+
pkey.p, pkey.q, pkey.g, pkey.pub_key, pkey.priv_key = p, q, g, pub_key, priv_key
|
214
|
+
end
|
215
|
+
end
|
216
|
+
# :nocov_openssl_pkey_dsa_set_key:
|
217
|
+
end
|
218
|
+
|
219
|
+
if ::OpenSSL::PKey::RSA.new.respond_to?(:set_factors)
|
220
|
+
# :nocov_no_openssl_pkey_rsa_set_factors:
|
221
|
+
|
222
|
+
# Creates a new OpenSSL RSA private key with the given parameters.
|
223
|
+
#
|
224
|
+
# @param e [::OpenSSL::BN] The public key exponent.
|
225
|
+
# @param n [::OpenSSL::BN] The modulus.
|
226
|
+
# @param d [::OpenSSL::BN] The private key exponent.
|
227
|
+
# @param p [::OpenSSL::BN] The p prime.
|
228
|
+
# @param q [::OpenSSL::BN] The q prime.
|
229
|
+
# @param iqmp [::OpenSSL::BN] The inverse of q, mod p.
|
230
|
+
# @param dmp1 [::OpenSSL::BN] `d` mod (`p` - 1).
|
231
|
+
# @param dmq1 [::OpenSSL::BN] `d` mod (`q` - 1).
|
232
|
+
# @return [::OpenSSL::PKey::RSA] The OpenSSL RSA private key.
|
233
|
+
def rsa_from_params(e, n, d, p, q, iqmp, dmp1, dmq1)
|
234
|
+
::OpenSSL::PKey::RSA.new.tap do |pkey|
|
235
|
+
pkey.set_factors(p, q)
|
236
|
+
pkey.set_key(n, e, d)
|
237
|
+
pkey.set_crt_params(dmp1, dmq1, iqmp)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
# :nocov_no_openssl_pkey_rsa_set_factors:
|
241
|
+
else
|
242
|
+
# :nocov_openssl_pkey_rsa_set_factors:
|
243
|
+
|
244
|
+
# Creates a new OpenSSL RSA private key with the given parameters.
|
245
|
+
#
|
246
|
+
# @param e [::OpenSSL::BN] The public key exponent.
|
247
|
+
# @param n [::OpenSSL::BN] The modulus.
|
248
|
+
# @param d [::OpenSSL::BN] The private key exponent.
|
249
|
+
# @param p [::OpenSSL::BN] The p prime.
|
250
|
+
# @param q [::OpenSSL::BN] The q prime.
|
251
|
+
# @param iqmp [::OpenSSL::BN] The inverse of q, mod p.
|
252
|
+
# @param dmp1 [::OpenSSL::BN] `d` mod (`p` - 1).
|
253
|
+
# @param dmq1 [::OpenSSL::BN] `d` mod (`q` - 1).
|
254
|
+
# @return [::OpenSSL::PKey::RSA] The OpenSSL RSA private key.
|
255
|
+
def rsa_from_params(e, n, d, p, q, iqmp, dmp1, dmq1)
|
256
|
+
::OpenSSL::PKey::RSA.new.tap do |pkey|
|
257
|
+
pkey.e, pkey.n, pkey.d, pkey.p, pkey.q, pkey.iqmp, pkey.dmp1, pkey.dmq1 = e, n, d, p, q, iqmp, dmp1, dmq1
|
258
|
+
end
|
259
|
+
end
|
260
|
+
# :nocov_openssl_pkey_rsa_set_factors:
|
261
|
+
end
|
262
|
+
|
263
|
+
# Creates a new OpenSSL EC private key with the given parameters.
|
264
|
+
#
|
265
|
+
# @param curve [String] The name of the OpenSSL EC curve.
|
266
|
+
# @param pub_key [::OpenSSL::BN] The public key.
|
267
|
+
# @param priv_key [::OpenSSL::BN] The private key.
|
268
|
+
# @return [::OpenSSL::PKey::EC] The OpenSSL EC private key.
|
269
|
+
def ec_from_params(curve, pub_key, priv_key)
|
270
|
+
# Old versions of jruby-openssl don't include an EC class (version 0.9.16).
|
271
|
+
ec_class = (::OpenSSL::PKey::EC rescue raise ArgumentError, "Unsupported algorithm: #{ppk.algorithm}")
|
272
|
+
|
273
|
+
ec_class.new(curve).tap do |pkey|
|
274
|
+
group = pkey.group || ::OpenSSL::PKey::EC::Group.new(curve)
|
275
|
+
pkey.public_key = ::OpenSSL::PKey::EC::Point.new(group, pub_key)
|
276
|
+
pkey.private_key = priv_key
|
277
|
+
end
|
278
|
+
end
|
279
|
+
# :nocov_openssl3:
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
private_constant :PKeyBuilding
|
284
|
+
|
28
285
|
# The {ClassMethods} module is used to extend `OpenSSL::PKey` when
|
29
286
|
# using the PuTTY::Key refinement or calling {PuTTY::Key.global_install}.
|
30
287
|
# This adds a `from_ppk` class method to `OpenSSL::PKey`.
|
31
|
-
#
|
32
288
|
module ClassMethods
|
33
289
|
# Creates a new `OpenSSL::PKey` from a PuTTY private key (instance of
|
34
290
|
# {PPK}).
|
@@ -50,53 +306,11 @@ module PuTTY
|
|
50
306
|
|
51
307
|
case ppk.algorithm
|
52
308
|
when 'ssh-dss'
|
53
|
-
|
54
|
-
_, p, q, g, pub_key = Util.ssh_unpack(ppk.public_blob, :string, :mpint, :mpint, :mpint, :mpint)
|
55
|
-
priv_key = Util.ssh_unpack(ppk.private_blob, :mpint).first
|
56
|
-
|
57
|
-
if pkey.respond_to?(:set_key)
|
58
|
-
# :nocov_no_openssl_pkey_dsa_set_key:
|
59
|
-
pkey.set_key(pub_key, priv_key)
|
60
|
-
pkey.set_pqg(p, q, g)
|
61
|
-
# :nocov_no_openssl_pkey_dsa_set_key:
|
62
|
-
else
|
63
|
-
# :nocov_openssl_pkey_dsa_set_key:
|
64
|
-
pkey.p, pkey.q, pkey.g, pkey.pub_key, pkey.priv_key = p, q, g, pub_key, priv_key
|
65
|
-
# :nocov_openssl_pkey_dsa_set_key:
|
66
|
-
end
|
67
|
-
end
|
309
|
+
PKeyBuilding.ppk_to_dsa(ppk)
|
68
310
|
when 'ssh-rsa'
|
69
|
-
|
70
|
-
_, e, n = Util.ssh_unpack(ppk.public_blob, :string, :mpint, :mpint)
|
71
|
-
d, p, q, iqmp = Util.ssh_unpack(ppk.private_blob, :mpint, :mpint, :mpint, :mpint)
|
72
|
-
|
73
|
-
dmp1 = d % (p - 1)
|
74
|
-
dmq1 = d % (q - 1)
|
75
|
-
|
76
|
-
if pkey.respond_to?(:set_factors)
|
77
|
-
# :nocov_no_openssl_pkey_rsa_set_factors:
|
78
|
-
pkey.set_factors(p, q)
|
79
|
-
pkey.set_key(n, e, d)
|
80
|
-
pkey.set_crt_params(dmp1, dmq1, iqmp)
|
81
|
-
# :nocov_no_openssl_pkey_rsa_set_factors:
|
82
|
-
else
|
83
|
-
# :nocov_openssl_pkey_rsa_set_factors:
|
84
|
-
pkey.e, pkey.n, pkey.d, pkey.p, pkey.q, pkey.iqmp, pkey.dmp1, pkey.dmq1 = e, n, d, p, q, iqmp, dmp1, dmq1
|
85
|
-
# :nocov_openssl_pkey_rsa_set_factors:
|
86
|
-
end
|
87
|
-
end
|
311
|
+
PKeyBuilding.ppk_to_rsa(ppk)
|
88
312
|
when /\Aecdsa-sha2-(nistp(?:256|384|521))\z/
|
89
|
-
|
90
|
-
|
91
|
-
# Old versions of jruby-openssl don't include an EC class (version 0.9.16).
|
92
|
-
ec_class = (::OpenSSL::PKey::EC rescue raise ArgumentError, "Unsupported algorithm: #{ppk.algorithm}")
|
93
|
-
|
94
|
-
ec_class.new(curve).tap do |pkey|
|
95
|
-
_, _, point = Util.ssh_unpack(ppk.public_blob, :string, :string, :mpint)
|
96
|
-
group = pkey.group || ::OpenSSL::PKey::EC::Group.new(curve)
|
97
|
-
pkey.public_key = ::OpenSSL::PKey::EC::Point.new(group, point)
|
98
|
-
pkey.private_key = Util.ssh_unpack(ppk.private_blob, :mpint).first
|
99
|
-
end
|
313
|
+
PKeyBuilding.ppk_to_ec(ppk, $1)
|
100
314
|
else
|
101
315
|
raise ArgumentError, "Unsupported algorithm: #{ppk.algorithm}"
|
102
316
|
end
|
@@ -201,13 +415,30 @@ module PuTTY
|
|
201
415
|
end
|
202
416
|
|
203
417
|
OpenSSL.const_get(:PKEY_CLASSES).each do |name, openssl_class|
|
418
|
+
mod = OpenSSL.const_get(name)
|
204
419
|
refine openssl_class do
|
205
|
-
|
420
|
+
if defined?(::Refinement) && kind_of?(::Refinement)
|
421
|
+
# :nocov_no_refinement_class:
|
422
|
+
import_methods(mod)
|
423
|
+
# :nocov_no_refinement_class:
|
424
|
+
else
|
425
|
+
# :nocov_refinement_class:
|
426
|
+
include mod
|
427
|
+
# :nocov_refinement_class:
|
428
|
+
end
|
206
429
|
end if respond_to?(:refine, true)
|
207
430
|
end
|
208
431
|
|
209
432
|
refine ::OpenSSL::PKey.singleton_class do
|
210
|
-
|
433
|
+
if defined?(::Refinement) && kind_of?(::Refinement)
|
434
|
+
# :nocov_no_refinement_class:
|
435
|
+
import_methods(OpenSSL::ClassMethods)
|
436
|
+
# :nocov_no_refinement_class:
|
437
|
+
else
|
438
|
+
# :nocov_refinement_class:
|
439
|
+
include OpenSSL::ClassMethods
|
440
|
+
# :nocov_refinement_class:
|
441
|
+
end
|
211
442
|
end if respond_to?(:refine, true)
|
212
443
|
end
|
213
444
|
end
|
data/lib/putty/key/ppk.rb
CHANGED
@@ -319,7 +319,19 @@ module PuTTY
|
|
319
319
|
def derive_keys(format, cipher = nil, passphrase = nil, argon2_params = nil)
|
320
320
|
if format >= 3
|
321
321
|
return derive_format_3_keys(cipher, passphrase, argon2_params) if cipher
|
322
|
-
|
322
|
+
|
323
|
+
# An empty string should work for the MAC, but ::OpenSSL::HMAC fails
|
324
|
+
# when used with OpenSSL 3:
|
325
|
+
#
|
326
|
+
# EVP_PKEY_new_mac_key: malloc failure (OpenSSL::HMACError).
|
327
|
+
#
|
328
|
+
# See https://github.com/ruby/openssl/pull/538 and
|
329
|
+
# https://github.com/openssl/openssl/issues/13089.
|
330
|
+
#
|
331
|
+
# Ruby 3.1.3 should contain the workaround from ruby/openssl PR 538.
|
332
|
+
#
|
333
|
+
# Use "\0" as the MAC key for a workaround for Ruby < 3.1.3.
|
334
|
+
return ["\0".b, nil, nil, nil]
|
323
335
|
end
|
324
336
|
|
325
337
|
mac_key = derive_format_2_mac_key(passphrase)
|
@@ -481,7 +493,7 @@ module PuTTY
|
|
481
493
|
# after padding bytes have been appended prior to encryption).
|
482
494
|
#
|
483
495
|
# @param format [Integer] The format of the .ppk file.
|
484
|
-
# @param
|
496
|
+
# @param mac_key [String] The HMAC key.
|
485
497
|
# @param encryption_type [String] The value of the Encryption field.
|
486
498
|
# @param padded_private_blob [String] The private blob after padding bytes
|
487
499
|
# have been appended prior to encryption.
|
data/lib/putty/key/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'putty/key'
|
4
|
+
|
3
5
|
TEST_TYPE = (ENV['TEST_TYPE'] || 'refinement').to_sym
|
4
6
|
raise "Unrecognized TEST_TYPE: #{TEST_TYPE}" unless [:refinement, :global].include?(TEST_TYPE)
|
5
7
|
|
@@ -15,6 +17,13 @@ if TEST_COVERAGE
|
|
15
17
|
"#{object.respond_to?(method) ? '' : 'no_'}#{Regexp.escape(object.class.name.downcase.gsub('::', '_'))}_#{Regexp.escape(method)}"
|
16
18
|
end
|
17
19
|
|
20
|
+
feature_support = [
|
21
|
+
['openssl3', PuTTY::Key::OpenSSL.const_get(:Version).openssl?(3)],
|
22
|
+
['refinement_class', defined?(Refinement)]
|
23
|
+
].map do |feature, available|
|
24
|
+
"#{available ? '' : 'no_'}#{feature}"
|
25
|
+
end
|
26
|
+
|
18
27
|
SimpleCov.command_name TEST_TYPE.to_s
|
19
28
|
|
20
29
|
SimpleCov.formatters = [
|
@@ -23,13 +32,11 @@ if TEST_COVERAGE
|
|
23
32
|
|
24
33
|
SimpleCov.start do
|
25
34
|
add_filter 'test'
|
26
|
-
nocov_token "nocov_(#{method_support.join('|')})"
|
35
|
+
nocov_token "nocov_(#{(method_support + feature_support).join('|')})"
|
27
36
|
project_name 'PuTTY::Key'
|
28
37
|
end
|
29
38
|
end
|
30
39
|
|
31
|
-
require 'putty/key'
|
32
|
-
|
33
40
|
require 'fileutils'
|
34
41
|
require 'minitest/autorun'
|
35
42
|
require 'tmpdir'
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: putty-key
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philip Ross
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
J3Zn/kSTjTekiaspyGbczC3PUaeJNxr+yCvR4sk71Xmk/GaKKGOHedJ1uj/LAXrA
|
30
30
|
MR0mpl7b8zCg0PFC1J73uw==
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date:
|
32
|
+
date: 2022-10-23 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: ffi
|
@@ -139,9 +139,9 @@ licenses:
|
|
139
139
|
metadata:
|
140
140
|
bug_tracker_uri: https://github.com/philr/putty-key/issues
|
141
141
|
changelog_uri: https://github.com/philr/putty-key/blob/master/CHANGES.md
|
142
|
-
documentation_uri: https://rubydoc.info/gems/putty-key/1.1.
|
142
|
+
documentation_uri: https://rubydoc.info/gems/putty-key/1.1.1
|
143
143
|
homepage_uri: https://github.com/philr/putty-key
|
144
|
-
source_code_uri: https://github.com/philr/putty-key/tree/v1.1.
|
144
|
+
source_code_uri: https://github.com/philr/putty-key/tree/v1.1.1
|
145
145
|
post_install_message:
|
146
146
|
rdoc_options:
|
147
147
|
- "--title"
|
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
164
|
version: '0'
|
165
165
|
requirements:
|
166
166
|
- libargon2 to handle format 3 .ppk files
|
167
|
-
rubygems_version: 3.
|
167
|
+
rubygems_version: 3.3.7
|
168
168
|
signing_key:
|
169
169
|
specification_version: 4
|
170
170
|
summary: PuTTY private key (.ppk) library. Supports reading and writing with a refinement
|
metadata.gz.sig
CHANGED
Binary file
|