phpass-ruby 0.1.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,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.1.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.1"
12
+ gem "rcov", ">= 0"
13
+ end
@@ -0,0 +1,29 @@
1
+ This is a porting of [phpass](http://www.openwall.com/phpass/)
2
+
3
+ All files within this package are in public domain.
4
+
5
+ # Install
6
+
7
+ $ gem install phpass
8
+
9
+ # Usage
10
+
11
+ require "rubygems"
12
+ require "phpass"
13
+
14
+ # 12 is password strength / calculation time. This is trade-off. Try
15
+ phpass = Phpass.new(12)
16
+
17
+ # Get hashed string. These are different result each time.
18
+ p phpass.hash('foo')
19
+ p phpass.hash('foo')
20
+ p phpass.hash('foo')
21
+
22
+ # Compare input and stored hash
23
+ known = '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'
24
+ p phpass.check('test12345', known) # => true
25
+ p phpass.check('test12346', known) # => false
26
+
27
+ # Caution
28
+
29
+ phpass-ruby is supporting portable(MD5) hashing only.
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "phpass-ruby"
16
+ gem.homepage = "http://github.com/tt25/phpass-ruby"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{TODO: one-line summary of your gem}
19
+ gem.description = %Q{TODO: longer description of your gem}
20
+ gem.email = "a@tt25.org"
21
+ gem.authors = ["uu59"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "phpass-ruby #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
@@ -0,0 +1,40 @@
1
+ # -- coding: utf-8
2
+
3
+ require "digest/md5"
4
+ require "openssl"
5
+ require "#{File.dirname(__FILE__)}/phpass/md5.rb"
6
+
7
+ class Phpass
8
+ def initialize(iter=8)
9
+ iter = 8 unless (8..128).include?(iter)
10
+ @iter = iter
11
+ end
12
+
13
+ def hash(pw, alg=:md5)
14
+ hasher = Md5.new(@iter)
15
+ hasher.hash(pw)
16
+ end
17
+
18
+ def check(pw, hash)
19
+ hasher = Md5.new(@iter)
20
+ hasher.check(pw, hash)
21
+ end
22
+
23
+ def self.random_bytes(length)
24
+ out = ''
25
+ if File.readable?('/dev/urandom')
26
+ out = File.read('/dev/urandom', length)
27
+ end
28
+
29
+ if(out.length < length)
30
+ random_state = '%s%s' % [Time.now.to_f, $$]
31
+ out = ''
32
+ while out.length < length
33
+ rnd = Digest::MD5.hexdigest(Time.now.to_f.to_s + random_state)
34
+ out << Digest::MD5.digest(rnd)
35
+ end
36
+ out = out[0..length]
37
+ end
38
+ out
39
+ end
40
+ end
@@ -0,0 +1,74 @@
1
+ # -- coding: utf-8
2
+
3
+ require "rubygems"
4
+
5
+ class Phpass
6
+ class Md5
7
+ def initialize(stretch=8)
8
+ @itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
9
+ stretch = 8 unless (8..128).include?(stretch)
10
+ @stretch = stretch
11
+ @random_state = '%s%s' % [Time.now.to_f, $$]
12
+ end
13
+
14
+ def hash(pw)
15
+ rnd = ''
16
+ rnd = Phpass.random_bytes(6)
17
+ crypt(pw, gensalt(rnd))
18
+ end
19
+
20
+ def check(pw, hash)
21
+ crypt(pw, hash) == hash
22
+ end
23
+
24
+ private
25
+
26
+ def gensalt(input)
27
+ out = '$P$'
28
+ out << @itoa64[[@stretch + 5, 30].min]
29
+ out << encode64(input, 6)
30
+ out
31
+ end
32
+
33
+ def crypt(pw, setting)
34
+ out = '*0'
35
+ out = '*1' if setting.start_with?(out)
36
+ iter = @itoa64.index(setting[3])
37
+ return out unless (8..30).include?(iter)
38
+ count = 1 << iter
39
+ salt = setting[4...12]
40
+ return out if salt.length != 8
41
+ hash = Digest::MD5.digest(salt + pw)
42
+ while count > 0
43
+ hash = Digest::MD5.digest(hash + pw)
44
+ count -= 1
45
+ end
46
+ setting[0,12] + encode64(hash, 16)
47
+ end
48
+
49
+ def encode64(input, count)
50
+ out = ''
51
+ cur = 0
52
+ while cur < count
53
+ value = input[cur].ord
54
+ cur += 1
55
+ out << @itoa64[value & 0x3f]
56
+ if cur < count
57
+ value |= input[cur].ord << 8
58
+ end
59
+ out << @itoa64[(value >> 6) & 0x3f]
60
+ break if cur >= count
61
+ cur += 1
62
+
63
+ if cur < count
64
+ value |= input[cur].ord << 16
65
+ end
66
+ out << @itoa64[(value >> 12) & 0x3f]
67
+ break if cur >= count
68
+ cur += 1
69
+ out << @itoa64[(value >> 18) & 0x3f]
70
+ end
71
+ out
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "PhpassRuby" do
4
+ before do
5
+ @ps = Phpass.new
6
+ @correct = 'test12345'
7
+ @wrong = 'test12346'
8
+ end
9
+
10
+ it 'should correct' do
11
+ hash = @ps.hash(@correct)
12
+ @ps.check(@correct, hash).should be_true
13
+ known = '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'
14
+ @ps.check(@correct, known).should be_true
15
+ @ps.check(@wrong, known).should be_false
16
+ end
17
+ end
18
+
19
+
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'phpass'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phpass-ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - uu59
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-14 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 1
31
+ - 0
32
+ version: 2.1.0
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: bundler
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 1
45
+ - 0
46
+ - 0
47
+ version: 1.0.0
48
+ type: :development
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: jeweler
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 1
60
+ - 5
61
+ - 1
62
+ version: 1.5.1
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: rcov
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ type: :development
77
+ version_requirements: *id004
78
+ description: phpass for ruby
79
+ email: a@tt25.org
80
+ executables: []
81
+
82
+ extensions: []
83
+
84
+ extra_rdoc_files:
85
+ - README.md
86
+ files:
87
+ - .document
88
+ - .rspec
89
+ - Gemfile
90
+ - README.md
91
+ - Rakefile
92
+ - lib/phpass.rb
93
+ - lib/phpass/md5.rb
94
+ - spec/phpass-ruby_spec.rb
95
+ - spec/spec_helper.rb
96
+ has_rdoc: true
97
+ homepage: http://github.com/tt25/phpass-ruby
98
+ licenses:
99
+ - MIT
100
+ post_install_message:
101
+ rdoc_options: []
102
+
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ requirements: []
122
+
123
+ rubyforge_project:
124
+ rubygems_version: 1.3.7
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: phpass for ruby
128
+ test_files:
129
+ - spec/phpass-ruby_spec.rb
130
+ - spec/spec_helper.rb