unix-crypt 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/LICENSE +10 -0
- data/README.rdoc +59 -0
- data/Rakefile +7 -0
- data/bin/mkunixcrypt +16 -0
- data/lib/unix_crypt.rb +32 -15
- data/lib/unix_crypt/command_line.rb +123 -0
- data/test/{unix_crypt_test.rb → test_unix_crypt.rb} +34 -1
- data/test/unix_crypt/test_command_line.rb +88 -0
- data/unix-crypt.gemspec +17 -0
- metadata +24 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1d23e0cd7fb0edc71372a52d4bd357dbbbbd0a8b
|
4
|
+
data.tar.gz: 0b135e10570ae2b629f52f441997cd304663b728
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 769ec3053c3e3af385aa5feb6bee79607763a6691cf33362f08a1198296c57cb1c98d8b78472f4eb354ac0e22cba35fc10d680e7bfecb30820d7ef71eb0a1b6b
|
7
|
+
data.tar.gz: a175438b7eedfe60a156aaaf003b3956cf70f7f0b054c181b29c9ca5879dbe421253b80d997331a2f095db1dcece3f5ed130df167c8dbaf82d037706cf31d317
|
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Copyright (c) 2013, Roger Nesbitt
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
Neither the name of the unix-crypt nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
9
|
+
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
= unix-crypt
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
unix-crypt creates and checks passwords that you'd normally find in an /etc/shadow file on your UNIX box.
|
6
|
+
|
7
|
+
It's written entirely in Ruby and has no external dependencies.
|
8
|
+
|
9
|
+
It handles:
|
10
|
+
* DES passwords (the standard 13 character password with a 2 character salt)
|
11
|
+
* MD5 passwords (starting with $1$)
|
12
|
+
* SHA256 passwords (starting with $5$)
|
13
|
+
* SHA512 passwords (starting with $6$)
|
14
|
+
|
15
|
+
This library is compatible with Ruby 1.8.7 and above. Tested on Ruby 2.0.0p0.
|
16
|
+
|
17
|
+
== Using the command line tool
|
18
|
+
|
19
|
+
An executable named +mkunixcrypt+ allows you to generate passwords from the command line.
|
20
|
+
|
21
|
+
Usage: mkunixcrypt [options]
|
22
|
+
Encrypts password using the unix-crypt gem
|
23
|
+
|
24
|
+
Options:
|
25
|
+
-h, --hash [HASH] Set hash algorithm [SHA512 (default), SHA256, MD5]
|
26
|
+
-p, --password [PASSWORD] Provide password on command line (insecure!)
|
27
|
+
-s, --salt [SALT] Provide hash salt
|
28
|
+
-r, --rounds [ROUNDS] Set number of hashing rounds (SHA256/SHA512 only)
|
29
|
+
--help Show this message
|
30
|
+
-v, --version Show version
|
31
|
+
|
32
|
+
== Using the library
|
33
|
+
|
34
|
+
You can either validate a password matches its hash:
|
35
|
+
|
36
|
+
>> UnixCrypt.valid?("Hello world!", "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5")
|
37
|
+
=> true
|
38
|
+
|
39
|
+
Or you can generate a new hash, given a password and salt:
|
40
|
+
|
41
|
+
>> UnixCrypt::SHA256.build("Hello world!", "saltstring")
|
42
|
+
=> "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5"
|
43
|
+
|
44
|
+
If a salt is not specified, one will be generated using random data:
|
45
|
+
|
46
|
+
>> UnixCrypt::SHA256.build("Hello world!")
|
47
|
+
=> "$5$v.fjb6lucDCZKjcf$90gzpr9HYo0eAeaN8rubElJdUUOcVYjTnGePBRvCgt1"
|
48
|
+
|
49
|
+
== License
|
50
|
+
|
51
|
+
Licensed under the BSD license. See LICENSE file for details.
|
52
|
+
|
53
|
+
== Author
|
54
|
+
|
55
|
+
* Roger Nesbitt (roger@seriousorange.com)
|
56
|
+
|
57
|
+
== Contributors
|
58
|
+
|
59
|
+
* Patrick Wyatt (pat@codeofhonor.com)
|
data/Rakefile
ADDED
data/bin/mkunixcrypt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'unix_crypt'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'unix_crypt'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'unix_crypt/command_line'
|
11
|
+
|
12
|
+
begin
|
13
|
+
UnixCrypt::CommandLine.new(ARGV).encrypt
|
14
|
+
rescue UnixCrypt::CommandLine::Abort => e
|
15
|
+
abort e.message
|
16
|
+
end
|
data/lib/unix_crypt.rb
CHANGED
@@ -2,6 +2,8 @@ require 'digest'
|
|
2
2
|
require 'securerandom'
|
3
3
|
|
4
4
|
module UnixCrypt
|
5
|
+
VERSION = "1.1.1"
|
6
|
+
|
5
7
|
def self.valid?(password, string)
|
6
8
|
# Handle the original DES-based crypt(3)
|
7
9
|
return password.crypt(string) == string if string.length == 13
|
@@ -16,7 +18,11 @@ module UnixCrypt
|
|
16
18
|
def self.build(password, salt = nil, rounds = nil)
|
17
19
|
salt ||= generate_salt
|
18
20
|
|
19
|
-
"$#{identifier}$#{salt}$#{hash(password, salt, rounds)}"
|
21
|
+
"$#{identifier}$#{rounds_marker rounds}#{salt}$#{hash(password, salt, rounds)}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.hash(password, salt, rounds = nil)
|
25
|
+
bit_specified_base64encode internal_hash(prepare_password(password), salt, rounds)
|
20
26
|
end
|
21
27
|
|
22
28
|
def self.generate_salt
|
@@ -56,6 +62,10 @@ module UnixCrypt
|
|
56
62
|
|
57
63
|
password
|
58
64
|
end
|
65
|
+
|
66
|
+
def self.rounds_marker(rounds)
|
67
|
+
nil
|
68
|
+
end
|
59
69
|
end
|
60
70
|
|
61
71
|
class MD5 < Base
|
@@ -68,11 +78,9 @@ module UnixCrypt
|
|
68
78
|
[[0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5], [nil, nil, 11]]
|
69
79
|
end
|
70
80
|
|
71
|
-
def self.
|
81
|
+
def self.internal_hash(password, salt, ignored = nil)
|
72
82
|
salt = salt[0..7]
|
73
83
|
|
74
|
-
password = prepare_password(password)
|
75
|
-
|
76
84
|
b = digest.digest("#{password}#{salt}#{password}")
|
77
85
|
a_string = "#{password}$1$#{salt}#{b * (password.length/length)}#{b[0...password.length % length]}"
|
78
86
|
|
@@ -92,22 +100,19 @@ module UnixCrypt
|
|
92
100
|
input = digest.digest(c_string)
|
93
101
|
end
|
94
102
|
|
95
|
-
|
103
|
+
input
|
96
104
|
end
|
97
105
|
end
|
98
106
|
|
99
107
|
class SHABase < Base
|
108
|
+
protected
|
100
109
|
def self.default_salt_length; 12; end
|
110
|
+
def self.default_rounds; 5000; end
|
101
111
|
|
102
|
-
def self.
|
103
|
-
rounds
|
104
|
-
rounds = 1000 if rounds < 1000
|
105
|
-
rounds = 999_999_999 if rounds > 999_999_999
|
106
|
-
|
112
|
+
def self.internal_hash(password, salt, rounds = nil)
|
113
|
+
rounds = apply_rounds_bounds(rounds || default_rounds)
|
107
114
|
salt = salt[0..15]
|
108
115
|
|
109
|
-
password = prepare_password(password)
|
110
|
-
|
111
116
|
b = digest.digest("#{password}#{salt}#{password}")
|
112
117
|
|
113
118
|
a_string = password + salt + b * (password.length/length) + b[0...password.length % length]
|
@@ -118,12 +123,12 @@ module UnixCrypt
|
|
118
123
|
password_length >>= 1
|
119
124
|
end
|
120
125
|
|
121
|
-
input =
|
126
|
+
input = digest.digest(a_string)
|
122
127
|
|
123
128
|
dp = digest.digest(password * password.length)
|
124
129
|
p = dp * (password.length/length) + dp[0...password.length % length]
|
125
130
|
|
126
|
-
ds = digest.digest(salt * (16 +
|
131
|
+
ds = digest.digest(salt * (16 + input.bytes.first))
|
127
132
|
s = ds * (salt.length/length) + ds[0...salt.length % length]
|
128
133
|
|
129
134
|
rounds.times do |index|
|
@@ -134,7 +139,19 @@ module UnixCrypt
|
|
134
139
|
input = digest.digest(c_string)
|
135
140
|
end
|
136
141
|
|
137
|
-
|
142
|
+
input
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.apply_rounds_bounds(rounds)
|
146
|
+
rounds = 1000 if rounds < 1000
|
147
|
+
rounds = 999_999_999 if rounds > 999_999_999
|
148
|
+
rounds
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.rounds_marker(rounds)
|
152
|
+
if rounds && rounds != default_rounds
|
153
|
+
"rounds=#{apply_rounds_bounds(rounds)}$"
|
154
|
+
end
|
138
155
|
end
|
139
156
|
end
|
140
157
|
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
begin
|
4
|
+
require 'io/console'
|
5
|
+
rescue LoadError
|
6
|
+
$no_io_console = true
|
7
|
+
end
|
8
|
+
|
9
|
+
class UnixCrypt::CommandLine
|
10
|
+
Abort = Class.new(StandardError)
|
11
|
+
|
12
|
+
attr_reader :options
|
13
|
+
|
14
|
+
def initialize(argv)
|
15
|
+
@options = Opts.parse(argv)
|
16
|
+
end
|
17
|
+
|
18
|
+
def encrypt
|
19
|
+
if @options.password.nil?
|
20
|
+
@options.password = ask_password
|
21
|
+
else
|
22
|
+
password_warning
|
23
|
+
end
|
24
|
+
|
25
|
+
puts @options.hasher.build(@options.password, @options.salt, @options.rounds)
|
26
|
+
clear_string(@options.password)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
class Opts
|
31
|
+
HASHERS = {
|
32
|
+
:SHA512 => UnixCrypt::SHA512,
|
33
|
+
:SHA256 => UnixCrypt::SHA256,
|
34
|
+
:MD5 => UnixCrypt::MD5
|
35
|
+
}
|
36
|
+
|
37
|
+
def self.parse(args)
|
38
|
+
options = OpenStruct.new
|
39
|
+
options.hashmethod = :SHA512
|
40
|
+
options.hasher = HASHERS[options.hashmethod]
|
41
|
+
options.password = nil
|
42
|
+
options.salt = nil
|
43
|
+
options.rounds = nil
|
44
|
+
options.leftovers = OptionParser.new do |opts|
|
45
|
+
opts.banner = "Usage: #{File.basename $0} [options]"
|
46
|
+
opts.separator "Encrypts password using the unix-crypt gem"
|
47
|
+
opts.separator ""
|
48
|
+
opts.separator "Options:"
|
49
|
+
|
50
|
+
opts.on("-h", "--hash [HASH]", String, "Set hash algorithm [SHA512 (default), SHA256, MD5]") do |hasher|
|
51
|
+
options.hashmethod = hasher.to_s.upcase.to_sym
|
52
|
+
options.hasher = HASHERS[options.hashmethod]
|
53
|
+
raise Abort, "Invalid hash algorithm for -h/--hash" if options.hasher.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on("-p", "--password [PASSWORD]", String, "Provide password on command line (insecure!)") do |password|
|
57
|
+
raise Abort, "Invalid password for -p/--password" if password.nil?
|
58
|
+
options.password = password
|
59
|
+
$0 = $0 # this invocation will get rid of the command line arguments from the process list
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-s", "--salt [SALT]", String, "Provide hash salt") do |salt|
|
63
|
+
raise Abort, "Invalid salt for -s/--salt" if salt.nil?
|
64
|
+
options.salt = salt
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on("-r", "--rounds [ROUNDS]", Integer, "Set number of hashing rounds (SHA256/SHA512 only)") do |rounds|
|
68
|
+
raise Abort, "Invalid hashing rounds for -r/--rounds" if rounds.nil? || rounds.to_i <= 0
|
69
|
+
options.rounds = rounds
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
73
|
+
puts opts
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on_tail("-v", "--version", "Show version") do
|
78
|
+
puts UnixCrypt::VERSION
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
end.parse!(args)
|
82
|
+
options
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def ask_noecho(message)
|
87
|
+
$stderr.print message
|
88
|
+
if $no_io_console
|
89
|
+
begin
|
90
|
+
`stty -echo`
|
91
|
+
result = gets
|
92
|
+
ensure
|
93
|
+
`stty echo`
|
94
|
+
end
|
95
|
+
else
|
96
|
+
result = $stdin.noecho(&:gets)
|
97
|
+
end
|
98
|
+
$stderr.puts
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
102
|
+
def password_warning
|
103
|
+
$stderr.puts "warning: providing a password on the command line is insecure"
|
104
|
+
end
|
105
|
+
|
106
|
+
def clear_string(string)
|
107
|
+
string.replace(" " * string.length)
|
108
|
+
end
|
109
|
+
|
110
|
+
def ask_password
|
111
|
+
password = ask_noecho("Enter password: ")
|
112
|
+
twice = ask_noecho("Verify password: ")
|
113
|
+
|
114
|
+
if password != twice
|
115
|
+
clear_string(password)
|
116
|
+
clear_string(twice)
|
117
|
+
raise Abort, "Passwords don't match"
|
118
|
+
end
|
119
|
+
|
120
|
+
clear_string(twice)
|
121
|
+
password.chomp!
|
122
|
+
end
|
123
|
+
end
|
@@ -8,7 +8,7 @@
|
|
8
8
|
#
|
9
9
|
|
10
10
|
require 'test/unit'
|
11
|
-
require '
|
11
|
+
require File.expand_path('../../lib/unix_crypt', __FILE__)
|
12
12
|
|
13
13
|
class UnixCryptTest < Test::Unit::TestCase
|
14
14
|
def test_password_validity
|
@@ -50,9 +50,42 @@ class UnixCryptTest < Test::Unit::TestCase
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
def test_md5_password_generation
|
54
|
+
hash = UnixCrypt::MD5.build("test")
|
55
|
+
assert UnixCrypt.valid?("test", hash)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_sha256_password_generation
|
59
|
+
hash = UnixCrypt::SHA256.build("test")
|
60
|
+
assert UnixCrypt.valid?("test", hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_sha512_password_generation
|
64
|
+
hash = UnixCrypt::SHA512.build("test")
|
65
|
+
assert UnixCrypt.valid?("test", hash)
|
66
|
+
end
|
67
|
+
|
53
68
|
def test_salt_generation
|
54
69
|
assert_match %r{\A\$1\$[a-zA-Z0-9./]{8}\$[a-zA-Z0-9./]{22}\z}, UnixCrypt::MD5.build("test password")
|
55
70
|
assert_match %r{\A\$5\$[a-zA-Z0-9./]{16}\$[a-zA-Z0-9./]{43}\z}, UnixCrypt::SHA256.build("test password")
|
56
71
|
assert_match %r{\A\$6\$[a-zA-Z0-9./]{16}\$[a-zA-Z0-9./]{86}\z}, UnixCrypt::SHA512.build("test password")
|
57
72
|
end
|
73
|
+
|
74
|
+
def test_password_generation_with_rounds
|
75
|
+
hash = UnixCrypt::SHA512.build("test password", nil, 5678)
|
76
|
+
assert_match %r{\A\$6\$rounds=5678\$[a-zA-Z0-9./]{16}\$[a-zA-Z0-9./]{86}\z}, hash
|
77
|
+
assert UnixCrypt.valid?("test password", hash)
|
78
|
+
|
79
|
+
assert_match %r{\A\$6\$rounds=5678\$salted\$[a-zA-Z0-9./]{86}\z}, UnixCrypt::SHA512.build("test password", "salted", 5678)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_default_rounds_does_not_add_rounds_marker
|
83
|
+
assert_match %r{\A\$6\$salted\$[a-zA-Z0-9./]{86}\z}, UnixCrypt::SHA512.build("test password", "salted", 5000) # the default number of rounds
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_rounds_bounds
|
87
|
+
hash = UnixCrypt::SHA512.build("test password", nil, 567)
|
88
|
+
assert_match %r{\A\$6\$rounds=1000\$[a-zA-Z0-9./]{16}\$[a-zA-Z0-9./]{86}\z}, hash
|
89
|
+
assert UnixCrypt.valid?("test password", hash)
|
90
|
+
end
|
58
91
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path('../../../lib/unix_crypt', __FILE__)
|
3
|
+
require File.expand_path('../../../lib/unix_crypt/command_line', __FILE__)
|
4
|
+
|
5
|
+
class CommandLineTest < Test::Unit::TestCase
|
6
|
+
class CaptureIO
|
7
|
+
def initialize(name, buffer, input = [])
|
8
|
+
@name = name
|
9
|
+
@buffer = buffer
|
10
|
+
@input = input
|
11
|
+
end
|
12
|
+
|
13
|
+
def noecho
|
14
|
+
yield self
|
15
|
+
end
|
16
|
+
|
17
|
+
def gets
|
18
|
+
@buffer << [@name, @input.first.dup]
|
19
|
+
@input.shift
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(data)
|
23
|
+
@buffer << [@name, data]
|
24
|
+
end
|
25
|
+
|
26
|
+
def print(data)
|
27
|
+
write data
|
28
|
+
end
|
29
|
+
|
30
|
+
def puts(data = "")
|
31
|
+
write "#{data}\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.redirect(input = [])
|
35
|
+
buffer = []
|
36
|
+
$stdin = new("stdin", buffer, input)
|
37
|
+
$stdout = new("stdout", buffer)
|
38
|
+
$stderr = new("stderr", buffer)
|
39
|
+
yield
|
40
|
+
buffer
|
41
|
+
ensure
|
42
|
+
$stdin = STDIN
|
43
|
+
$stdout = STDOUT
|
44
|
+
$stderr = STDERR
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_no_parameter_password_creation
|
49
|
+
result = CaptureIO.redirect(["hello\n", "hello\n"]) do
|
50
|
+
UnixCrypt::CommandLine.new([]).encrypt
|
51
|
+
end
|
52
|
+
|
53
|
+
expected = [
|
54
|
+
["stderr", "Enter password: "],
|
55
|
+
["stdin", "hello\n"],
|
56
|
+
["stderr", "\n"],
|
57
|
+
["stderr", "Verify password: "],
|
58
|
+
["stdin", "hello\n"],
|
59
|
+
["stderr", "\n"]
|
60
|
+
]
|
61
|
+
|
62
|
+
assert_equal expected, result[0..-2]
|
63
|
+
|
64
|
+
channel, password = result[-1]
|
65
|
+
assert_equal "stdout", channel
|
66
|
+
assert_match %r{\A\$6\$[a-zA-Z0-9./]{16}\$[a-zA-Z0-9./]{86}\n\z}, password
|
67
|
+
|
68
|
+
assert UnixCrypt.valid?("hello", password)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_parameters_provided_password_creation
|
72
|
+
result = CaptureIO.redirect do
|
73
|
+
UnixCrypt::CommandLine.new(%w(-h sha256 -p hello -s salty -r 1234)).encrypt
|
74
|
+
end
|
75
|
+
|
76
|
+
expected = [
|
77
|
+
["stderr", "warning: providing a password on the command line is insecure\n"]
|
78
|
+
]
|
79
|
+
|
80
|
+
assert_equal expected, result[0..-2]
|
81
|
+
|
82
|
+
channel, password = result[-1]
|
83
|
+
assert_equal "stdout", channel
|
84
|
+
assert_match %r{\A\$5\$rounds=1234\$salty\$[a-zA-Z0-9./]{43}\n\z}, password
|
85
|
+
|
86
|
+
assert UnixCrypt.valid?("hello", password)
|
87
|
+
end
|
88
|
+
end
|
data/unix-crypt.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require './lib/unix_crypt'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'unix-crypt'
|
5
|
+
s.version = UnixCrypt::VERSION
|
6
|
+
s.summary = "Performs the UNIX crypt(3) algorithm using DES, MD5, SHA256 or SHA512"
|
7
|
+
s.description = %{Performs the UNIX crypt(3) algorithm using DES (standard 13 character passwords), MD5 (starting with $1$), SHA256 (starting with $5$) and SHA512 (starting with $6$)}
|
8
|
+
s.files = `git ls-files`.split($\)
|
9
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
10
|
+
s.executables = ["mkunixcrypt"]
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.has_rdoc = false
|
13
|
+
s.author = "Roger Nesbitt"
|
14
|
+
s.email = "roger@seriousorange.com"
|
15
|
+
s.homepage = "https://github.com/mogest/unix-crypt"
|
16
|
+
s.license = "BSD"
|
17
|
+
end
|
metadata
CHANGED
@@ -1,48 +1,58 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unix-crypt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Roger Nesbitt
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-09-23 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Performs the UNIX crypt(3) algorithm using DES (standard 13 character
|
15
14
|
passwords), MD5 (starting with $1$), SHA256 (starting with $5$) and SHA512 (starting
|
16
15
|
with $6$)
|
17
16
|
email: roger@seriousorange.com
|
18
|
-
executables:
|
17
|
+
executables:
|
18
|
+
- mkunixcrypt
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- .gitignore
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
- Rakefile
|
26
|
+
- bin/mkunixcrypt
|
22
27
|
- lib/unix_crypt.rb
|
23
|
-
-
|
24
|
-
|
25
|
-
|
28
|
+
- lib/unix_crypt/command_line.rb
|
29
|
+
- test/test_unix_crypt.rb
|
30
|
+
- test/unix_crypt/test_command_line.rb
|
31
|
+
- unix-crypt.gemspec
|
32
|
+
homepage: https://github.com/mogest/unix-crypt
|
33
|
+
licenses:
|
34
|
+
- BSD
|
35
|
+
metadata: {}
|
26
36
|
post_install_message:
|
27
37
|
rdoc_options: []
|
28
38
|
require_paths:
|
29
39
|
- lib
|
30
40
|
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
-
none: false
|
32
41
|
requirements:
|
33
|
-
- -
|
42
|
+
- - '>='
|
34
43
|
- !ruby/object:Gem::Version
|
35
44
|
version: '0'
|
36
45
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
46
|
requirements:
|
39
|
-
- -
|
47
|
+
- - '>='
|
40
48
|
- !ruby/object:Gem::Version
|
41
49
|
version: '0'
|
42
50
|
requirements: []
|
43
51
|
rubyforge_project:
|
44
|
-
rubygems_version:
|
52
|
+
rubygems_version: 2.0.2
|
45
53
|
signing_key:
|
46
|
-
specification_version:
|
54
|
+
specification_version: 4
|
47
55
|
summary: Performs the UNIX crypt(3) algorithm using DES, MD5, SHA256 or SHA512
|
48
|
-
test_files:
|
56
|
+
test_files:
|
57
|
+
- test/test_unix_crypt.rb
|
58
|
+
- test/unix_crypt/test_command_line.rb
|