sshkey 1.3.0 → 1.3.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.
@@ -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