passwd 0.0.6 → 0.0.7
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.
- data/README.md +1 -1
- data/lib/passwd.rb +18 -15
- data/lib/passwd/active_record.rb +28 -14
- data/lib/passwd/version.rb +1 -1
- data/spec/passwd/password_spec.rb +102 -89
- data/spec/passwd_spec.rb +129 -76
- data/spec/spec_helper.rb +15 -0
- metadata +5 -5
data/README.md
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/passwd)
|
4
4
|
[](https://travis-ci.org/i2bskn/passwd)
|
5
|
-
[](https://codeclimate.com/github/i2bskn/passwd)
|
6
5
|
[](https://coveralls.io/r/i2bskn/passwd?branch=master)
|
6
|
+
[](https://codeclimate.com/github/i2bskn/passwd)
|
7
7
|
|
8
8
|
Password utilities.
|
9
9
|
|
data/lib/passwd.rb
CHANGED
@@ -19,33 +19,36 @@ module Passwd
|
|
19
19
|
|
20
20
|
class << self
|
21
21
|
def create(options={})
|
22
|
-
config = @@config.merge(options)
|
22
|
+
config = @@config.merge(config_validator(options))
|
23
23
|
letters = get_retters(config)
|
24
|
-
|
25
|
-
# Create random password
|
26
24
|
Array.new(config[:length]){letters[rand(letters.size)]}.join
|
27
25
|
end
|
28
26
|
|
29
|
-
def get_retters(config)
|
30
|
-
# Create letters
|
31
|
-
letters = Array.new
|
32
|
-
letters += config[:letters_lower] if config[:lower]
|
33
|
-
letters += config[:letters_upper] if config[:upper]
|
34
|
-
letters += config[:letters_number] if config[:number]
|
35
|
-
letters
|
36
|
-
end
|
37
|
-
|
38
27
|
def auth(password_text, salt_hash, password_hash)
|
39
28
|
enc_pass = Passwd.hashing("#{salt_hash}#{password_text}")
|
40
29
|
password_hash == enc_pass
|
41
30
|
end
|
42
31
|
|
43
|
-
def hashing(
|
44
|
-
Digest::SHA1.hexdigest
|
32
|
+
def hashing(password)
|
33
|
+
Digest::SHA1.hexdigest password
|
45
34
|
end
|
46
35
|
|
47
36
|
def config(options={})
|
48
|
-
@@config.merge!(options)
|
37
|
+
@@config.merge!(config_validator(options))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def get_retters(config)
|
42
|
+
["lower", "upper", "number"].inject([]) do |letters, type|
|
43
|
+
letters.concat(config["letters_#{type}".to_sym]) if config[type.to_sym]
|
44
|
+
letters
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def config_validator(config_hash)
|
49
|
+
parameters = [:length, :lower, :upper, :number, :letters_lower, :letters_upper, :letters_number]
|
50
|
+
config = config_hash.inject({}){|r, (k, v)| r.store(k.to_sym, v); r}
|
51
|
+
config.select{|k, v| parameters.include? k}
|
49
52
|
end
|
50
53
|
end
|
51
54
|
end
|
data/lib/passwd/active_record.rb
CHANGED
@@ -4,30 +4,44 @@ module Passwd
|
|
4
4
|
module ActiveRecord
|
5
5
|
module ClassMethods
|
6
6
|
def define_column(options={})
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
id_name = options[:id] || :email
|
8
|
+
salt_name = options[:salt] || :salt
|
9
|
+
password_name = options[:password] || :password
|
10
10
|
|
11
|
+
define_singleton_auth(id_name, salt_name, password_name)
|
12
|
+
define_instance_auth(id_name, salt_name, password_name)
|
13
|
+
define_set_password(id_name, salt_name, password_name)
|
14
|
+
define_update_password(salt_name, password_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def define_singleton_auth(id_name, salt_name, password_name)
|
11
19
|
define_singleton_method :authenticate do |id, pass|
|
12
|
-
user = self.where(
|
13
|
-
user if user && Passwd.auth(pass, user.send(
|
20
|
+
user = self.where(id_name => id).first
|
21
|
+
user if user && Passwd.auth(pass, user.send(salt_name), user.send(password_name))
|
14
22
|
end
|
23
|
+
end
|
15
24
|
|
25
|
+
def define_instance_auth(id_name, salt_name, password_name)
|
16
26
|
define_method :authenticate do |pass|
|
17
|
-
Passwd.auth(pass, self.send(
|
27
|
+
Passwd.auth(pass, self.send(salt_name), self.send(password_name))
|
18
28
|
end
|
29
|
+
end
|
19
30
|
|
31
|
+
def define_set_password(id_name, salt_name, password_name)
|
20
32
|
define_method :set_password do |pass=nil|
|
21
33
|
password = pass || Passwd.create
|
22
|
-
salt = self.send(
|
23
|
-
self.send("#{
|
24
|
-
self.send("#{
|
34
|
+
salt = self.send(salt_name) || Passwd.hashing("#{self.send(id_name)}#{Time.now.to_s}")
|
35
|
+
self.send("#{salt_name.to_s}=", salt)
|
36
|
+
self.send("#{password_name.to_s}=", Passwd.hashing("#{salt}#{password}"))
|
25
37
|
password
|
26
38
|
end
|
39
|
+
end
|
27
40
|
|
28
|
-
|
29
|
-
|
30
|
-
|
41
|
+
def define_update_password(salt_name, password_name)
|
42
|
+
define_method :update_password do |old_pass, new_pass|
|
43
|
+
if Passwd.auth(old_pass, self.send(salt_name), self.send(password_name))
|
44
|
+
set_password(new_pass)
|
31
45
|
else
|
32
46
|
false
|
33
47
|
end
|
@@ -36,8 +50,8 @@ module Passwd
|
|
36
50
|
end
|
37
51
|
|
38
52
|
class << self
|
39
|
-
def included(
|
40
|
-
|
53
|
+
def included(base)
|
54
|
+
base.extend ClassMethods
|
41
55
|
end
|
42
56
|
end
|
43
57
|
end
|
data/lib/passwd/version.rb
CHANGED
@@ -3,136 +3,149 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe Passwd::Password do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
let(:default) {@default}
|
7
|
+
let(:password) {Passwd::Password.new}
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
context "with default params" do
|
11
|
+
let!(:password_text) {
|
12
|
+
password_text = Passwd.create
|
13
|
+
Passwd.should_receive(:create).and_return(password_text)
|
14
|
+
password_text
|
15
|
+
}
|
16
|
+
|
17
|
+
let!(:time_now) {
|
18
|
+
time_now = Time.now
|
19
|
+
Time.should_receive(:now).and_return(time_now)
|
20
|
+
time_now
|
21
|
+
}
|
22
|
+
|
23
|
+
it "@text should be a random password" do
|
24
|
+
expect(password.text.size).to eq(default[:length])
|
25
|
+
expect(password.text).to eq(password_text)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "@salt_text should be a auto created" do
|
29
|
+
expect(password.salt_text).to eq(time_now.to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "@salt_hash should be a hashed salt" do
|
33
|
+
expect(password.salt_hash).to eq(Passwd.hashing(time_now.to_s))
|
34
|
+
end
|
35
|
+
|
36
|
+
it "@password_hash should be a hashed password with salt" do
|
37
|
+
password_hash = Passwd.hashing("#{Passwd.hashing(time_now.to_s)}#{password_text}")
|
38
|
+
expect(password.hash).to eq(password_hash)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with custom params" do
|
43
|
+
let(:password_text) {Passwd.create}
|
44
|
+
let(:salt_text) {"salt"}
|
45
|
+
let!(:time_now) {
|
46
|
+
time_now = Time.now
|
47
|
+
Time.stub(:create).and_return(time_now)
|
48
|
+
time_now
|
49
|
+
}
|
50
|
+
|
51
|
+
it "@text is specified password" do
|
52
|
+
password = Passwd::Password.new(password: password_text)
|
53
|
+
expect(password.text).to eq(password_text)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "@hash is hash of specified password" do
|
57
|
+
password = Passwd::Password.new(password: password_text)
|
58
|
+
password_hash = Passwd.hashing("#{Passwd.hashing(time_now.to_s)}#{password_text}")
|
59
|
+
expect(password.hash).to eq(password_hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "@salt_text is specified salt" do
|
63
|
+
password = Passwd::Password.new(salt_text: salt_text)
|
64
|
+
expect(password.salt_text).to eq(salt_text)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "@salt_hash is hash of specified salt" do
|
68
|
+
salt_hash = Passwd.hashing(salt_text)
|
69
|
+
password = Passwd::Password.new(salt_text: salt_text)
|
70
|
+
expect(password.salt_hash).to eq(salt_hash)
|
71
|
+
end
|
40
72
|
end
|
41
73
|
end
|
42
74
|
|
43
|
-
|
44
|
-
before(:each) do
|
45
|
-
@password = Passwd::Password.new(password: "Secret!!")
|
46
|
-
end
|
47
|
-
|
75
|
+
describe "#text=" do
|
48
76
|
it "@text is changed" do
|
49
|
-
old_password =
|
50
|
-
|
51
|
-
expect(
|
77
|
+
old_password = password.text
|
78
|
+
password.text = password.text.reverse
|
79
|
+
expect(password.text).not_to eq(old_password)
|
52
80
|
end
|
53
81
|
|
54
82
|
it "@hash is changed" do
|
55
|
-
old_hash =
|
56
|
-
|
57
|
-
expect(
|
83
|
+
old_hash = password.hash
|
84
|
+
new_password = password.text = password.text.reverse
|
85
|
+
expect(password.hash).not_to eq(old_hash)
|
86
|
+
expect(password.hash).to eq(Passwd.hashing("#{password.salt_hash}#{new_password}"))
|
58
87
|
end
|
59
88
|
end
|
60
89
|
|
61
|
-
|
62
|
-
before(:each) do
|
63
|
-
@password = Passwd::Password.new
|
64
|
-
end
|
65
|
-
|
90
|
+
describe "#hash=" do
|
66
91
|
it "@text is nil" do
|
67
|
-
|
68
|
-
expect(
|
92
|
+
password.hash = Passwd.hashing("secret")
|
93
|
+
expect(password.text).to be_nil
|
69
94
|
end
|
70
95
|
|
71
96
|
it "@hash is changed" do
|
72
|
-
old_hash =
|
73
|
-
|
74
|
-
expect(
|
97
|
+
old_hash = password.hash
|
98
|
+
password.hash = Passwd.hashing("secret")
|
99
|
+
expect(password.hash).not_to eq(old_hash)
|
75
100
|
end
|
76
101
|
end
|
77
102
|
|
78
|
-
|
79
|
-
before(:each) do
|
80
|
-
@password = Passwd::Password.new
|
81
|
-
end
|
82
|
-
|
103
|
+
describe "#salt_text=" do
|
83
104
|
it "@salt_text is changed" do
|
84
|
-
|
85
|
-
|
86
|
-
expect(
|
105
|
+
old_salt = password.salt_text
|
106
|
+
password.salt_text = "salt"
|
107
|
+
expect(password.salt_text).not_to eq(old_salt)
|
87
108
|
end
|
88
109
|
|
89
110
|
it "@salt_hash is changed" do
|
90
|
-
|
91
|
-
|
92
|
-
expect(
|
111
|
+
old_salt = password.salt_hash
|
112
|
+
password.salt_text = "salt"
|
113
|
+
expect(password.salt_hash).not_to eq(old_salt)
|
93
114
|
end
|
94
115
|
|
95
116
|
it "@hash is changed" do
|
96
|
-
old_hash =
|
97
|
-
|
98
|
-
expect(
|
117
|
+
old_hash = password.hash
|
118
|
+
password.salt_text = "salt"
|
119
|
+
expect(password.hash).not_to eq(old_hash)
|
99
120
|
end
|
100
121
|
end
|
101
122
|
|
102
|
-
|
103
|
-
before(:each) do
|
104
|
-
@password = Passwd::Password.new
|
105
|
-
end
|
106
|
-
|
123
|
+
describe "#salt_hash=" do
|
107
124
|
it "@salt_text is nil" do
|
108
|
-
|
109
|
-
expect(
|
125
|
+
password.salt_hash = Passwd.hashing("salt")
|
126
|
+
expect(password.salt_text).to eq(nil)
|
110
127
|
end
|
111
128
|
|
112
129
|
it "@salt_hash is changed" do
|
113
|
-
old_salt_hash =
|
114
|
-
|
115
|
-
expect(
|
130
|
+
old_salt_hash = password.salt_hash
|
131
|
+
password.salt_hash = Passwd.hashing("salt")
|
132
|
+
expect(password.salt_hash).not_to eq(old_salt_hash)
|
116
133
|
end
|
117
134
|
|
118
135
|
it "@hash is changed" do
|
119
|
-
old_hash =
|
120
|
-
|
121
|
-
expect(
|
136
|
+
old_hash = password.hash
|
137
|
+
password.salt_hash = Passwd.hashing("salt")
|
138
|
+
expect(password.hash).not_to eq(old_hash)
|
122
139
|
end
|
123
140
|
end
|
124
141
|
|
125
|
-
|
126
|
-
before(:each) do
|
127
|
-
@password = Passwd::Password.new
|
128
|
-
end
|
129
|
-
|
142
|
+
describe "#==" do
|
130
143
|
it "return true with valid password" do
|
131
|
-
expect(
|
144
|
+
expect(password == password.text).to be_true
|
132
145
|
end
|
133
146
|
|
134
147
|
it "return false with invalid password" do
|
135
|
-
expect(
|
148
|
+
expect(password == "secret").to be_false
|
136
149
|
end
|
137
150
|
end
|
138
151
|
end
|
data/spec/passwd_spec.rb
CHANGED
@@ -3,82 +3,135 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe Passwd do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
6
|
+
let(:default) {@default}
|
7
|
+
|
8
|
+
describe "default settings" do
|
9
|
+
let(:config) {Passwd.config}
|
10
|
+
|
11
|
+
it "length should be a default" do
|
12
|
+
expect(config[:length]).to eq(default[:length])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "lower should be a default" do
|
16
|
+
expect(config[:lower]).to eq(default[:lower])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "upper should be a default" do
|
20
|
+
expect(config[:upper]).to eq(default[:upper])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "number should be a default" do
|
24
|
+
expect(config[:number]).to eq(default[:number])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "letters_lower should be a default" do
|
28
|
+
expect(config[:letters_lower]).to eq(default[:letters_lower])
|
29
|
+
end
|
30
|
+
|
31
|
+
it "letters_upper should be a default" do
|
32
|
+
expect(config[:letters_upper]).to eq(default[:letters_upper])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "letters_number should be a default" do
|
36
|
+
expect(config[:letters_number]).to eq(default[:letters_number])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ".create" do
|
41
|
+
it "create random password" do
|
42
|
+
password = Passwd.create
|
43
|
+
expect(password.is_a? String).to be_true
|
44
|
+
expect(password.size).to eq(default[:length])
|
45
|
+
end
|
46
|
+
|
47
|
+
it "password was created specified characters" do
|
48
|
+
expect(Passwd.create(length: 10).size).to eq(10)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "password create without lower case" do
|
52
|
+
password = Passwd.create lower: false
|
53
|
+
expect(default[:letters_lower].include? password).to be_false
|
54
|
+
end
|
55
|
+
|
56
|
+
it "password create without upper case" do
|
57
|
+
password = Passwd.create upper: false
|
58
|
+
expect(default[:letters_upper].include? password).to be_false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "password create without number" do
|
62
|
+
password = Passwd.create(number: false)
|
63
|
+
expect(default[:letters_number].include? password).to be_false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe ".auth" do
|
68
|
+
let!(:password) do
|
69
|
+
password = Passwd.create
|
70
|
+
salt_hash = Passwd.hashing(Time.now.to_s)
|
71
|
+
password_hash = Passwd.hashing("#{salt_hash}#{password}")
|
72
|
+
{text: password, salt: salt_hash, hash: password_hash}
|
73
|
+
end
|
74
|
+
|
75
|
+
it "return true with valid password" do
|
76
|
+
expect(Passwd.auth(password[:text], password[:salt], password[:hash])).to be_true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "return false with invalid password" do
|
80
|
+
expect(Passwd.auth("invalid", password[:salt], password[:hash])).to be_false
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should create exception if not specified arguments" do
|
84
|
+
expect(proc{Passwd.auth}).to raise_error
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".hashing" do
|
89
|
+
it "return hashed password" do
|
90
|
+
Digest::SHA1.should_receive(:hexdigest).with("secret").and_return("hash")
|
91
|
+
expect(Passwd.hashing("secret")).to eq("hash")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should create exception if not specified argument" do
|
95
|
+
expect(proc{Passwd.hashing}).to raise_error
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe ".config" do
|
100
|
+
after {Passwd.config(default)}
|
101
|
+
|
102
|
+
it "return config hash" do
|
103
|
+
expect(Passwd.config.is_a? Hash).to be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it "set config value" do
|
107
|
+
Passwd.config(length: 10)
|
108
|
+
expect(Passwd.config[:length]).not_to eq(default[:length])
|
109
|
+
expect(Passwd.config[:lower]).to eq(default[:lower])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe ".get_retters" do
|
114
|
+
it "return letters" do
|
115
|
+
letters = Passwd.send(:get_retters, default)
|
116
|
+
expect(letters.is_a? Array).to be_true
|
117
|
+
expect(letters.select{|s| s.is_a? String}).to eq(letters)
|
118
|
+
expect(letters).to eq(default[:letters_lower] + default[:letters_upper] + default[:letters_number])
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should create exception if not specified argument" do
|
122
|
+
expect(proc{Passwd.send(:get_retters)}).to raise_error
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe ".config_validator" do
|
127
|
+
it "convert to symbol the key" do
|
128
|
+
config = default.inject({}){|r, (k, v)| r.store(k.to_s, v); r}
|
129
|
+
expect(Passwd.send(:config_validator, config)).to eq(default)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "delete not defined parameters" do
|
133
|
+
config = default.merge(invalid_parameter: true)
|
134
|
+
expect(Passwd.send(:config_validator, config)).to eq(default)
|
82
135
|
end
|
83
136
|
end
|
84
137
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,3 +2,18 @@ require "passwd"
|
|
2
2
|
|
3
3
|
require "coveralls"
|
4
4
|
Coveralls.wear!
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.order = "random"
|
8
|
+
config.before do
|
9
|
+
@default = {
|
10
|
+
length: 8,
|
11
|
+
lower: true,
|
12
|
+
upper: true,
|
13
|
+
number: true,
|
14
|
+
letters_lower: ('a'..'z').to_a,
|
15
|
+
letters_upper: ('A'..'Z').to_a,
|
16
|
+
letters_number: ('0'..'9').to_a
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passwd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -97,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
97
|
version: '0'
|
98
98
|
segments:
|
99
99
|
- 0
|
100
|
-
hash:
|
100
|
+
hash: 35413922955959980
|
101
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
102
|
none: false
|
103
103
|
requirements:
|
@@ -106,10 +106,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
106
|
version: '0'
|
107
107
|
segments:
|
108
108
|
- 0
|
109
|
-
hash:
|
109
|
+
hash: 35413922955959980
|
110
110
|
requirements: []
|
111
111
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.8.
|
112
|
+
rubygems_version: 1.8.25
|
113
113
|
signing_key:
|
114
114
|
specification_version: 3
|
115
115
|
summary: Password utility
|