putty-key 1.0.1 → 1.1.1

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 (70) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  3. data/CHANGES.md +23 -0
  4. data/Gemfile +10 -5
  5. data/LICENSE +1 -1
  6. data/README.md +32 -6
  7. data/Rakefile +24 -0
  8. data/lib/putty/key/argon2_params.rb +101 -0
  9. data/lib/putty/key/error.rb +17 -0
  10. data/lib/putty/key/libargon2.rb +54 -0
  11. data/lib/putty/key/openssl.rb +279 -48
  12. data/lib/putty/key/ppk.rb +482 -104
  13. data/lib/putty/key/util.rb +10 -10
  14. data/lib/putty/key/version.rb +1 -1
  15. data/lib/putty/key.rb +6 -6
  16. data/putty-key.gemspec +11 -2
  17. data/test/argon2_params_test.rb +144 -0
  18. data/test/fixtures/{dss-1024-encrypted.ppk → dss-1024-encrypted-format-2.ppk} +17 -17
  19. data/test/fixtures/dss-1024-encrypted-format-3.ppk +22 -0
  20. data/test/fixtures/{dss-1024.ppk → dss-1024-format-2.ppk} +17 -17
  21. data/test/fixtures/dss-1024-format-3.ppk +17 -0
  22. data/test/fixtures/{ecdsa-sha2-nistp256-encrypted.ppk → ecdsa-sha2-nistp256-encrypted-format-2.ppk} +10 -10
  23. data/test/fixtures/ecdsa-sha2-nistp256-encrypted-format-3.ppk +15 -0
  24. data/test/fixtures/{ecdsa-sha2-nistp256.ppk → ecdsa-sha2-nistp256-format-2.ppk} +10 -10
  25. data/test/fixtures/ecdsa-sha2-nistp256-format-3.ppk +10 -0
  26. data/test/fixtures/{ecdsa-sha2-nistp384-encrypted.ppk → ecdsa-sha2-nistp384-encrypted-format-2.ppk} +11 -11
  27. data/test/fixtures/ecdsa-sha2-nistp384-encrypted-format-3.ppk +16 -0
  28. data/test/fixtures/{ecdsa-sha2-nistp384.ppk → ecdsa-sha2-nistp384-format-2.ppk} +11 -11
  29. data/test/fixtures/ecdsa-sha2-nistp384-format-3.ppk +11 -0
  30. data/test/fixtures/{ecdsa-sha2-nistp521-encrypted.ppk → ecdsa-sha2-nistp521-encrypted-format-2.ppk} +12 -12
  31. data/test/fixtures/ecdsa-sha2-nistp521-encrypted-format-3.ppk +17 -0
  32. data/test/fixtures/{ecdsa-sha2-nistp521.ppk → ecdsa-sha2-nistp521-format-2.ppk} +12 -12
  33. data/test/fixtures/ecdsa-sha2-nistp521-format-3.ppk +12 -0
  34. data/test/fixtures/{rsa-2048-encrypted.ppk → rsa-2048-encrypted-format-2.ppk} +26 -26
  35. data/test/fixtures/rsa-2048-encrypted-format-3.ppk +31 -0
  36. data/test/fixtures/{rsa-2048.ppk → rsa-2048-format-2.ppk} +26 -26
  37. data/test/fixtures/rsa-2048-format-3.ppk +26 -0
  38. data/test/fixtures/test-blank-comment.ppk +11 -11
  39. data/test/fixtures/test-empty-blobs-encrypted.ppk +6 -0
  40. data/test/fixtures/test-empty-blobs.ppk +6 -0
  41. data/test/fixtures/{test-encrypted.ppk → test-encrypted-format-2.ppk} +11 -11
  42. data/test/fixtures/test-encrypted-format-3.ppk +16 -0
  43. data/test/fixtures/test-encrypted-type-d-format-3.ppk +16 -0
  44. data/test/fixtures/test-encrypted-type-i-format-3.ppk +16 -0
  45. data/test/fixtures/{test-unix-line-endings.ppk → test-format-2.ppk} +0 -0
  46. data/test/fixtures/test-format-3.ppk +11 -0
  47. data/test/fixtures/test-invalid-argon2-memory-for-libargon2.ppk +16 -0
  48. data/test/fixtures/test-invalid-argon2-memory-maximum.ppk +16 -0
  49. data/test/fixtures/test-invalid-argon2-memory.ppk +16 -0
  50. data/test/fixtures/test-invalid-argon2-parallelism-maximum.ppk +16 -0
  51. data/test/fixtures/test-invalid-argon2-parallelism.ppk +16 -0
  52. data/test/fixtures/test-invalid-argon2-passes-maximum.ppk +16 -0
  53. data/test/fixtures/test-invalid-argon2-passes.ppk +16 -0
  54. data/test/fixtures/test-invalid-argon2-salt.ppk +16 -0
  55. data/test/fixtures/test-invalid-blob-lines.ppk +11 -11
  56. data/test/fixtures/test-invalid-encryption-type.ppk +11 -11
  57. data/test/fixtures/test-invalid-format-1.ppk +11 -11
  58. data/test/fixtures/{test-invalid-format-3.ppk → test-invalid-format-4.ppk} +11 -11
  59. data/test/fixtures/test-invalid-key-derivation.ppk +16 -0
  60. data/test/fixtures/test-invalid-private-mac.ppk +11 -11
  61. data/test/fixtures/test-legacy-mac-line-endings.ppk +1 -0
  62. data/test/fixtures/test-missing-final-line-ending.ppk +11 -0
  63. data/test/fixtures/test-truncated.ppk +10 -10
  64. data/test/fixtures/{test.ppk → test-windows-line-endings.ppk} +0 -0
  65. data/test/openssl_test.rb +243 -53
  66. data/test/ppk_test.rb +325 -44
  67. data/test/test_helper.rb +10 -3
  68. data.tar.gz.sig +0 -0
  69. metadata +73 -23
  70. metadata.gz.sig +0 -0
@@ -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
- ::OpenSSL::PKey::DSA.new.tap do |pkey|
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
- ::OpenSSL::PKey::RSA.new.tap do |pkey|
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
- curve = OPENSSL_CURVES[$1]
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
- include OpenSSL.const_get(name)
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
- include OpenSSL::ClassMethods
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