sshkey 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![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)
|
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
|