sshkey 1.0.0

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,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sshkey.gemspec
4
+ gemspec
@@ -0,0 +1,16 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the sshkey gem.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
@@ -0,0 +1,60 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ class SSHKey
5
+
6
+ def self.generate(comment)
7
+ SSHKey.new(OpenSSL::PKey::RSA.generate(2048), comment)
8
+ end
9
+
10
+ attr_reader :key_object, :comment, :rsa_private_key, :rsa_public_key, :ssh_public_key
11
+
12
+ def initialize(key_object, comment)
13
+ @key_object = key_object
14
+ @comment = comment
15
+ @rsa_private_key = key_object.to_pem
16
+ @rsa_public_key = key_object.public_key.to_pem
17
+ @ssh_public_key = ["ssh-rsa", Base64.strict_encode64(ssh_public_key_conversion), @comment].join(" ")
18
+ end
19
+
20
+ private
21
+
22
+ # All data type encoding is defined in the section #5 of RFC #4251.
23
+ # String and mpint (multiple precision integer) types are encoded this way :
24
+ # 4-bytes word: data length (unsigned big-endian 32 bits integer)
25
+ # n bytes : binary representation of the data
26
+
27
+ # For instance, the "ssh-rsa" string is encoded as the following byte array
28
+ # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a']
29
+ def ssh_public_key_conversion
30
+ e = @key_object.public_key.e.to_i
31
+ n = @key_object.public_key.n.to_i
32
+
33
+ out = [0,0,0,7].pack("c*")
34
+ out += "ssh-rsa"
35
+ out += encode_unsigned_int_32(to_byte_array(e).length).pack("c*")
36
+ out += to_byte_array(e).pack("c*")
37
+ out += encode_unsigned_int_32(to_byte_array(n).length).pack("c*")
38
+ out += to_byte_array(n).pack("c*")
39
+
40
+ return out
41
+ end
42
+
43
+ def encode_unsigned_int_32(value)
44
+ out = []
45
+ out[0] = value >> 24 & 0xff
46
+ out[1] = value >> 16 & 0xff
47
+ out[2] = value >> 8 & 0xff
48
+ out[3] = value & 0xff
49
+ return out
50
+ end
51
+
52
+ def to_byte_array(num)
53
+ result = []
54
+ begin
55
+ result << (num & 0xff)
56
+ num >>= 8
57
+ end until (num == 0 || num == -1) && (result.last[7] == num[7])
58
+ result.reverse
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ class SSHKey
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sshkey/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sshkey"
7
+ s.version = SSHKey::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["James Miller"]
10
+ s.email = ["bensie@gmail.com"]
11
+ s.homepage = "https://github.com/bensie/sshkey"
12
+ s.summary = %q{SSH private/public key generator in Ruby}
13
+ s.description = %q{Generate private/public SSH keys using Ruby without the ssh-keygen system command.}
14
+
15
+ s.rubyforge_project = "sshkey"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,121 @@
1
+ require 'test/unit'
2
+ require 'sshkey'
3
+
4
+ class SSHKeyTest < Test::Unit::TestCase
5
+ SSH_PRIVATE_KEY1 = <<-EOF
6
+ -----BEGIN RSA PRIVATE KEY-----
7
+ MIIEogIBAAKCAQEArfTA/lKVR84IMc9ZzXOCHr8DVtR8hzWuEVHF6KElavRHlk14
8
+ g0SZu3m908Ejm/XF3EfNHjX9wN+62IMA0QBxkBMFCuLF+U/oeUs0NoDdAEKxjj4n
9
+ 6lq6Ss8aLct+anMy7D1jwvOLbcwV54w1d5JDdlZVdZ6AvHm9otwJq6rNpDgdmXY4
10
+ HgC2nM9csFpuy0cDpL6fdJx9lcNL2RnkRC4+RMsIB+PxDw0j3vDi04dYLBXMGYjy
11
+ eGH+mIFpL3PTPXGXwL2XDYXZ2H4SQX6bOoKmazTXq6QXuEB665njh1GxXldoIMcS
12
+ shoJL0hrk3WrTOG22N2CQA+IfHgrXJ+A+QUzKQIBIwKCAQBAnLy2O+5N3s/X/I8R
13
+ y9E+nrgY79Z7XRTEmrc5JelTnI+eOggwwbVxhP1dR7zE5kItPz2O4NqYGJXbY9u7
14
+ V++qiri65oQMJP6Tc7ROwiYzS/jObtugMFPSpLHzwJyrMho6fTOuz3zuRH0qHiJ8
15
+ 3o4WAs9I8brJqY+UQxmI56t3gfHcX4nRhueyUvmEdDG+4Mob21wED1GD5ENh9ebX
16
+ UiuYkeROqd+lfBUkWoxUXi2fjRMSRt7n3bq59pyZQCwKiShIVaonciV8xAAlNvhI
17
+ RBzYvXbQ47YgsTmcW4Srlv0j/Oij2/RaDhkJtaXyPkqw9k4B8oCaX3C2x4sdhcwa
18
+ iLU7AoGBANb4Rmz1w4wfZSnu/HlW4G0Us+AWVEX+6zePoOartP5Pe5t3XhHW7vpi
19
+ YoB4ecqhz4Y1LoYZL07cSsQZHfntUV4eh/apuo/5slrhDkk0ewJkUh6SKLOFNv6Q
20
+ 7iJnmtzzRovW1MQPa0NeInsUrZYe4B4iGZmK4yEr9+c7IQCPFQvVAoGBAM8ofVgb
21
+ gzDYY2uX1lvU9bGAHqA/qNJHcYZBu5AZr7bkZC1GlSKh93ppczdQhiZmj2FQr09R
22
+ Z5GgKIlSWk8MYC+kYq7l5r2O42g3Unp+i1Zc5KCYUWYpyeE/jfl5IFJFQJFVtdB1
23
+ JlsFxruQIF/HuTzY6D+zF8GzK/T5ZQwigBgFAoGAGJFnImU663FNY+DMZaOHXOxs
24
+ VB/PHfE/dBBqKP2uSPMkEcR/x4ZHMo7mr5i9dj5g3CNVxi7Dk/vrSZx4dFWi5i9f
25
+ /u7TfisqU4dvWNLMOsmi/C32BeNWvgHvVGOcq4mEZ8DH2+SBSYcZ4i4/uWKdRUW5
26
+ yGek7dkjpWXX4s6GD/sCgYEAiCHr+BIUYe1Ipcotx1FuQXFzNhs0bO0et0/EZgJA
27
+ RPx8WERTX+bHMy9aV4yv7VlW6C21CDzPB+zncC7NoakMAgzwZE3vZp+6AqgDAAoD
28
+ ywnYEcMuLTFnaCJzPYocjdW8t0bz0iEZNIAjgpHpY4M/Np0q6Af5qyyZOpVCZw9b
29
+ fX8CgYEAqFpBwetp78UfwvWyKkfN56cY8EaC7gMkwE4gnXsByrqW0f/Shf5ofpO1
30
+ kCMav5GhplRYcF3mUO9xiAPx1FxWj/MjeevkmmugIrcYi5OpGu70KoaBmCmb5uV6
31
+ zJLsX4h3i0JFdIOaECZEOXhPA7btQT8Vvznj8cHFeeronqdFWf0=
32
+ -----END RSA PRIVATE KEY-----
33
+ EOF
34
+ SSH_PRIVATE_KEY2 = <<-EOF
35
+ -----BEGIN RSA PRIVATE KEY-----
36
+ MIIEogIBAAKCAQEAxl6TpN7uFiY/JZ8qDnD7UrxDP+ABeh2PVg8Du1LEgXNk0+YW
37
+ CeP5S6oHklqaWeDlbmAs1oHsBwCMAVpMa5tgONOLvz4JgwgkiqQEbKR8ofWJ+LAD
38
+ UElvqRVGmGiNEMLI6GJWeneL4sjmbb8d6U+M53c6iWG0si9XE5m7teBQSsCl0Tk3
39
+ qMIkQGw5zpJeCXjZ8KpJhIJRYgexFkGgPlYRV+UYIhxpUW90t0Ra5i6JOFYwq98k
40
+ 5S/6SJIZQ/A9F4JNzwLw3eVxZj0yVHWxkGz1+TyELNY1kOyMxnZaqSfGzSQJTrnI
41
+ XpdweVHuYh1LtOgedRQhCyiELeSMGwio1vRPKwIBIwKCAQEAiAZWnPCjQmNegDKg
42
+ fu5jMWsmzLbccP5TqLnWrFYDFvAKn+46/3fA421HBUVxJ7AoS6+pt6mL54tYsHhu
43
+ 6rOvsfAlT/AGhbxw1Biyk6P9sOLiRCDsVE+dBjp5jRR9/N1WkLh10FH5hZETCW0b
44
+ 0y88DG8DkWeR2UUIgngLr+pFr5jV/e4nvA5QpvbNscOwoiR7sFsMGLcMgM2fT4Hj
45
+ ZZovcGQMrDr6AG+y0/Vdf9wX22j+XKj7huIqM3GZvyqGPqJnP9sOKkPcuTck8Wx3
46
+ 55BX675RVdoW9OTcHbUh3qHcCND4d9WZqHarW/a7XBdIiuRmC2kBX5WBmVXnm/RF
47
+ bvxoCwKBgQDqyVNWwm98gIw7LS8dR6Ec7t3kOeLNo/rtNTszo631yZ4hqdwgYR3Q
48
+ q6rhjufsVVRLVzfTDXucbhZ5h+UB9wXAM49ZPxKNw+ddHsRbhCuIWUl/iO8E/Aub
49
+ H3eZupo73N9JGa4STFw056ejOQrTTCMf0M316V4wgFAXOZeHEErxSQKBgQDYSuqR
50
+ nr3Hdw1n/iXfKrfd9fJI++nm14uQ4mkA+9HrtQpj/RTxr66/QSj7p3r6GF4dDYY4
51
+ XaqK+iCfhUKMr8+3CP7NoS/saZAUqvMnL+RCvX14sV55xRMwplaaNIwqDhQAhkmL
52
+ UeOBq40kmBsunjfp06JedmWhWKHYc1eR2iPw0wKBgA1qlwxFn/h8X8jeArE3Swj3
53
+ tOh4VhphJEgRq5yNAqBUqfNLiOvoSti5WjjGVmVGtFwTnMo7SOReD+mv/nUkDvUK
54
+ QrSkhLeky2RoKHpCER279ZJCVs0Vt4U0/4UgmxldFBLORHYS/fRlAkPXX7RNflmW
55
+ 5zKfnvt1C+QR62bNuyO7AoGBAI4imiUtzStOPAKCcKiYajLGMYBrB2vPePjPTFEa
56
+ gqI1JBXSMlWt9n2uegR1X3El9LQBkrdTfrMZZeUrr2PD/Ybop3EvaKKrxRTlXfUu
57
+ GagzYRTMVAbgl5T/l/7vVMst0qFCTZYRPbucnpRj9Jr6QgAOuygh6wOgpN6yMjtG
58
+ NOAVAoGACIdfR5oZ4tvNIeqjtLF83HmUJARv86eMmjqgiQTFcZS3A8vk5y05STxX
59
+ HU3kTCfT6sypRi9zDQafIIyqYFgaOezr2eRRFRojQZqzHjtuFUeKLrKf7R9bzwwx
60
+ DPlNgYq8p4FOY5ZOL/ZOxUHW4vKRewURJttnxzw+LEy0T1FyAE0=
61
+ -----END RSA PRIVATE KEY-----
62
+ EOF
63
+
64
+ SSH_PUBLIC_KEY1 = 'AAAAB3NzaC1yc2EAAAABIwAAAQEArfTA/lKVR84IMc9ZzXOCHr8DVtR8hzWuEVHF6KElavRHlk14g0SZu3m908Ejm/XF3EfNHjX9wN+62IMA0QBxkBMFCuLF+U/oeUs0NoDdAEKxjj4n6lq6Ss8aLct+anMy7D1jwvOLbcwV54w1d5JDdlZVdZ6AvHm9otwJq6rNpDgdmXY4HgC2nM9csFpuy0cDpL6fdJx9lcNL2RnkRC4+RMsIB+PxDw0j3vDi04dYLBXMGYjyeGH+mIFpL3PTPXGXwL2XDYXZ2H4SQX6bOoKmazTXq6QXuEB665njh1GxXldoIMcSshoJL0hrk3WrTOG22N2CQA+IfHgrXJ+A+QUzKQ=='
65
+ SSH_PUBLIC_KEY2 = 'AAAAB3NzaC1yc2EAAAABIwAAAQEAxl6TpN7uFiY/JZ8qDnD7UrxDP+ABeh2PVg8Du1LEgXNk0+YWCeP5S6oHklqaWeDlbmAs1oHsBwCMAVpMa5tgONOLvz4JgwgkiqQEbKR8ofWJ+LADUElvqRVGmGiNEMLI6GJWeneL4sjmbb8d6U+M53c6iWG0si9XE5m7teBQSsCl0Tk3qMIkQGw5zpJeCXjZ8KpJhIJRYgexFkGgPlYRV+UYIhxpUW90t0Ra5i6JOFYwq98k5S/6SJIZQ/A9F4JNzwLw3eVxZj0yVHWxkGz1+TyELNY1kOyMxnZaqSfGzSQJTrnIXpdweVHuYh1LtOgedRQhCyiELeSMGwio1vRPKw=='
66
+
67
+ FINGERPRINT = "2a:89:84:c9:29:05:d1:f8:49:79:1c:ba:73:99:eb:af"
68
+
69
+ def setup
70
+ @key1 = SSHKey.new(OpenSSL::PKey::RSA.new(SSH_PRIVATE_KEY1), "me@example.com")
71
+ @key2 = SSHKey.new(OpenSSL::PKey::RSA.new(SSH_PRIVATE_KEY2), "me@example.com")
72
+ end
73
+
74
+ def test_private_key1
75
+ assert_equal SSH_PRIVATE_KEY1, @key1.rsa_private_key
76
+ end
77
+
78
+ def test_private_key2
79
+ assert_equal SSH_PRIVATE_KEY2, @key2.rsa_private_key
80
+ end
81
+
82
+ def test_ssh_public_key_decoded1
83
+ assert_equal Base64.strict_decode64(SSH_PUBLIC_KEY1), @key1.send(:ssh_public_key_conversion)
84
+ end
85
+
86
+ def test_ssh_public_key_decoded2
87
+ assert_equal Base64.strict_decode64(SSH_PUBLIC_KEY2), @key2.send(:ssh_public_key_conversion)
88
+ end
89
+
90
+ def test_ssh_public_key_encoded1
91
+ assert_equal SSH_PUBLIC_KEY1, Base64.strict_encode64(@key1.send(:ssh_public_key_conversion))
92
+ end
93
+
94
+ def test_ssh_public_key_encoded2
95
+ assert_equal SSH_PUBLIC_KEY2, Base64.strict_encode64(@key2.send(:ssh_public_key_conversion))
96
+ end
97
+
98
+ def test_ssh_public_key_output
99
+ expected1 = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArfTA/lKVR84IMc9ZzXOCHr8DVtR8hzWuEVHF6KElavRHlk14g0SZu3m908Ejm/XF3EfNHjX9wN+62IMA0QBxkBMFCuLF+U/oeUs0NoDdAEKxjj4n6lq6Ss8aLct+anMy7D1jwvOLbcwV54w1d5JDdlZVdZ6AvHm9otwJq6rNpDgdmXY4HgC2nM9csFpuy0cDpL6fdJx9lcNL2RnkRC4+RMsIB+PxDw0j3vDi04dYLBXMGYjyeGH+mIFpL3PTPXGXwL2XDYXZ2H4SQX6bOoKmazTXq6QXuEB665njh1GxXldoIMcSshoJL0hrk3WrTOG22N2CQA+IfHgrXJ+A+QUzKQ== me@example.com"
100
+ expected2 = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxl6TpN7uFiY/JZ8qDnD7UrxDP+ABeh2PVg8Du1LEgXNk0+YWCeP5S6oHklqaWeDlbmAs1oHsBwCMAVpMa5tgONOLvz4JgwgkiqQEbKR8ofWJ+LADUElvqRVGmGiNEMLI6GJWeneL4sjmbb8d6U+M53c6iWG0si9XE5m7teBQSsCl0Tk3qMIkQGw5zpJeCXjZ8KpJhIJRYgexFkGgPlYRV+UYIhxpUW90t0Ra5i6JOFYwq98k5S/6SJIZQ/A9F4JNzwLw3eVxZj0yVHWxkGz1+TyELNY1kOyMxnZaqSfGzSQJTrnIXpdweVHuYh1LtOgedRQhCyiELeSMGwio1vRPKw== me@example.com"
101
+ assert_equal expected1, @key1.ssh_public_key
102
+ assert_equal expected2, @key2.ssh_public_key
103
+ end
104
+
105
+ def test_exponent
106
+ assert_equal 35, @key1.key_object.e.to_i
107
+ assert_equal 35, @key2.key_object.e.to_i
108
+ end
109
+
110
+ def test_modulus
111
+ assert_equal 21959919395955180268707532246136630338880737002345156586705317733493418045367765414088155418090419238250026039981229751319343545922377196559932805781226688384973919515037364518167604848468288361633800200593870224270802677578686553567598208927704479575929054501425347794297979215349516030584575472280923909378896367886007339003194417496761108245404573433556449606964806956220743380296147376168499567508629678037211105349574822849913423806275470761711930875368363589001630573570236600319099783704171412637535837916991323769813598516411655563604244942820475880695152610674934239619752487880623016350579174487901241422633, @key1.key_object.n.to_i
112
+ assert_equal 25041821909255634338594631709409930006900629565221199423527442992482865961613864019776541767273966885435978473182530882048894721263421597979360058644777295324028381353356143013803778109979347540540538361684778724178534886189535456555760676722894784592989232554962714835255398111716791175503010379276254975882143986862239829255392231575481418297073759441882528318940783011390002193682320028951031205422825662402426266933458263786546846123394508656926946338411182471843223455365249418245551220933173115037201835242811305615780499842939975996344432437312062643436832423359634116147870328774728910949553186982115987967787, @key2.key_object.n.to_i
113
+ end
114
+
115
+ def test_to_byte_array
116
+ ba1 = @key1.send(:to_byte_array, 35)
117
+ ba2 = @key1.send(:to_byte_array, 65537)
118
+ assert_equal [35], ba1
119
+ assert_equal [1, 0, 1], ba2
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sshkey
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - James Miller
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-12 00:00:00 -08:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Generate private/public SSH keys using Ruby without the ssh-keygen system command.
18
+ email:
19
+ - bensie@gmail.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files: []
25
+
26
+ files:
27
+ - .gitignore
28
+ - Gemfile
29
+ - Rakefile
30
+ - lib/sshkey.rb
31
+ - lib/sshkey/version.rb
32
+ - sshkey.gemspec
33
+ - test/sshkey_test.rb
34
+ has_rdoc: true
35
+ homepage: https://github.com/bensie/sshkey
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ requirements: []
56
+
57
+ rubyforge_project: sshkey
58
+ rubygems_version: 1.5.1
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: SSH private/public key generator in Ruby
62
+ test_files:
63
+ - test/sshkey_test.rb