cram_md5 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +38 -0
- data/README.md +34 -0
- data/Rakefile +2 -0
- data/cram_md5.gemspec +29 -0
- data/lib/cram_md5/version.rb +3 -0
- data/lib/cram_md5.rb +129 -0
- metadata +78 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Copyright (c) 2012 Thiago Coutinho
|
2
|
+
|
3
|
+
Written by
|
4
|
+
|
5
|
+
- Thiago Coutinho <thiago@osfeio.com>
|
6
|
+
|
7
|
+
Based on
|
8
|
+
|
9
|
+
- perl's Crypt::PasswdMD5 by Luis Munoz (lem@cantv.net)
|
10
|
+
- phyton's md5crypt.py by Michal Wallace http://www.sabren.com/
|
11
|
+
- /usr/src/libcrypt/crypt.c from FreeBSD 2.2.5-RELEASE
|
12
|
+
Many thanks to
|
13
|
+
- Ricardo Perez <riperezzz@gmail.com>
|
14
|
+
|
15
|
+
Version: 1.0 stable
|
16
|
+
Last edit: Tue, 13 September 2012 17:05:28 -0300 GMT
|
17
|
+
(after 7 years of phyton version... \o/ happy Birthday \o/)
|
18
|
+
|
19
|
+
USAGE
|
20
|
+
|
21
|
+
cryptedpassword = CramMd5::md5crypt_unix (password [, salt [, magicstring ])
|
22
|
+
apachepassword = CramMd5::md5crypt_apache (password [, salt])
|
23
|
+
|
24
|
+
DESCRIPTION
|
25
|
+
|
26
|
+
unix_md5_crypt() provides a crypt()-compatible interface to the
|
27
|
+
rather old MD5-based crypt() function found in modern operating systems
|
28
|
+
using old and solid libs.
|
29
|
+
|
30
|
+
It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and
|
31
|
+
contains the following license in it:
|
32
|
+
|
33
|
+
"THE BEER-WARE LICENSE" (Revision 42):
|
34
|
+
<thiago@osfeio.com> wrote this file based on the other descriptions. As long as
|
35
|
+
you retain this notice you can do whatever you want with this stuff. If we meet
|
36
|
+
some day, and you think this stuff is worth it, you can buy me a beer in return.
|
37
|
+
|
38
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# CramMd5
|
2
|
+
|
3
|
+
unix_md5_crypt() provides a crypt()-compatible interface to the
|
4
|
+
rather old MD5-based crypt() function found in modern operating systems
|
5
|
+
using old and solid libs.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'cram_md5'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install cram_md5
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
cryptedpassword = CramMd5::md5crypt_unix (password [, salt [, magicstring ])
|
24
|
+
|
25
|
+
apachepassword = CramMd5::md5crypt_apache (password [, salt])
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
1. Fork it
|
30
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
32
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
33
|
+
5. Create new Pull Request
|
34
|
+
6. Execure the "THE BEER-WARE LICENSE".
|
data/Rakefile
ADDED
data/cram_md5.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/cram_md5/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Thiago Coutinho"]
|
6
|
+
gem.email = ["thiago.coutinho@locaweb.com.br"]
|
7
|
+
gem.description = %q{
|
8
|
+
unix_md5_crypt() provides a crypt()-compatible interface to the
|
9
|
+
rather old MD5-based crypt() function found in modern operating systems
|
10
|
+
using old and solid libs.}
|
11
|
+
gem.summary = %q{ unix_md5_crypt CRAM-MD5 or Crypt MD5 }
|
12
|
+
gem.homepage = ""
|
13
|
+
|
14
|
+
gem.files = [
|
15
|
+
"Gemfile",
|
16
|
+
"LICENSE",
|
17
|
+
"README.md",
|
18
|
+
"Rakefile",
|
19
|
+
"cram_md5.gemspec",
|
20
|
+
"lib/cram_md5.rb",
|
21
|
+
"lib/cram_md5/version.rb"
|
22
|
+
]
|
23
|
+
|
24
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
25
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
26
|
+
gem.name = "cram_md5"
|
27
|
+
gem.require_paths = ["lib"]
|
28
|
+
gem.version = CramMd5::VERSION
|
29
|
+
end
|
data/lib/cram_md5.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
module CramMd5
|
5
|
+
MAGIC = '$1$'
|
6
|
+
ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
7
|
+
|
8
|
+
def self.to64(v, n)
|
9
|
+
ret = ''
|
10
|
+
while (n - 1 >= 0)
|
11
|
+
n = n - 1
|
12
|
+
|
13
|
+
ret = ret + ITOA64[v & 0x3f]
|
14
|
+
v = v >> 6
|
15
|
+
end
|
16
|
+
ret
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.apache_md5_crypt (pw, salt)
|
20
|
+
self.unix_md5_crypt(pw, salt, '$apr1$')
|
21
|
+
end
|
22
|
+
|
23
|
+
#@params [string] password
|
24
|
+
#@params [string] salt
|
25
|
+
#@params [string] magic
|
26
|
+
#@note For compare, use de original password and the salt of encrypted password.
|
27
|
+
#@return [string] crypt pass
|
28
|
+
|
29
|
+
def self.unix_md5_crypt(pw, salt="", magic=nil)
|
30
|
+
|
31
|
+
if magic==nil
|
32
|
+
magic = MAGIC
|
33
|
+
end
|
34
|
+
|
35
|
+
# Take care of the magic string if present
|
36
|
+
salt = salt[magic.length..-1] if salt[0..magic.length-1] == magic
|
37
|
+
|
38
|
+
# salt can have up to 8 characters:
|
39
|
+
salt = salt[0..7]
|
40
|
+
salt = rand_str(8) if salt == ""
|
41
|
+
|
42
|
+
ctx = pw + magic + salt
|
43
|
+
|
44
|
+
final = Digest::MD5.digest(pw + salt + pw)
|
45
|
+
|
46
|
+
pl = pw.length
|
47
|
+
while(pl>0)
|
48
|
+
if pl > 16
|
49
|
+
ctx = ctx + final[0..15]
|
50
|
+
else
|
51
|
+
ctx = ctx + final[0..pl-1]
|
52
|
+
end
|
53
|
+
pl -= 16
|
54
|
+
end
|
55
|
+
# Now the 'weird' xform (??)
|
56
|
+
|
57
|
+
i = pw.length
|
58
|
+
while(i>0)
|
59
|
+
if (i & 1) > 0
|
60
|
+
ctx = ctx + 0.chr #if ($i & 1) { $ctx->add(pack("C", 0)); }
|
61
|
+
else
|
62
|
+
ctx = ctx + pw[0]
|
63
|
+
end
|
64
|
+
i = i >> 1
|
65
|
+
end
|
66
|
+
|
67
|
+
final = Digest::MD5.digest(ctx)
|
68
|
+
|
69
|
+
# The following is supposed to make
|
70
|
+
# things run slower.
|
71
|
+
|
72
|
+
# my question: WTF???
|
73
|
+
|
74
|
+
(0..999).each do |i|
|
75
|
+
ctx1 = ''
|
76
|
+
if (i & 1) > 0
|
77
|
+
ctx1 = ctx1 + pw
|
78
|
+
else
|
79
|
+
ctx1 = ctx1 + final[0..15]
|
80
|
+
end
|
81
|
+
|
82
|
+
ctx1 = ctx1 + salt if (i % 3) > 0
|
83
|
+
|
84
|
+
|
85
|
+
ctx1 = ctx1 + pw if (i % 7) > 0
|
86
|
+
|
87
|
+
if (i & 1) > 0
|
88
|
+
ctx1 = ctx1 + final[0..15]
|
89
|
+
else
|
90
|
+
ctx1 = ctx1 + pw
|
91
|
+
end
|
92
|
+
|
93
|
+
final = Digest::MD5.digest(ctx1)
|
94
|
+
end
|
95
|
+
# Final xform
|
96
|
+
|
97
|
+
passwd = ''
|
98
|
+
|
99
|
+
passwd = passwd + self.to64( (final[0].ord.to_i << 16)|(final[6].ord.to_i << 8)|(final[12].ord.to_i),4)
|
100
|
+
|
101
|
+
passwd = passwd + self.to64((final[1].ord.to_i << 16)|(final[7].ord.to_i << 8)|(final[13].ord.to_i), 4)
|
102
|
+
|
103
|
+
passwd = passwd + self.to64((final[2].ord.to_i << 16)|(final[8].ord.to_i << 8)|(final[14].ord.to_i), 4)
|
104
|
+
|
105
|
+
passwd = passwd + self.to64((final[3].ord.to_i << 16)|(final[9].ord.to_i << 8)|(final[15].ord.to_i), 4)
|
106
|
+
|
107
|
+
passwd = passwd + self.to64((final[4].ord.to_i << 16)|(final[10].ord.to_i << 8)|(final[5].ord.to_i), 4)
|
108
|
+
|
109
|
+
passwd = passwd + self.to64((final[11].ord.to_i), 2)
|
110
|
+
|
111
|
+
magic + salt + '$' + passwd
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.rand_str(max_length = 32, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890')
|
115
|
+
|
116
|
+
chars_length = (chars.length - 1);
|
117
|
+
|
118
|
+
string = chars[rand(chars_length)];
|
119
|
+
i=0
|
120
|
+
while(string.length<max_length)
|
121
|
+
c = chars[rand(chars_length)];
|
122
|
+
|
123
|
+
string += c if (c != string[string.length - 1])
|
124
|
+
end
|
125
|
+
|
126
|
+
string
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cram_md5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Thiago Coutinho
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-09-25 00:00:00 -03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: |-
|
23
|
+
|
24
|
+
unix_md5_crypt() provides a crypt()-compatible interface to the
|
25
|
+
rather old MD5-based crypt() function found in modern operating systems
|
26
|
+
using old and solid libs.
|
27
|
+
email:
|
28
|
+
- thiago.coutinho@locaweb.com.br
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- Gemfile
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- cram_md5.gemspec
|
41
|
+
- lib/cram_md5.rb
|
42
|
+
- lib/cram_md5/version.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: ""
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
hash: 3
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.7
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: unix_md5_crypt CRAM-MD5 or Crypt MD5
|
77
|
+
test_files: []
|
78
|
+
|