sshkey 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,9 @@ rvm:
2
2
  - 1.8.7
3
3
  - 1.9.2
4
4
  - 1.9.3
5
- - rbx
6
- - rbx-2.0
7
5
  - ree
8
6
  - ruby-head
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - rbx-18mode
10
+ - rbx-19mode
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
+
3
+ gem "jruby-openssl", "~> 0.7.7", :platform => :jruby
2
4
 
3
5
  gemspec
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- sshkey
1
+ SSHKey
2
2
  ======
3
3
 
4
4
  Generate private and public SSH keys (RSA and DSA supported) using pure Ruby.
5
5
 
6
6
  gem install sshkey
7
7
 
8
- Tested on the following Rubies: MRI 1.8.7, 1.9.2, 1.9.3, Rubinius, REE. Ruby must be compiled with OpenSSL support.
8
+ Tested on the following Rubies: MRI 1.8.7, 1.9.2, 1.9.3, REE, JRuby, Rubinius. Ruby must be compiled with OpenSSL support.
9
9
 
10
10
  [![Build Status](https://secure.travis-ci.org/bensie/sshkey.png)](http://travis-ci.org/bensie/sshkey)
11
11
 
@@ -13,12 +13,12 @@ Usage
13
13
  -----
14
14
 
15
15
  When generating a new keypair the default key type is 2048-bit RSA, but you can supply the `type` (RSA or DSA) and `bits` in the options.
16
- You can also (optionally) supply a `comment`:
16
+ You can also (optionally) supply a `comment` or `passphrase`:
17
17
 
18
18
  ``` ruby
19
19
  k = SSHKey.generate
20
20
 
21
- k = SSHKey.generate(:type => "DSA", :bits => 1024, :comment => "foo@bar.com")
21
+ k = SSHKey.generate(:type => "DSA", :bits => 1024, :comment => "foo@bar.com", :passphrase => "foobar")
22
22
  ```
23
23
 
24
24
  Return an SSHKey object from an existing RSA or DSA private key (provided as a string)
@@ -40,6 +40,10 @@ k.key_object
40
40
  k.private_key
41
41
  # => "-----BEGIN RSA PRIVATE KEY-----\nMIIEowI..."
42
42
 
43
+ # Return the Private Key in encrypted form if a passphrase was provided
44
+ k.encrypted_private_key
45
+ # => "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED..."
46
+
43
47
  # Returns the Public Key as a string
44
48
  k.public_key
45
49
  # => "-----BEGIN RSA PUBLIC KEY-----\nMIIBCg..."
@@ -68,4 +72,4 @@ SSHKey.valid_ssh_public_key? "ssh-rsa AAAAB3NzaC1yc2EA...."
68
72
  Copyright
69
73
  ---------
70
74
 
71
- Copyright (c) 2011 James Miller
75
+ Copyright (c) 2012 James Miller
@@ -10,71 +10,110 @@ class SSHKey
10
10
  attr_reader :key_object, :comment, :type
11
11
  attr_accessor :passphrase
12
12
 
13
- # Generate a new keypair and return an SSHKey object
14
- #
15
- # The default behavior when providing no options will generate a 2048-bit RSA
16
- # keypair.
17
- #
18
- # ==== Parameters
19
- # * options<~Hash>:
20
- # * :type<~String> - "rsa" or "dsa", "rsa" by default
21
- # * :bits<~Integer> - Bit length
22
- # * :comment<~String> - Comment to use for the public key, defaults to ""
23
- # * :passphrase<~String> - Encrypt the key with this passphrase
24
- #
25
- def self.generate(options = {})
26
- type = options[:type] || "rsa"
27
- bits = options[:bits] || 2048
28
- cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC") if options[:passphrase]
29
-
30
- case type.downcase
31
- when "rsa" then SSHKey.new(OpenSSL::PKey::RSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
32
- when "dsa" then SSHKey.new(OpenSSL::PKey::DSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
33
- else
34
- raise "Unknown key type: #{type}"
13
+ class << self
14
+ # Generate a new keypair and return an SSHKey object
15
+ #
16
+ # The default behavior when providing no options will generate a 2048-bit RSA
17
+ # keypair.
18
+ #
19
+ # ==== Parameters
20
+ # * options<~Hash>:
21
+ # * :type<~String> - "rsa" or "dsa", "rsa" by default
22
+ # * :bits<~Integer> - Bit length
23
+ # * :comment<~String> - Comment to use for the public key, defaults to ""
24
+ # * :passphrase<~String> - Encrypt the key with this passphrase
25
+ #
26
+ def generate(options = {})
27
+ type = options[:type] || "rsa"
28
+
29
+ # JRuby modulus size must range from 512 to 1024
30
+ default_bits = type == "rsa" ? 2048 : 1024
31
+
32
+ bits = options[:bits] || default_bits
33
+ cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC") if options[:passphrase]
34
+
35
+ case type.downcase
36
+ when "rsa" then new(OpenSSL::PKey::RSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
37
+ when "dsa" then new(OpenSSL::PKey::DSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
38
+ else
39
+ raise "Unknown key type: #{type}"
40
+ end
35
41
  end
36
- end
37
42
 
38
- # Validate an existing SSH public key
39
- #
40
- # Returns true or false depending on the validity of the public key provided
41
- #
42
- # ==== Parameters
43
- # * ssh_public_key<~String> - "ssh-rsa AAAAB3NzaC1yc2EA...."
44
- #
45
- def self.valid_ssh_public_key?(ssh_public_key)
46
- ssh_type, encoded_key = ssh_public_key.split(" ")
47
- type = SSH_TYPES.invert[ssh_type]
48
- prefix = [0,0,0,7].pack("C*")
49
- decoded = Base64.decode64(encoded_key)
50
-
51
- # Base64 decoding is too permissive, so we should validate if encoding is correct
52
- return false unless Base64.encode64(decoded).gsub("\n", "") == encoded_key
53
- return false unless decoded.sub!(/^#{prefix}#{ssh_type}/, "")
54
-
55
- unpacked = decoded.unpack("C*")
56
- data = []
57
- index = 0
58
- until unpacked[index].nil?
59
- datum_size = from_byte_array unpacked[index..index+4-1], 4
60
- index = index + 4
61
- datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
62
- data << datum
63
- index = index + datum_size
43
+ # Validate an existing SSH public key
44
+ #
45
+ # Returns true or false depending on the validity of the public key provided
46
+ #
47
+ # ==== Parameters
48
+ # * ssh_public_key<~String> - "ssh-rsa AAAAB3NzaC1yc2EA...."
49
+ #
50
+ def valid_ssh_public_key?(ssh_public_key)
51
+ ssh_type, encoded_key = ssh_public_key.split(" ")
52
+ type = SSH_TYPES.invert[ssh_type]
53
+ prefix = [0,0,0,7].pack("C*")
54
+ decoded = Base64.decode64(encoded_key)
55
+
56
+ # Base64 decoding is too permissive, so we should validate if encoding is correct
57
+ return false unless Base64.encode64(decoded).gsub("\n", "") == encoded_key
58
+ return false unless decoded.sub!(/^#{prefix}#{ssh_type}/, "")
59
+
60
+ unpacked = decoded.unpack("C*")
61
+ data = []
62
+ index = 0
63
+ until unpacked[index].nil?
64
+ datum_size = from_byte_array unpacked[index..index+4-1], 4
65
+ index = index + 4
66
+ datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
67
+ data << datum
68
+ index = index + datum_size
69
+ end
70
+
71
+ SSH_CONVERSION[type].size == data.size
72
+ rescue
73
+ false
64
74
  end
65
75
 
66
- SSH_CONVERSION[type].size == data.size
67
- rescue
68
- false
69
- end
76
+ # Fingerprints
77
+ #
78
+ # Accepts either a public or private key
79
+ #
80
+ # MD5 fingerprint for the given SSH key
81
+ def md5_fingerprint(key)
82
+ if key.match(/PRIVATE/)
83
+ new(key).md5_fingerprint
84
+ else
85
+ Digest::MD5.hexdigest(decoded_key(key)).gsub(fingerprint_regex, '\1:\2')
86
+ end
87
+ end
88
+ alias_method :fingerprint, :md5_fingerprint
89
+
90
+ # SHA1 fingerprint for the given SSH key
91
+ def sha1_fingerprint(key)
92
+ if key.match(/PRIVATE/)
93
+ new(key).sha1_fingerprint
94
+ else
95
+ Digest::SHA1.hexdigest(decoded_key(key)).gsub(fingerprint_regex, '\1:\2')
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def from_byte_array(byte_array, expected_size = nil)
102
+ num = 0
103
+ raise "Byte array too short" if !expected_size.nil? && expected_size != byte_array.size
104
+ byte_array.reverse.each_with_index do |item, index|
105
+ num += item * 256**(index)
106
+ end
107
+ num
108
+ end
109
+
110
+ def decoded_key(key)
111
+ Base64.decode64(key.chomp.gsub(/ssh-[dr]s[as] /, ''))
112
+ end
70
113
 
71
- def self.from_byte_array(byte_array, expected_size = nil)
72
- num = 0
73
- raise "Byte array too short" if !expected_size.nil? && expected_size != byte_array.size
74
- byte_array.reverse.each_with_index do |item, index|
75
- num += item * 256**(index)
114
+ def fingerprint_regex
115
+ /(.{2})(?=.)/
76
116
  end
77
- num
78
117
  end
79
118
 
80
119
  # Create a new SSHKey object
@@ -1,3 +1,3 @@
1
1
  class SSHKey
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
3
3
  end
@@ -75,71 +75,6 @@ GzM8qwTcXd06uIZAJdTHIQ==
75
75
  -----END DSA PRIVATE KEY-----
76
76
  EOF
77
77
 
78
- ENCRYPTED_PRIVATE_KEY = <<-EOF
79
- -----BEGIN RSA PRIVATE KEY-----
80
- Proc-Type: 4,ENCRYPTED
81
- DEK-Info: AES-128-CBC,3514D8812B519059944A811726594515
82
-
83
- fSr1v51I65MZrSs7u12nype6RH6NS15xN5FDPaPKV++EBPxysEzicU5QHDt/aHa3
84
- t87nXkra1M400+zNgFcfi5Ga7w5SBmqEjdNgwhUV2/j1Yqqlr5c7l804OfIPxdE6
85
- ELoWH7pen72JnlZe6gXq495W96QTg3IzIWdiKEbKJlEwrNBligqT7GB2mup8nY1D
86
- o71R07dIrvfDy3xVgCoRjX4LKUilO6nRnwVCFRgVQTEVKclqt8NiSFGMjzv3iekR
87
- f1fJ8Wm6CiST8zdetIXgMnHEK1KELhNeMhI/42Tn/gHPDsckBiKLtM+85OOT92wh
88
- L9o/KUySdcsb/ld0yT/kAc99/wqNitHAqUEcLshIWDVhqoT1XK46hEuRN782AN2U
89
- shQKirF8QFopYF+u9K2Q0mr1EsYaBWOFFBR7EiwFvEYOx+ad6qGQGPcxWhbf6eCU
90
- D///9g1g5q8nWb80UH9Hw1aMhIA+VTlIasM6XJKmGr1LapxlrYsqRovPwkgOQg01
91
- jhSV1fy10bbaFBwd9qTdTTVqa368/e3/TxF2VKhDaqoy5lqvRqKzGJxi3ubzDuz9
92
- m3qRTCgy1v3XI5DgcjWt5xC5gZLHjKf79fQKRJjuEnWALahpDVWQ6PRCuqPfyph5
93
- /vVqGHqvA53HJ9pmXz4J9qtQQ2gkYRj1m2tlRJjtGRMqnAj7bpcDKIrdLudOiWB0
94
- FXwmsXljzPaf/SPUa+tGg7jbh+Jq+72vdpo1ijJtLXhWQAJasIbvSXOVHbZ6YhJj
95
- vES98gJPzevqemS//C1DMrr0ci6pM9ciT2szkrg71zRacnfqrjeZUI7qHKAsRbD5
96
- 258Jj6BeFPeQSrUg8sqQdoPxVTNnVr2bOB5SNfh7gqLanPksi6Kr7XNIzsYP5Wzf
97
- ADAElPdcRRwYc2kLVqugZTMLSn1r8rQjEyQ8/TT2QefI4ma8mCrBKgqYX+SDbhMJ
98
- +KUrah0jCgj86z6fSNkNHaKuzvGCovZsJHXt2SoIWVYWVUz91IHPKXXycIqvf3Yj
99
- 9HFpJRAPh30MYBgiImCJjmk8tqKGn0Tc80vOsrKMlVuMIIu2eNrddrnHUzSbjIHr
100
- tTtSDvsJ/Bn/6+Ox77U/FKg6s6/6PxOA1a+ffKkBXB/g4jS5CfGZl1owb3kX91C/
101
- a+bcNWp07DsaTaZd/0UEL2gIvaEuCULgyIvmnBPCOY6Pc5GGegWEJne/sk7j9W4I
102
- 59YtVfcSXiovYR/QEywytfN/tfPxKfUoqNMIxLkukjFYz4Zzk5kXEeI+1lcry398
103
- UQSaOboSDKY6boX4rWgiiqyn5LN+47eAIZPO+zsWXky16F04JpT7V7XqZPXQn7vI
104
- pMAoPCkT4qE9Gp2CcSj2l2CoZ3ZA5lOs6Wvxuz0q1zd0uSe8O81/3rnw28DthDQO
105
- SuzrY0HinPEFomwMGbfhosB5kOmBXEk7XbSWWHhK0QG63CYqp5caUst2Mie21b0Y
106
- FgFTrS1VqUiqDjCmt8F8UCPQS89aFm096wqtmwDO+VWKanuHUUShtTPlYyLe1RTm
107
- wqh1BBa05ydM0Vf1NagFB4JNT1qSIL5x4XtkOFwqcdXWYvwYfT8PkZjX/kz+W7jb
108
- -----END RSA PRIVATE KEY-----
109
- EOF
110
-
111
- DECRYPTED_PRIVATE_KEY = <<-EOF
112
- -----BEGIN RSA PRIVATE KEY-----
113
- MIIEpAIBAAKCAQEA33H9u4rG0SVMzK8PFyIi30kVHvogmpKVOQL2g2tozi2GipkA
114
- imzoCW9jIx1jo6zo0kMKCbMdJCNUc93tQxkJAAWA07WYwE9z+J6MC/3urb4Q0UAZ
115
- orlNyN3pPP8ATFIQomd0wW/EHwbmknlJOIZY4MNUQpNJunnBAAzZyLef6+sbLzQZ
116
- wc0/vgtmatoCxh4mZWFuFMopkMqScYDKxL30xXXPRGfJvAVWZDnY3ErJSe7uyefI
117
- Zo/lp4tsH5XGMcFm+nLs++nJjYZ6Ud/ie1g+ZCJv5Qit1m7zCVjiJ4RVMC/4yTb7
118
- CO8n4PhX8gR9d1DRPVvlKa1sZfQeULEIXMniKQIDAQABAoIBAQDEXS74s5rJjhgS
119
- AP4n/E3dICK5mGMytAMDmUD+eVQfbQ7BmnhJLjA0qnjbESbRXlE1Bsk5gPjpG0tK
120
- kAvEXan1JOD0LLDSwIBQSzUUDNLGSTQKUGS3BlX/YlVoz0h5ydzofDa1D/2wrqXO
121
- r1vTmu1ciQvxffLbN8iOvLxfkk+uSMhqnhf/q3WVinu+VALPg8e/v3p4VbnSfP4D
122
- eClBiMKEKRFdsa9xBxShijcX1HxjIvp3zDgb127fo2iFw09PIHUZCUo6M77iGrQY
123
- mscoA+5q1qSyD6Btw0EkKK55ytNMC2T+KfGYV0ySwhadmM+5+G64etvNGCn/j7CU
124
- rhuRhMlpAoGBAPiJlcWaNVw3ttlea+jllxnaCEOmG29NGWxw080XRvjSIrltPAiE
125
- 8e4FynAMx49aXKsaB8Df2WspdKBxHJgv1U0sapADwxlMO8erj2eDSRqy6bwnI4CT
126
- T+vvo2vdmkvkV0D9RskXCi5tgTO5FYnf7CjON6JLkg83V3vzyjsKlvDzAoGBAOYn
127
- iC50OdZ84U58wQUsvwXFuyzMQX9r+h0jL2tIDv/yYlMWg9tNt0HkGUOo7H1ZVhdL
128
- 9Z1B0Ztl2qoJipcQvhzfwdo4XwuLk7D0bOAfZo9YMbU5Jqy+rqE5yv/P4wa7ba4S
129
- uUQYvSuv54CtiOZDFyK8dU7y9mm+no3Fvrd9RwdzAoGANzlLACctqBnxFQd37r3k
130
- /yeFIpLsEaUN+xxu02lSqcL3WEA/UJ1JrFu5CYCtbtrjMFmOU3rpsnf5pBS+B8rJ
131
- GGbAHtPXK+3Wcp1aNePkAHy0lswThWQ2I/SRWUxaFnbcNGKSsefeqUZHqRh9Aq+w
132
- p7h6gCNOhvcDB1W6H7hQpaUCgYEAyBRDygaWJUVI5N+FOUduBMmhb09d/TTUKTJm
133
- TcBF8fE30v12wVZtYqW15ODcPhhExFnverc2Tf6cukczKSKP8y/+KQPqdHHxgdrr
134
- L2d81E6aX+4AFhpqW5SPShXiSf70WWjDkFRlV65C9dVmdq6KVVM6M9j5qHHjCmKG
135
- 6qLI9csCgYBuhFwwI9DiYvJPR1LJZnJtE0qZiTwpmCjU2LoBRsywvuBeyXtwpmIM
136
- 5IgfgXXLK5qK/+cp9047T5rzT6ndu5fNZINPzynA8tNhTtHXK8l/GT/iq8Rd6AcM
137
- WJmIe8EnUDhHqg7Z2h5tGpX1QPMSA4G8RGPPyrcd3v0G/PZ6pFALlQ==
138
- -----END RSA PRIVATE KEY-----
139
- EOF
140
-
141
- DECRYPTED_KEY_FINGERPRINT = "2e:ba:06:b1:c7:13:37:24:6f:2d:3a:ba:45:e2:b4:78"
142
-
143
78
  SSH_PUBLIC_KEY1 = 'AAAAB3NzaC1yc2EAAAABIwAAAQEArfTA/lKVR84IMc9ZzXOCHr8DVtR8hzWuEVHF6KElavRHlk14g0SZu3m908Ejm/XF3EfNHjX9wN+62IMA0QBxkBMFCuLF+U/oeUs0NoDdAEKxjj4n6lq6Ss8aLct+anMy7D1jwvOLbcwV54w1d5JDdlZVdZ6AvHm9otwJq6rNpDgdmXY4HgC2nM9csFpuy0cDpL6fdJx9lcNL2RnkRC4+RMsIB+PxDw0j3vDi04dYLBXMGYjyeGH+mIFpL3PTPXGXwL2XDYXZ2H4SQX6bOoKmazTXq6QXuEB665njh1GxXldoIMcSshoJL0hrk3WrTOG22N2CQA+IfHgrXJ+A+QUzKQ=='
144
79
  SSH_PUBLIC_KEY2 = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAxl6TpN7uFiY/JZ8qDnD7UrxDP+ABeh2PVg8Du1LEgXNk0+YWCeP5S6oHklqaWeDlbmAs1oHsBwCMAVpMa5tgONOLvz4JgwgkiqQEbKR8ofWJ+LADUElvqRVGmGiNEMLI6GJWeneL4sjmbb8d6U+M53c6iWG0si9XE5m7teBQSsCl0Tk3qMIkQGw5zpJeCXjZ8KpJhIJRYgexFkGgPlYRV+UYIhxpUW90t0Ra5i6JOFYwq98k5S/6SJIZQ/A9F4JNzwLw3eVxZj0yVHWxkGz1+TyELNY1kOyMxnZaqSfGzSQJTrnIXpdweVHuYh1LtOgedRQhCyiELeSMGwio1vRPKw=='
145
80
  SSH_PUBLIC_KEY3 = 'AAAAB3NzaC1kc3MAAACBALyVy5dwVwgL3CxXzsvo8DBh58qArQLBNIPW/f9pptmy7jD5QXzOw+12w0/z4lZ86ncoVutRMf44OABcX9ovhRl+luxB7jjpkVXy/p2ZaqPbeyTQUtdTmXa2y4n053Jd61VeMG+iLP7+viT+Ib96y9aVUYQfCrl5heBDUZ9cAFjdAAAAFQDFXnO7JJpFKwkeoor4GWGHtz0D2QAAAIEAqel0RUBO0MY5b3DZ69J/mRzUifN1O6twk4er2ph0JpryuUwZohLpcVZwqoGWmPQy/ZHmV1b3RtT9GWUa+HUqKdMhFVOx/iq1khVfLi83whjMMvXj3ecqd0yzGxGHnSsjVKefa2ywCLHrh4nlUVIaXI5gQpgMyVbMcromDe1WZzoAAACBAIwTRPAEcroqOzaebiVspFcmsXxDQ4wXQZQdho1ExW6FKS8s7/6pItmZYXTvJDwLXgq2/iK1fRRcKk2PJEaSuJR7WeNGsJKfWmQ2UbOhqA3wWLDazIZtcMKjFzD0hM4E8qgjHjMvKDE6WgT6SFP+tqx3nnh7pJWwsbGjSMQexpyR'
@@ -156,7 +91,6 @@ EOF
156
91
  @key1 = SSHKey.new(SSH_PRIVATE_KEY1, :comment => "me@example.com")
157
92
  @key2 = SSHKey.new(SSH_PRIVATE_KEY2, :comment => "me@example.com")
158
93
  @key3 = SSHKey.new(SSH_PRIVATE_KEY3, :comment => "me@example.com")
159
- @key_encrypted = SSHKey.new(ENCRYPTED_PRIVATE_KEY, :passphrase => "password")
160
94
  @key_without_comment = SSHKey.new(SSH_PRIVATE_KEY1)
161
95
  end
162
96
 
@@ -191,20 +125,6 @@ EOF
191
125
  assert_equal SSH_PRIVATE_KEY3, @key3.dsa_private_key
192
126
  end
193
127
 
194
- def test_encrypted_private_key_can_be_decrypted
195
- assert_equal DECRYPTED_PRIVATE_KEY, @key_encrypted.private_key
196
- end
197
-
198
- def test_encrypted_private_key_matches_when_reencrypted
199
- key = SSHKey.new(@key_encrypted.encrypted_private_key, :passphrase => "password")
200
- assert_equal DECRYPTED_PRIVATE_KEY, key.private_key
201
- assert_equal DECRYPTED_KEY_FINGERPRINT, key.md5_fingerprint
202
- end
203
-
204
- def test_unencrypted_private_key_returns_private_key_when_asked_for_encrypted
205
- assert_equal SSH_PRIVATE_KEY1, @key1.encrypted_private_key
206
- end
207
-
208
128
  def test_ssh_public_key_decoded1
209
129
  assert_equal Base64.decode64(SSH_PUBLIC_KEY1), @key1.send(:ssh_public_key_conversion)
210
130
  end
@@ -282,6 +202,20 @@ EOF
282
202
  assert_equal KEY1_SHA1_FINGERPRINT, @key1.sha1_fingerprint
283
203
  assert_equal KEY2_SHA1_FINGERPRINT, @key2.sha1_fingerprint
284
204
  assert_equal KEY3_SHA1_FINGERPRINT, @key3.sha1_fingerprint
205
+
206
+ assert_equal KEY1_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY1)
207
+ assert_equal KEY1_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY1)
208
+ assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY2)
209
+ assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY2)
210
+ assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY3)
211
+ assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY3)
212
+
213
+ assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY1)
214
+ assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY1)
215
+ assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY2)
216
+ assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY2)
217
+ assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY3)
218
+ assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY3)
285
219
  end
286
220
 
287
221
  def test_to_byte_array
@@ -293,3 +227,85 @@ EOF
293
227
  assert_equal [[0], [1], [0, 255], [1, 0], [255], [128], [255, 0]], ba3
294
228
  end
295
229
  end
230
+
231
+ class SSHKeyEncryptedTest < Test::Unit::TestCase
232
+
233
+ ENCRYPTED_PRIVATE_KEY = <<-EOF
234
+ -----BEGIN RSA PRIVATE KEY-----
235
+ Proc-Type: 4,ENCRYPTED
236
+ DEK-Info: AES-128-CBC,3514D8812B519059944A811726594515
237
+
238
+ fSr1v51I65MZrSs7u12nype6RH6NS15xN5FDPaPKV++EBPxysEzicU5QHDt/aHa3
239
+ t87nXkra1M400+zNgFcfi5Ga7w5SBmqEjdNgwhUV2/j1Yqqlr5c7l804OfIPxdE6
240
+ ELoWH7pen72JnlZe6gXq495W96QTg3IzIWdiKEbKJlEwrNBligqT7GB2mup8nY1D
241
+ o71R07dIrvfDy3xVgCoRjX4LKUilO6nRnwVCFRgVQTEVKclqt8NiSFGMjzv3iekR
242
+ f1fJ8Wm6CiST8zdetIXgMnHEK1KELhNeMhI/42Tn/gHPDsckBiKLtM+85OOT92wh
243
+ L9o/KUySdcsb/ld0yT/kAc99/wqNitHAqUEcLshIWDVhqoT1XK46hEuRN782AN2U
244
+ shQKirF8QFopYF+u9K2Q0mr1EsYaBWOFFBR7EiwFvEYOx+ad6qGQGPcxWhbf6eCU
245
+ D///9g1g5q8nWb80UH9Hw1aMhIA+VTlIasM6XJKmGr1LapxlrYsqRovPwkgOQg01
246
+ jhSV1fy10bbaFBwd9qTdTTVqa368/e3/TxF2VKhDaqoy5lqvRqKzGJxi3ubzDuz9
247
+ m3qRTCgy1v3XI5DgcjWt5xC5gZLHjKf79fQKRJjuEnWALahpDVWQ6PRCuqPfyph5
248
+ /vVqGHqvA53HJ9pmXz4J9qtQQ2gkYRj1m2tlRJjtGRMqnAj7bpcDKIrdLudOiWB0
249
+ FXwmsXljzPaf/SPUa+tGg7jbh+Jq+72vdpo1ijJtLXhWQAJasIbvSXOVHbZ6YhJj
250
+ vES98gJPzevqemS//C1DMrr0ci6pM9ciT2szkrg71zRacnfqrjeZUI7qHKAsRbD5
251
+ 258Jj6BeFPeQSrUg8sqQdoPxVTNnVr2bOB5SNfh7gqLanPksi6Kr7XNIzsYP5Wzf
252
+ ADAElPdcRRwYc2kLVqugZTMLSn1r8rQjEyQ8/TT2QefI4ma8mCrBKgqYX+SDbhMJ
253
+ +KUrah0jCgj86z6fSNkNHaKuzvGCovZsJHXt2SoIWVYWVUz91IHPKXXycIqvf3Yj
254
+ 9HFpJRAPh30MYBgiImCJjmk8tqKGn0Tc80vOsrKMlVuMIIu2eNrddrnHUzSbjIHr
255
+ tTtSDvsJ/Bn/6+Ox77U/FKg6s6/6PxOA1a+ffKkBXB/g4jS5CfGZl1owb3kX91C/
256
+ a+bcNWp07DsaTaZd/0UEL2gIvaEuCULgyIvmnBPCOY6Pc5GGegWEJne/sk7j9W4I
257
+ 59YtVfcSXiovYR/QEywytfN/tfPxKfUoqNMIxLkukjFYz4Zzk5kXEeI+1lcry398
258
+ UQSaOboSDKY6boX4rWgiiqyn5LN+47eAIZPO+zsWXky16F04JpT7V7XqZPXQn7vI
259
+ pMAoPCkT4qE9Gp2CcSj2l2CoZ3ZA5lOs6Wvxuz0q1zd0uSe8O81/3rnw28DthDQO
260
+ SuzrY0HinPEFomwMGbfhosB5kOmBXEk7XbSWWHhK0QG63CYqp5caUst2Mie21b0Y
261
+ FgFTrS1VqUiqDjCmt8F8UCPQS89aFm096wqtmwDO+VWKanuHUUShtTPlYyLe1RTm
262
+ wqh1BBa05ydM0Vf1NagFB4JNT1qSIL5x4XtkOFwqcdXWYvwYfT8PkZjX/kz+W7jb
263
+ -----END RSA PRIVATE KEY-----
264
+ EOF
265
+
266
+ DECRYPTED_PRIVATE_KEY = <<-EOF
267
+ -----BEGIN RSA PRIVATE KEY-----
268
+ MIIEpAIBAAKCAQEA33H9u4rG0SVMzK8PFyIi30kVHvogmpKVOQL2g2tozi2GipkA
269
+ imzoCW9jIx1jo6zo0kMKCbMdJCNUc93tQxkJAAWA07WYwE9z+J6MC/3urb4Q0UAZ
270
+ orlNyN3pPP8ATFIQomd0wW/EHwbmknlJOIZY4MNUQpNJunnBAAzZyLef6+sbLzQZ
271
+ wc0/vgtmatoCxh4mZWFuFMopkMqScYDKxL30xXXPRGfJvAVWZDnY3ErJSe7uyefI
272
+ Zo/lp4tsH5XGMcFm+nLs++nJjYZ6Ud/ie1g+ZCJv5Qit1m7zCVjiJ4RVMC/4yTb7
273
+ CO8n4PhX8gR9d1DRPVvlKa1sZfQeULEIXMniKQIDAQABAoIBAQDEXS74s5rJjhgS
274
+ AP4n/E3dICK5mGMytAMDmUD+eVQfbQ7BmnhJLjA0qnjbESbRXlE1Bsk5gPjpG0tK
275
+ kAvEXan1JOD0LLDSwIBQSzUUDNLGSTQKUGS3BlX/YlVoz0h5ydzofDa1D/2wrqXO
276
+ r1vTmu1ciQvxffLbN8iOvLxfkk+uSMhqnhf/q3WVinu+VALPg8e/v3p4VbnSfP4D
277
+ eClBiMKEKRFdsa9xBxShijcX1HxjIvp3zDgb127fo2iFw09PIHUZCUo6M77iGrQY
278
+ mscoA+5q1qSyD6Btw0EkKK55ytNMC2T+KfGYV0ySwhadmM+5+G64etvNGCn/j7CU
279
+ rhuRhMlpAoGBAPiJlcWaNVw3ttlea+jllxnaCEOmG29NGWxw080XRvjSIrltPAiE
280
+ 8e4FynAMx49aXKsaB8Df2WspdKBxHJgv1U0sapADwxlMO8erj2eDSRqy6bwnI4CT
281
+ T+vvo2vdmkvkV0D9RskXCi5tgTO5FYnf7CjON6JLkg83V3vzyjsKlvDzAoGBAOYn
282
+ iC50OdZ84U58wQUsvwXFuyzMQX9r+h0jL2tIDv/yYlMWg9tNt0HkGUOo7H1ZVhdL
283
+ 9Z1B0Ztl2qoJipcQvhzfwdo4XwuLk7D0bOAfZo9YMbU5Jqy+rqE5yv/P4wa7ba4S
284
+ uUQYvSuv54CtiOZDFyK8dU7y9mm+no3Fvrd9RwdzAoGANzlLACctqBnxFQd37r3k
285
+ /yeFIpLsEaUN+xxu02lSqcL3WEA/UJ1JrFu5CYCtbtrjMFmOU3rpsnf5pBS+B8rJ
286
+ GGbAHtPXK+3Wcp1aNePkAHy0lswThWQ2I/SRWUxaFnbcNGKSsefeqUZHqRh9Aq+w
287
+ p7h6gCNOhvcDB1W6H7hQpaUCgYEAyBRDygaWJUVI5N+FOUduBMmhb09d/TTUKTJm
288
+ TcBF8fE30v12wVZtYqW15ODcPhhExFnverc2Tf6cukczKSKP8y/+KQPqdHHxgdrr
289
+ L2d81E6aX+4AFhpqW5SPShXiSf70WWjDkFRlV65C9dVmdq6KVVM6M9j5qHHjCmKG
290
+ 6qLI9csCgYBuhFwwI9DiYvJPR1LJZnJtE0qZiTwpmCjU2LoBRsywvuBeyXtwpmIM
291
+ 5IgfgXXLK5qK/+cp9047T5rzT6ndu5fNZINPzynA8tNhTtHXK8l/GT/iq8Rd6AcM
292
+ WJmIe8EnUDhHqg7Z2h5tGpX1QPMSA4G8RGPPyrcd3v0G/PZ6pFALlQ==
293
+ -----END RSA PRIVATE KEY-----
294
+ EOF
295
+
296
+ DECRYPTED_KEY_FINGERPRINT = "2e:ba:06:b1:c7:13:37:24:6f:2d:3a:ba:45:e2:b4:78"
297
+
298
+ def setup
299
+ @key_encrypted = SSHKey.new(ENCRYPTED_PRIVATE_KEY, :passphrase => "password")
300
+ end
301
+
302
+ def test_encrypted_private_key_can_be_decrypted
303
+ assert_equal DECRYPTED_PRIVATE_KEY, @key_encrypted.private_key
304
+ end
305
+
306
+ def test_encrypted_private_key_matches_when_reencrypted
307
+ key = SSHKey.new(@key_encrypted.encrypted_private_key, :passphrase => "password")
308
+ assert_equal DECRYPTED_PRIVATE_KEY, key.private_key
309
+ assert_equal DECRYPTED_KEY_FINGERPRINT, key.md5_fingerprint
310
+ end
311
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-10 00:00:00.000000000 Z
12
+ date: 2012-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70360303706000 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70360303706000
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  description: Generate private/public SSH keypairs using pure Ruby
26
31
  email:
27
32
  - bensie@gmail.com
@@ -59,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
64
  version: '0'
60
65
  requirements: []
61
66
  rubyforge_project: sshkey
62
- rubygems_version: 1.8.10
67
+ rubygems_version: 1.8.23
63
68
  signing_key:
64
69
  specification_version: 3
65
70
  summary: SSH private/public key generator in Ruby