sshkey 1.6.0 → 1.6.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dcab21406c740089ec26317a5499a2b757f03e7c
4
+ data.tar.gz: 212a9a19f541aea1aeaf577cb2e938f1eae9c4fd
5
+ SHA512:
6
+ metadata.gz: ba8bf9fcef2981609256d9765e855e49771992caa20d1b87ff52a20d627a8d2571318486687b2cf51c52d6f8a510281ad351069e94cb092e44a520f069af5ab6
7
+ data.tar.gz: f1f47cb1a2861aa2a8a741d8b511529c62701e943658c1dead0f6621ad639158874b4c13fc6a00f9bc6375e00ea46aab32612d5337c8e55002503f0aaac6dab9
@@ -9,8 +9,33 @@ rvm:
9
9
  - jruby-19mode
10
10
  - jruby-20mode
11
11
  - jruby-head
12
- - rbx-18mode
13
- - rbx-19mode
12
+ - rbx-2.1.1
13
+
14
14
  matrix:
15
15
  allow_failures:
16
16
  - rvm: ruby-head
17
+ include:
18
+ - rvm: jruby-18mode
19
+ jdk: openjdk6
20
+ - rvm: jruby-18mode
21
+ jdk: openjdk7
22
+ - rvm: jruby-18mode
23
+ jdk: oraclejdk7
24
+ - rvm: jruby-19mode
25
+ jdk: openjdk6
26
+ - rvm: jruby-19mode
27
+ jdk: openjdk7
28
+ - rvm: jruby-19mode
29
+ jdk: oraclejdk7
30
+ - rvm: jruby-20mode
31
+ jdk: openjdk6
32
+ - rvm: jruby-20mode
33
+ jdk: openjdk7
34
+ - rvm: jruby-20mode
35
+ jdk: oraclejdk7
36
+ - rvm: jruby-head
37
+ jdk: openjdk6
38
+ - rvm: jruby-head
39
+ jdk: openjdk7
40
+ - rvm: jruby-head
41
+ jdk: oraclejdk7
data/Gemfile CHANGED
@@ -1,5 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "jruby-openssl", "~> 0.8.2", :platform => :jruby
3
+ gem "jruby-openssl", ">= 0.8.2", :platforms => :jruby
4
+ gem "rubysl", "~> 2.0.14", :platforms => :rbx
4
5
 
5
6
  gemspec
data/README.md CHANGED
@@ -4,7 +4,7 @@ Generate private and public SSH keys (RSA and DSA supported) using pure Ruby.
4
4
 
5
5
  gem install sshkey
6
6
 
7
- Tested on the following Rubies: MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0, REE, JRuby (1.7.2 or later), Rubinius. Ruby must be compiled with OpenSSL support.
7
+ Tested on the following Rubies: MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0, REE, JRuby (1.7.2 and newer), Rubinius (2.1.1 and newer). Ruby must be compiled with OpenSSL support.
8
8
 
9
9
  [![Build Status](https://secure.travis-ci.org/bensie/sshkey.png)](http://travis-ci.org/bensie/sshkey)
10
10
 
@@ -152,15 +152,38 @@ k.key_object
152
152
  # => -----BEGIN RSA PRIVATE KEY-----\nMIIEowI...
153
153
  ```
154
154
 
155
- ### Validate existing SSH public keys
155
+ ### Existing SSH public keys
156
156
 
157
- Determine if a given SSH public key is valid. Very useful to test user input of public keys to make sure they accurately copy/pasted the key. Just pass the SSH public key as a string.
157
+ #### Validation
158
+
159
+ Determine if a given SSH public key is valid. Very useful to test user input of public keys to make sure they accurately copy/pasted the key. Just pass the SSH public key as a string. Returns false if the key is invalid.
158
160
 
159
161
  ```ruby
160
162
  SSHKey.valid_ssh_public_key? "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9HuXvYJPtQE/o/7TYi63yAopsrJ6TP+lDGdyQ+nVVp+5ojAIy9h8/h99UlNxjkiFT2YhI3Fl/pgNDRO4PVo6tlgb3CwiAZjSdeE5RnF79Dkj5XsM4j+FLMoXtbRw0K9ok9RKjz6ygIs1JDmaOdXexFnq4nAYU3fSLUa6WoccqTHe8bFuJoAv1gbnx09Js8YcVMD96mpTJ3V/MK5YfIv10dbtrDhGug3IS1V2J+0BB9orbQja554N+4S0I9rFBgVCpvPmQqddDHd/AdGkLv/zjEfGytjnvp68bEfDinkQkPfuxw01yd5MbcvLv39VVICWtKbqW263HT5LvSxwKorR7"
161
163
  # => true
162
164
  ```
163
165
 
166
+ #### Bit length
167
+
168
+ Determine the strenth of the key in bits as an integer. Returns `SSHKey::PublicKeyError` if bits cannot be determined.
169
+
170
+ ```ruby
171
+ SSHKey.ssh_public_key_bits "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9HuXvYJPtQE/o/7TYi63yAopsrJ6TP+lDGdyQ+nVVp+5ojAIy9h8/h99UlNxjkiFT2YhI3Fl/pgNDRO4PVo6tlgb3CwiAZjSdeE5RnF79Dkj5XsM4j+FLMoXtbRw0K9ok9RKjz6ygIs1JDmaOdXexFnq4nAYU3fSLUa6WoccqTHe8bFuJoAv1gbnx09Js8YcVMD96mpTJ3V/MK5YfIv10dbtrDhGug3IS1V2J+0BB9orbQja554N+4S0I9rFBgVCpvPmQqddDHd/AdGkLv/zjEfGytjnvp68bEfDinkQkPfuxw01yd5MbcvLv39VVICWtKbqW263HT5LvSxwKorR7"
172
+ # => 2048
173
+ ```
174
+
175
+ #### Fingerprints
176
+
177
+ Fetch either an MD5 (OpenSSH default) or SHA1 fingerprint of the SSH
178
+ public key. Returns `SSHKey::PublicKeyError` if a fingerprint cannot be determined.
179
+
180
+ ```ruby
181
+ SSHKey.fingerprint "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9HuXvYJPtQE/o/7TYi63yAopsrJ6TP+lDGdyQ+nVVp+5ojAIy9h8/h99UlNxjkiFT2YhI3Fl/pgNDRO4PVo6tlgb3CwiAZjSdeE5RnF79Dkj5XsM4j+FLMoXtbRw0K9ok9RKjz6ygIs1JDmaOdXexFnq4nAYU3fSLUa6WoccqTHe8bFuJoAv1gbnx09Js8YcVMD96mpTJ3V/MK5YfIv10dbtrDhGug3IS1V2J+0BB9orbQja554N+4S0I9rFBgVCpvPmQqddDHd/AdGkLv/zjEfGytjnvp68bEfDinkQkPfuxw01yd5MbcvLv39VVICWtKbqW263HT5LvSxwKorR7"
182
+ # => "04:1b:d4:18:df:87:60:94:8c:83:8a:7b:5a:35:59:3d"
183
+ SSHKey.sha1_fingerprint "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9HuXvYJPtQE/o/7TYi63yAopsrJ6TP+lDGdyQ+nVVp+5ojAIy9h8/h99UlNxjkiFT2YhI3Fl/pgNDRO4PVo6tlgb3CwiAZjSdeE5RnF79Dkj5XsM4j+FLMoXtbRw0K9ok9RKjz6ygIs1JDmaOdXexFnq4nAYU3fSLUa6WoccqTHe8bFuJoAv1gbnx09Js8YcVMD96mpTJ3V/MK5YfIv10dbtrDhGug3IS1V2J+0BB9orbQja554N+4S0I9rFBgVCpvPmQqddDHd/AdGkLv/zjEfGytjnvp68bEfDinkQkPfuxw01yd5MbcvLv39VVICWtKbqW263HT5LvSxwKorR7"
184
+ # => "e5:c2:43:9e:e4:0c:0c:47:82:7a:3b:e9:61:13:bd:9c:43:eb:4c:b7"
185
+ ```
186
+
164
187
  ## Copyright
165
188
 
166
189
  Copyright (c) 2011-2013 James Miller
@@ -62,7 +62,7 @@ class SSHKey
62
62
  # * ssh_public_key<~String> - "ssh-rsa AAAAB3NzaC1yc2EA...."
63
63
  #
64
64
  def ssh_public_key_bits(ssh_public_key)
65
- unpacked_byte_array( *parse_ssh_public_key(ssh_public_key) ).last.size * 8
65
+ unpacked_byte_array( *parse_ssh_public_key(ssh_public_key) ).last.num_bytes * 8
66
66
  end
67
67
 
68
68
  # Fingerprints
@@ -91,38 +91,29 @@ class SSHKey
91
91
  private
92
92
 
93
93
  def unpacked_byte_array(ssh_type, encoded_key)
94
- prefix = [0,0,0,7].pack("C*")
94
+ prefix = [7].pack("N") + ssh_type
95
95
  decoded = Base64.decode64(encoded_key)
96
96
 
97
97
  # Base64 decoding is too permissive, so we should validate if encoding is correct
98
- if Base64.encode64(decoded).gsub("\n", "") != encoded_key || decoded.sub!(/^#{prefix}#{ssh_type}/, "").nil?
98
+ unless Base64.encode64(decoded).gsub("\n", "") == encoded_key && decoded.slice!(0, prefix.length) == prefix
99
99
  raise PublicKeyError, "validation error"
100
100
  end
101
101
 
102
- unpacked = decoded.unpack("C*")
103
102
  data = []
104
- index = 0
105
- until unpacked[index].nil?
106
- datum_size = from_byte_array unpacked[index..index+4-1], 4
107
- index = index + 4
108
- datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
109
- data << datum
110
- index = index + datum_size
103
+ until decoded.empty?
104
+ front = decoded.slice!(0,4)
105
+ size = front.unpack("N").first
106
+ segment = decoded.slice!(0, size)
107
+ unless front.length == 4 && segment.length == size
108
+ raise PublicKeyError, "byte array too short"
109
+ end
110
+ data << OpenSSL::BN.new(segment, 2)
111
111
  end
112
112
  return data
113
113
  end
114
114
 
115
- def from_byte_array(byte_array, expected_size = nil)
116
- raise PublicKeyError, "byte array too short" if !expected_size.nil? && expected_size != byte_array.size
117
- num = 0
118
- byte_array.reverse.each_with_index do |item, index|
119
- num += item * 256**(index)
120
- end
121
- num
122
- end
123
-
124
115
  def decoded_key(key)
125
- Base64.decode64(key.gsub(/^(ssh-[dr]s[as]\s+)|(\s+.+\@.+)|\n/, ''))
116
+ Base64.decode64(parse_ssh_public_key(key).last)
126
117
  end
127
118
 
128
119
  def fingerprint_regex
@@ -286,34 +277,27 @@ class SSHKey
286
277
  # For instance, the "ssh-rsa" string is encoded as the following byte array
287
278
  # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a']
288
279
  def ssh_public_key_conversion
289
- out = [0,0,0,7].pack("C*")
290
- out += SSH_TYPES[type]
291
-
292
- SSH_CONVERSION[type].each do |method|
293
- byte_array = to_byte_array(key_object.public_key.send(method).to_i)
294
- out += encode_unsigned_int_32(byte_array.length).pack("c*")
295
- out += byte_array.pack("C*")
280
+ typestr = SSH_TYPES[type]
281
+ methods = SSH_CONVERSION[type]
282
+ pubkey = key_object.public_key
283
+ methods.inject([7].pack("N") + typestr) do |pubkeystr, m|
284
+ # Given pubkey.class == OpenSSL::BN, pubkey.to_s(0) returns an MPI
285
+ # formatted string (length prefixed bytes). This is not supported by
286
+ # JRuby, so we still have to deal with length and data separately.
287
+ val = pubkey.send(m)
288
+
289
+ # Get byte-representation of absolute value of val
290
+ data = val.to_s(2)
291
+
292
+ first_byte = data[0,1].unpack("c").first
293
+ if val < 0
294
+ # For negative values, highest bit must be set
295
+ data[0] = [0x80 & first_byte].pack("c")
296
+ elsif first_byte < 0
297
+ # For positive values where highest bit would be set, prefix with \0
298
+ data = "\0" + data
299
+ end
300
+ pubkeystr + [data.length].pack("N") + data
296
301
  end
297
-
298
- return out
299
302
  end
300
-
301
- def encode_unsigned_int_32(value)
302
- out = []
303
- out[0] = value >> 24 & 0xff
304
- out[1] = value >> 16 & 0xff
305
- out[2] = value >> 8 & 0xff
306
- out[3] = value & 0xff
307
- return out
308
- end
309
-
310
- def to_byte_array(num)
311
- result = []
312
- begin
313
- result << (num & 0xff)
314
- num >>= 8
315
- end until (num == 0 || num == -1) && (result.last[7] == num[7])
316
- result.reverse
317
- end
318
-
319
303
  end
@@ -1,3 +1,3 @@
1
1
  class SSHKey
2
- VERSION = "1.6.0"
2
+ VERSION = "1.6.1"
3
3
  end
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "https://github.com/bensie/sshkey"
12
12
  s.summary = %q{SSH private/public key generator in Ruby}
13
13
  s.description = %q{Generate private/public SSH keypairs using pure Ruby}
14
+ s.licenses = ["MIT"]
14
15
 
15
16
  s.rubyforge_project = "sshkey"
16
17
 
@@ -298,18 +298,18 @@ EOF
298
298
  assert_equal KEY3_SHA1_FINGERPRINT, @key3.sha1_fingerprint
299
299
 
300
300
  assert_equal KEY1_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY1)
301
- assert_equal KEY1_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY1)
301
+ assert_equal KEY1_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY1}")
302
302
  assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY2)
303
- assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY2)
303
+ assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY2} me@me.com")
304
304
  assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY3)
305
- assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PUBLIC_KEY3)
305
+ assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-dss #{SSH_PUBLIC_KEY3}")
306
306
 
307
307
  assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY1)
308
- assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY1)
308
+ assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY1}")
309
309
  assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY2)
310
- assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY2)
310
+ assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY2} me@me.com")
311
311
  assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY3)
312
- assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PUBLIC_KEY3)
312
+ assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-dss #{SSH_PUBLIC_KEY3}")
313
313
  end
314
314
 
315
315
  def test_bits
@@ -324,15 +324,6 @@ EOF
324
324
  assert_equal KEY2_RANDOMART, @key2.randomart
325
325
  assert_equal KEY3_RANDOMART, @key3.randomart
326
326
  end
327
-
328
- def test_to_byte_array
329
- ba1 = @key1.send(:to_byte_array, 35)
330
- ba2 = @key1.send(:to_byte_array, 65537)
331
- ba3 = [0, 1, 255, 256, -1, -128, -256].map{|i| @key1.send(:to_byte_array, i)}
332
- assert_equal [35], ba1
333
- assert_equal [1, 0, 1], ba2
334
- assert_equal [[0], [1], [0, 255], [1, 0], [255], [128], [255, 0]], ba3
335
- end
336
327
  end
337
328
 
338
329
  class SSHKeyEncryptedTest < Test::Unit::TestCase
metadata CHANGED
@@ -1,30 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
5
- prerelease:
4
+ version: 1.6.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - James Miller
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-11 00:00:00.000000000 Z
11
+ date: 2013-11-14 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  description: Generate private/public SSH keypairs using pure Ruby
@@ -46,28 +43,28 @@ files:
46
43
  - sshkey.gemspec
47
44
  - test/sshkey_test.rb
48
45
  homepage: https://github.com/bensie/sshkey
49
- licenses: []
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
50
49
  post_install_message:
51
50
  rdoc_options: []
52
51
  require_paths:
53
52
  - lib
54
53
  required_ruby_version: !ruby/object:Gem::Requirement
55
- none: false
56
54
  requirements:
57
- - - ! '>='
55
+ - - '>='
58
56
  - !ruby/object:Gem::Version
59
57
  version: '0'
60
58
  required_rubygems_version: !ruby/object:Gem::Requirement
61
- none: false
62
59
  requirements:
63
- - - ! '>='
60
+ - - '>='
64
61
  - !ruby/object:Gem::Version
65
62
  version: '0'
66
63
  requirements: []
67
64
  rubyforge_project: sshkey
68
- rubygems_version: 1.8.23
65
+ rubygems_version: 2.0.3
69
66
  signing_key:
70
- specification_version: 3
67
+ specification_version: 4
71
68
  summary: SSH private/public key generator in Ruby
72
69
  test_files:
73
70
  - test/sshkey_test.rb