sshkey 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c6a9c5ef164d05f4575e492f588a6e6aee6506e
4
- data.tar.gz: bc65fc61b32246e9a5fa1de721188923abad2fc9
3
+ metadata.gz: e557b4605e1f00d77de9e7b939f79a5ba9601cdf
4
+ data.tar.gz: 6764a84f581a544e0adea8958731eb01bd35a550
5
5
  SHA512:
6
- metadata.gz: dfb36e68eaf79b51f30b4655acbf3da004b64faea378148e12bc8fe5831fe68d89eb636119cd2212d5adbad9bbb7fbb303b25f5e8464e169b508569f01050874
7
- data.tar.gz: 458c373b8e718990b7667931d260dc02af65a7d463842135c5a7a9fef35a8fe43451bae4e67d5ea742425a2c10b8ab2c76f136176e0d1dfeed873e168d827ee7
6
+ metadata.gz: dd96a9bacc99265e0f211b40a4c0d4a860ed4f6e5ffb7197277f5fdf11800776f6dbf687288b4c2b4bf3829e02273b2dcaa7b5c8fec662fda8b695b6f5861c5c
7
+ data.tar.gz: 8d68590c6f42a5d3868eaa0c39a8880c8c2666c5f63ac9d53df9cee0cba7f7827a3f3f3343166adecdca88e05de7599b0c7c163327ca12f72f3f04f2a0e0b965
@@ -1,14 +1,13 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 1.8.7
5
- - 1.9.2
6
4
  - 1.9.3
7
- - 2.0
8
- - 2.1
9
- - 2.2
5
+ - 2.0.0
6
+ - 2.1.9
7
+ - 2.2.6
8
+ - 2.3.3
9
+ - 2.4.0
10
10
  - ruby-head
11
- - ree
12
11
  - jruby
13
12
  - jruby-head
14
13
 
@@ -17,4 +16,5 @@ matrix:
17
16
  - rvm: ruby-head
18
17
  - rvm: jruby-head
19
18
 
20
- sudo: false
19
+ sudo: required
20
+ dist: trusty
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2014 James Miller
1
+ Copyright (c) 2011-2016 James Miller
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -6,7 +6,7 @@ Generate private and public SSH keys (RSA and DSA supported) using pure Ruby.
6
6
 
7
7
  ## Requirements
8
8
 
9
- Tested / supported on CRuby 1.8.7+ and JRuby.
9
+ Tested / supported on CRuby 1.9.3+ and JRuby.
10
10
 
11
11
  ## Installation
12
12
 
@@ -61,11 +61,11 @@ k.ssh_public_key
61
61
 
62
62
  #### Encryption
63
63
 
64
- If a passcode is set when a key is generated or by setting the `passcode` accessor, you can
64
+ If a passphrase is set when a key is generated or by setting the `passphrase` accessor, you can
65
65
  fetch the encrypted version of the private key.
66
66
 
67
67
  ```ruby
68
- k.passcode = "foo"
68
+ k.passphrase = "foo"
69
69
  # => "foo"
70
70
 
71
71
  k.encrypted_private_key
@@ -211,4 +211,4 @@ SSHKey.ssh_public_key_to_ssh2_public_key "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ
211
211
 
212
212
  ## Copyright
213
213
 
214
- Copyright (c) 2011-2015 James Miller
214
+ Copyright (c) 2011-2016 James Miller
@@ -7,7 +7,14 @@ require 'digest/sha1'
7
7
  require 'sshkey/exception'
8
8
 
9
9
  class SSHKey
10
- SSH_TYPES = {"rsa" => "ssh-rsa", "dsa" => "ssh-dss"}
10
+ SSH_TYPES = {
11
+ "ssh-rsa" => "rsa",
12
+ "ssh-dss" => "dsa",
13
+ "ssh-ed25519" => "ed25519",
14
+ "ecdsa-sha2-nistp256" => "ecdsa",
15
+ "ecdsa-sha2-nistp384" => "ecdsa",
16
+ "ecdsa-sha2-nistp521" => "ecdsa",
17
+ }
11
18
  SSH_CONVERSION = {"rsa" => ["e", "n"], "dsa" => ["p", "q", "g", "pub_key"]}
12
19
  SSH2_LINE_LENGTH = 70 # +1 (for line wrap '/' character) must be <= 72
13
20
 
@@ -50,7 +57,17 @@ class SSHKey
50
57
  #
51
58
  def valid_ssh_public_key?(ssh_public_key)
52
59
  ssh_type, encoded_key = parse_ssh_public_key(ssh_public_key)
53
- SSH_CONVERSION[SSH_TYPES.invert[ssh_type]].size == unpacked_byte_array(ssh_type, encoded_key).size
60
+ sections = unpacked_byte_array(ssh_type, encoded_key)
61
+ case ssh_type
62
+ when "ssh-rsa", "ssh-dss"
63
+ sections.size == SSH_CONVERSION[SSH_TYPES[ssh_type]].size
64
+ when "ssh-ed25519"
65
+ sections.size == 1 && sections[0].num_bytes == 32 # https://tools.ietf.org/id/draft-bjh21-ssh-ed25519-00.html#rfc.section.4
66
+ when "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521"
67
+ sections.size == 2 # https://tools.ietf.org/html/rfc5656#section-3.1
68
+ else
69
+ false
70
+ end
54
71
  rescue
55
72
  false
56
73
  end
@@ -124,7 +141,7 @@ class SSHKey
124
141
  private
125
142
 
126
143
  def unpacked_byte_array(ssh_type, encoded_key)
127
- prefix = [7].pack("N") + ssh_type
144
+ prefix = [ssh_type.length].pack("N") + ssh_type
128
145
  decoded = Base64.decode64(encoded_key)
129
146
 
130
147
  # Base64 decoding is too permissive, so we should validate if encoding is correct
@@ -158,7 +175,7 @@ class SSHKey
158
175
 
159
176
  parsed = public_key.split(" ")
160
177
  parsed.each_with_index do |el, index|
161
- return parsed[index..(index+1)] if SSH_TYPES.invert[el]
178
+ return parsed[index..(index+1)] if SSH_TYPES[el]
162
179
  end
163
180
  raise PublicKeyError, "cannot determine key type"
164
181
  end
@@ -231,7 +248,7 @@ class SSHKey
231
248
 
232
249
  # SSH public key
233
250
  def ssh_public_key
234
- [directives.join(",").strip, SSH_TYPES[type], Base64.encode64(ssh_public_key_conversion).gsub("\n", ""), comment].join(" ").strip
251
+ [directives.join(",").strip, SSH_TYPES.invert[type], Base64.encode64(ssh_public_key_conversion).gsub("\n", ""), comment].join(" ").strip
235
252
  end
236
253
 
237
254
  # SSH2 public key (RFC4716)
@@ -344,7 +361,7 @@ class SSHKey
344
361
  # For instance, the "ssh-rsa" string is encoded as the following byte array
345
362
  # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a']
346
363
  def ssh_public_key_conversion
347
- typestr = SSH_TYPES[type]
364
+ typestr = SSH_TYPES.invert[type]
348
365
  methods = SSH_CONVERSION[type]
349
366
  pubkey = key_object.public_key
350
367
  methods.inject([7].pack("N") + typestr) do |pubkeystr, m|
@@ -1,3 +1,3 @@
1
1
  class SSHKey
2
- VERSION = "1.8.0"
2
+ VERSION = "1.9.0"
3
3
  end
@@ -79,17 +79,28 @@ EOF
79
79
  SSH_PUBLIC_KEY2 = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAxl6TpN7uFiY/JZ8qDnD7UrxDP+ABeh2PVg8Du1LEgXNk0+YWCeP5S6oHklqaWeDlbmAs1oHsBwCMAVpMa5tgONOLvz4JgwgkiqQEbKR8ofWJ+LADUElvqRVGmGiNEMLI6GJWeneL4sjmbb8d6U+M53c6iWG0si9XE5m7teBQSsCl0Tk3qMIkQGw5zpJeCXjZ8KpJhIJRYgexFkGgPlYRV+UYIhxpUW90t0Ra5i6JOFYwq98k5S/6SJIZQ/A9F4JNzwLw3eVxZj0yVHWxkGz1+TyELNY1kOyMxnZaqSfGzSQJTrnIXpdweVHuYh1LtOgedRQhCyiELeSMGwio1vRPKw=='
80
80
  SSH_PUBLIC_KEY3 = 'AAAAB3NzaC1kc3MAAACBALyVy5dwVwgL3CxXzsvo8DBh58qArQLBNIPW/f9pptmy7jD5QXzOw+12w0/z4lZ86ncoVutRMf44OABcX9ovhRl+luxB7jjpkVXy/p2ZaqPbeyTQUtdTmXa2y4n053Jd61VeMG+iLP7+viT+Ib96y9aVUYQfCrl5heBDUZ9cAFjdAAAAFQDFXnO7JJpFKwkeoor4GWGHtz0D2QAAAIEAqel0RUBO0MY5b3DZ69J/mRzUifN1O6twk4er2ph0JpryuUwZohLpcVZwqoGWmPQy/ZHmV1b3RtT9GWUa+HUqKdMhFVOx/iq1khVfLi83whjMMvXj3ecqd0yzGxGHnSsjVKefa2ywCLHrh4nlUVIaXI5gQpgMyVbMcromDe1WZzoAAACBAIwTRPAEcroqOzaebiVspFcmsXxDQ4wXQZQdho1ExW6FKS8s7/6pItmZYXTvJDwLXgq2/iK1fRRcKk2PJEaSuJR7WeNGsJKfWmQ2UbOhqA3wWLDazIZtcMKjFzD0hM4E8qgjHjMvKDE6WgT6SFP+tqx3nnh7pJWwsbGjSMQexpyR'
81
81
 
82
+ SSH_PUBLIC_KEY_ED25519 = 'AAAAC3NzaC1lZDI1NTE5AAAAIBrNsRCISAtKXV5OVxqV6unVcdis5Uh3oiC6B7CMB7HQ'
83
+ SSH_PUBLIC_KEY_ECDSA_256 = 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHJFDZ5qymZfIzoJcxYeu3C9HjJ08QAbqR28C2zSMLwcb3ZzWdRApnj6wEgRvizsBmr9zyPKb2u5Rp0vjJtQcZo='
84
+ SSH_PUBLIC_KEY_ECDSA_384 = 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBP+GtUCOR8aW7xTtpkbJS0qqNZ98PgbUNtTFhE+Oe+khgoFMX+o0JG5bckVuvtkRl8dr+63kUK0QPTtzP9O5yixB9CYnB8CgCgYo1FCXZuJIImf12wW5nWKglrCH4kV1Qg=='
85
+ SSH_PUBLIC_KEY_ECDSA_521 = 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACsunidnIZ77AjCHSDp/xknLGDW3M0Ia7nxLdImmp0XGbxtbwYm2ga5XUzV9dMO9wF9ICC3OuH6g9DtGOBNPru1PwFDjaPISGgm0vniEzWazLsvjJVLThOA3VyYLxmtjm0WfS+/DfxgWVS6oeCTnDjjoVVpwU/fDbUbYPPRZI84/hOGNA=='
86
+
82
87
  KEY1_MD5_FINGERPRINT = "2a:89:84:c9:29:05:d1:f8:49:79:1c:ba:73:99:eb:af"
83
88
  KEY2_MD5_FINGERPRINT = "3c:af:74:87:cc:cc:a1:12:05:1a:09:b7:7b:ce:ed:ce"
84
89
  KEY3_MD5_FINGERPRINT = "14:f6:6a:12:96:be:44:32:e6:3c:77:43:94:52:f5:7a"
90
+ ED25519_MD5_FINGERPRINT = "6f:1a:8a:c1:4f:13:5c:36:6e:3f:be:eb:49:3b:8e:3e"
91
+ ECDSA_256_MD5_FINGERPRINT = "d9:3a:7f:de:b2:65:04:ac:62:05:1a:1e:97:e9:2b:9d"
85
92
 
86
93
  KEY1_SHA1_FINGERPRINT = "e4:f9:79:f2:fe:d6:be:2d:ef:2e:c2:fa:aa:f8:b0:17:34:fe:0d:c0"
87
94
  KEY2_SHA1_FINGERPRINT = "9a:52:78:2b:6b:cb:39:b7:85:ed:90:8a:28:62:aa:b3:98:88:e6:07"
88
95
  KEY3_SHA1_FINGERPRINT = "15:68:c6:72:ac:18:d1:fc:ab:a2:b7:b5:8c:d1:fe:8f:b9:ae:a9:47"
96
+ ED25519_SHA1_FINGERPRINT = "57:41:7c:d0:e2:53:28:87:7e:87:53:d4:69:ef:ef:63:ec:c0:0e:5e"
97
+ ECDSA_256_SHA1_FINGERPRINT = "94:e8:92:2b:1b:ec:49:de:ff:85:ea:6e:10:d6:8d:87:7a:67:40:ee"
89
98
 
90
99
  KEY1_SHA256_FINGERPRINT = "js3llFehloxCfsVuDw5xu3NtS9AOAxcXY8WL6vkDIts="
91
100
  KEY2_SHA256_FINGERPRINT = "23f/6U/LdxIFx1CQFKHylw76n+LIHYoY4nRxKcFoos4="
92
101
  KEY3_SHA256_FINGERPRINT = "mPqEPQlOPGORrTJrU17sPax1jOqeutZja6MOsFIca+8="
102
+ ED25519_SHA256_FINGERPRINT = "gyzHUKl1eO8Bk1Cvn4joRgxRlXo1+1HJ3Vho/hAtKEg="
103
+ ECDSA_256_SHA256_FINGERPRINT = "ncy2crhoL44R58GCZPQ5chPRrjlQKKgu07FDNelDmdk="
93
104
 
94
105
  KEY1_RANDOMART = <<-EOF.rstrip
95
106
  +--[ RSA 2048]----+
@@ -311,17 +322,34 @@ EOF
311
322
  assert !SSHKey.valid_ssh_public_key?(invalid5)
312
323
  end
313
324
 
325
+ def test_ssh_public_key_validation_elliptic
326
+ assert SSHKey.valid_ssh_public_key?("ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519} me@example.com")
327
+ assert SSHKey.valid_ssh_public_key?("ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_256}")
328
+ assert SSHKey.valid_ssh_public_key?("ecdsa-sha2-nistp384 #{SSH_PUBLIC_KEY_ECDSA_384} me@example.com")
329
+ assert SSHKey.valid_ssh_public_key?(%Q{from="trusted.eng.cam.ac.uk",no-port-forwarding,no-pty ecdsa-sha2-nistp521 #{SSH_PUBLIC_KEY_ECDSA_521} me@example.com})
330
+
331
+ assert !SSHKey.valid_ssh_public_key?("ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519}= me@example.com") # bad base64
332
+ assert !SSHKey.valid_ssh_public_key?("ssh-ed25519 #{SSH_PUBLIC_KEY_ECDSA_384} me@example.com") # mismatched key format
333
+ assert !SSHKey.valid_ssh_public_key?("ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_384} me@example.com") # mismatched key format
334
+ assert !SSHKey.valid_ssh_public_key?("ssh-ed25519 asdf me@example.com") # gibberish key data
335
+ assert !SSHKey.valid_ssh_public_key?("ecdsa-sha2-nistp256 asdf me@example.com") # gibberish key data
336
+ end
337
+
314
338
  def test_ssh_public_key_validation_with_newlines
315
339
  expected1 = "ssh-rsa #{SSH_PUBLIC_KEY1}\n"
340
+ expected2 = "ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519} me@example.com\n"
316
341
  invalid1 = "ssh-rsa #{SSH_PUBLIC_KEY1}\nme@example.com"
317
342
  invalid2 = "ssh-rsa #{SSH_PUBLIC_KEY1}\n me@example.com"
318
343
  invalid3 = "ssh-rsa #{SSH_PUBLIC_KEY1} \nme@example.com"
344
+ invalid4 = "ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_256}\nme@example.com"
319
345
 
320
346
  assert SSHKey.valid_ssh_public_key?(expected1)
347
+ assert SSHKey.valid_ssh_public_key?(expected2)
321
348
 
322
349
  assert !SSHKey.valid_ssh_public_key?(invalid1)
323
350
  assert !SSHKey.valid_ssh_public_key?(invalid2)
324
351
  assert !SSHKey.valid_ssh_public_key?(invalid3)
352
+ assert !SSHKey.valid_ssh_public_key?(invalid4)
325
353
  end
326
354
 
327
355
  def test_ssh_public_key_bits
@@ -389,6 +417,8 @@ end
389
417
  assert_equal KEY2_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY2} me@me.com")
390
418
  assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint(SSH_PRIVATE_KEY3)
391
419
  assert_equal KEY3_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-dss #{SSH_PUBLIC_KEY3}")
420
+ assert_equal ED25519_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519}")
421
+ assert_equal ECDSA_256_MD5_FINGERPRINT, SSHKey.md5_fingerprint("ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_256} me@me.com")
392
422
 
393
423
  assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY1)
394
424
  assert_equal KEY1_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY1}")
@@ -396,6 +426,8 @@ end
396
426
  assert_equal KEY2_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY2} me@me.com")
397
427
  assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint(SSH_PRIVATE_KEY3)
398
428
  assert_equal KEY3_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-dss #{SSH_PUBLIC_KEY3}")
429
+ assert_equal ED25519_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519}")
430
+ assert_equal ECDSA_256_SHA1_FINGERPRINT, SSHKey.sha1_fingerprint("ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_256} me@me.com")
399
431
 
400
432
  assert_equal KEY1_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint(SSH_PRIVATE_KEY1)
401
433
  assert_equal KEY1_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY1}")
@@ -403,6 +435,8 @@ end
403
435
  assert_equal KEY2_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint("ssh-rsa #{SSH_PUBLIC_KEY2} me@me.com")
404
436
  assert_equal KEY3_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint(SSH_PRIVATE_KEY3)
405
437
  assert_equal KEY3_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint("ssh-dss #{SSH_PUBLIC_KEY3}")
438
+ assert_equal ED25519_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint("ssh-ed25519 #{SSH_PUBLIC_KEY_ED25519}")
439
+ assert_equal ECDSA_256_SHA256_FINGERPRINT, SSHKey.sha256_fingerprint("ecdsa-sha2-nistp256 #{SSH_PUBLIC_KEY_ECDSA_256} me@me.com")
406
440
  end
407
441
 
408
442
  def test_bits
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Miller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-01 00:00:00.000000000 Z
11
+ date: 2017-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
76
  version: '0'
77
77
  requirements: []
78
78
  rubyforge_project: sshkey
79
- rubygems_version: 2.4.5.1
79
+ rubygems_version: 2.6.8
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: SSH private/public key generator in Ruby