openssl-additions 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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