openssl-additions 0.4.0 → 0.5.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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openssl/ssh_pkey.rb +118 -0
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c002f0205350fca421c6edb69f29e96cb17691b2878211542ead695aeb59fe8f
4
- data.tar.gz: ecdbaf9fc58ab1d58a04df73ebdd14c59e4ed3efe72e86fee3bad7d00d18cbdd
3
+ metadata.gz: '07362825a73c86976d2405912f1edb3525e685d3e0e29322e8ce25cc1df3b3ca'
4
+ data.tar.gz: e547d3b7f72ecac40a5c180685c22b983b0e5b1179a6b4c09947aeee15bc6bad
5
5
  SHA512:
6
- metadata.gz: 6fba57730fb6e4967ab67b97c94a7c82fd907b2b0dfbcbdbbeb059f79e3d745eb16e40ce6e90c71b3ffdf12234f13335e237ccd5386581cdefe338751f46f4d0
7
- data.tar.gz: 2ba9996f6dcdc468d8bff817d5a8c8ebc6e8b97eb5146c11ded5fdacd2081f5a9223d0598638879879e42ba2b7fc6c92a6c20501d69d734f5e12cdf40b261182
6
+ metadata.gz: 977cd5463beca1c0f59f4ab4f470cd9149e8bc9c672701b592697e2c57d3a0a26218a69839d73e870b14314f91365a5cf55c3a86308a255a34982635a2e89ca5
7
+ data.tar.gz: 3bb1d9f777ffd936311ab4fe1eed977e5c9cd18e2ab42b8e942ce2eebc88bba01a0379912e229ff1da2e90a297c2d926d4e53a123767dcf1043fb9702c72e11e
@@ -44,6 +44,124 @@ module OpenSSL::PKey
44
44
  end
45
45
  end
46
46
 
47
+ # Create a new `OpenSSL::PKey` from a PuTTY private key.
48
+ #
49
+ # Given a PuTTY version 2 key file ("PPK"), an equivalent instance of an
50
+ # `OpenSSL::PKey::PKey` subclass will be derived representing the same
51
+ # key parameters.
52
+ #
53
+ # @param s [String] the PuTTY PPK file contents to convert.
54
+ #
55
+ # @yield if the key data passed is an encrypted private key, the block
56
+ # (if provided) will be called.
57
+ #
58
+ # @return [OpenSSL::PKey::PKey] the OpenSSL-compatible key object.
59
+ #
60
+ # @raise OpenSSL::PKey::PKeyError] if anything went wrong with the conversion
61
+ # process.
62
+ #
63
+ def self.from_putty_key(s, &blk)
64
+ lines = s.gsub("\r\n", "\n").gsub("\r", "\n").split("\n")
65
+
66
+ unless lines.shift =~ /\APuTTY-User-Key-File-2: ([a-z0-9-]+)\z/
67
+ raise OpenSSL::PKey::PKeyError,
68
+ "No PuTTY key file header found"
69
+ end
70
+
71
+ keytype = $1
72
+
73
+ key = case keytype
74
+ when 'ssh-rsa'
75
+ OpenSSL::PKey::RSA.new
76
+ when 'ssh-dss'
77
+ OpenSSL::PKey::DSA.new
78
+ when /ecdsa-sha2-/
79
+ OpenSSL::PKey::EC.new
80
+ else
81
+ raise OpenSSL::PKey::PKeyError,
82
+ "Unknown key type #{keytype}"
83
+ end
84
+
85
+ unless lines.shift =~ /\AEncryption: (none|aes256-cbc)\z/
86
+ raise OpenSSL::PKey::PKeyError,
87
+ "Missing or invalid PuTTY Encryption line"
88
+ end
89
+
90
+ cipher = $1
91
+
92
+ if cipher != "none"
93
+ yield if block_given?
94
+ raise OpenSSL::PKey::PKeyError,
95
+ "Encrypted PuTTY keys are not (yet) supported"
96
+ end
97
+
98
+ unless lines.shift =~ /\AComment: /
99
+ raise OpenSSL::PKey::PKeyError,
100
+ "Missing or invalid PuTTY Comment line"
101
+ end
102
+
103
+ unless lines.shift =~ /\APublic-Lines: (\d+)\z/
104
+ raise OpenSSL::PKey::PKeyError,
105
+ "Missing or invalid PuTTY Public-Lines line"
106
+ end
107
+
108
+ line_count = $1.to_i
109
+
110
+ if lines.length < line_count
111
+ raise OpenSSL::PKey::PKeyError,
112
+ "Invalid Public-Lines value, only #{lines.length} lines remaining in file"
113
+ end
114
+
115
+ pubkey = lines[0, line_count].join.unpack("m").first
116
+
117
+ lines = lines[line_count..-1]
118
+
119
+ unless lines.shift =~ /Private-Lines: (\d+)\z/
120
+ raise OpenSSL::PKey::PKeyError,
121
+ "Missing or invalid PuTTY Private-Lines line"
122
+ end
123
+
124
+ line_count = $1.to_i
125
+
126
+ if lines.length < line_count
127
+ raise OpenSSL::PKey::PKeyError,
128
+ "Invalid Private-Lines value, only #{lines.length} lines remaining in file"
129
+ end
130
+
131
+ privkey = lines[0, line_count].join.unpack("m").first
132
+
133
+ case key
134
+ when OpenSSL::PKey::RSA
135
+ _kt, e, n = ssh_key_lv_decode(pubkey, 3).map { |c| ssh_key_mpi_decode(c) }
136
+ d, p, q, iqmp, _ = ssh_key_lv_decode(privkey, 4).map { |c| ssh_key_mpi_decode(c) }
137
+
138
+ key.set_key(n, e, d)
139
+ key.set_factors(p, q)
140
+ key.set_crt_params(d % (p - 1), d % (q - 1), iqmp)
141
+ when OpenSSL::PKey::DSA
142
+ _kt, p, q, g, y = ssh_key_lv_decode(pubkey, 5).map { |c| ssh_key_mpi_decode(c) }
143
+ x, _ = ssh_key_lv_decode(privkey, 1).map { |c| ssh_key_mpi_decode(c) }
144
+
145
+ key.set_key(y, x)
146
+ key.set_pqg(p, q, g)
147
+ when OpenSSL::PKey::EC
148
+ _kt, curve, w = ssh_key_lv_decode(pubkey, 3)
149
+ p, _ = ssh_key_lv_decode(privkey, 1).map { |c| ssh_key_mpi_decode(c) }
150
+
151
+ begin
152
+ key = OpenSSL::PKey::EC.new(SSH_CURVE_NAME_MAP[curve])
153
+ rescue TypeError
154
+ raise OpenSSL::PKey::PKeyError,
155
+ "Unknown curve identifier #{curve}"
156
+ end
157
+
158
+ key.public_key = OpenSSL::PKey::EC::Point.new(key.group, w)
159
+ key.private_key = p
160
+ end
161
+
162
+ key
163
+ end
164
+
47
165
  private
48
166
 
49
167
  def self.decode_private_ssh_key(s, &blk)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openssl-additions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-03 00:00:00.000000000 Z
11
+ date: 2020-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler