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.
- data/.travis.yml +4 -2
- data/Gemfile +3 -1
- data/README.md +9 -5
- data/lib/sshkey.rb +98 -59
- data/lib/sshkey/version.rb +1 -1
- data/test/sshkey_test.rb +96 -80
- metadata +10 -5
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
|
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,
|
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
|
[](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)
|
75
|
+
Copyright (c) 2012 James Miller
|
data/lib/sshkey.rb
CHANGED
@@ -10,71 +10,110 @@ class SSHKey
|
|
10
10
|
attr_reader :key_object, :comment, :type
|
11
11
|
attr_accessor :passphrase
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
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
|
data/lib/sshkey/version.rb
CHANGED
data/test/sshkey_test.rb
CHANGED
@@ -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.
|
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:
|
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:
|
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:
|
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.
|
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
|