smbhash 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.
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ script: rake test
3
+ rvm:
4
+ - ruby-head
5
+ - 2.1.1
6
+ - 2.0.0
7
+ - 1.9.3
8
+ - 1.9.2
9
+ - 1.8.7
10
+
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # ruby-smbhash
2
+ [![Build Status](https://travis-ci.org/krissi/ruby-smbhash.svg?branch=master)](https://travis-ci.org/krissi/ruby-smbhash)
3
+
4
+ ## Description
5
+ ruby-smbhash is a implementation of lanman and nt md4 hash functions for use in Samba style smbpasswd entries. It was stripped from ActiveSambaLDAP (http://asl.rubyforge.org/activesambaldap/)
6
+
7
+ ## Tested Ruby Versions
8
+ * MRI 1.8.6
9
+ * MRI 1.9.2
10
+ * MRI 1.9.3
11
+ * MRI 2.0.0
12
+ * MRI 2.1.1
13
+
14
+ ## Usage
15
+ require 'samba/encrypt'
16
+
17
+ Samba::Encrypt.lm_hash "password"
18
+ => "E52CAC67419A9A224A3B108F3FA6CB6D"
19
+
20
+ Samba::Encrypt.ntlm_hash "password"
21
+ => "8846F7EAEE8FB117AD06BDD830B7586C"
22
+
23
+ Samba::Encrypt.ntlmgen "password"
24
+ => ["E52CAC67419A9A224A3B108F3FA6CB6D", "8846F7EAEE8FB117AD06BDD830B7586C"]
25
+
26
+ ## Credits
27
+ * ActiveSambaLDAP project for sharing the code
28
+ * jon-mercer for porting it to ruby 1.9
29
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'rubygems'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/test_*.rb']
9
+ t.verbose = false
10
+ end
11
+
@@ -0,0 +1,32 @@
1
+ module Smbhash
2
+ module Methods18
3
+ require 'iconv'
4
+
5
+ def str_to_key(str)
6
+ key = "\000" * 8
7
+ key[0] = str[0] >> 1;
8
+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
9
+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
10
+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
11
+ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
12
+ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
13
+ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
14
+ key[7] = str[6] & 0x7F;
15
+
16
+ key.size.times do |i|
17
+ key[i] = (key[i] << 1);
18
+ end
19
+
20
+ key
21
+ end
22
+
23
+ def convert_encoding(to, from, str)
24
+ if same_encoding?(to, from)
25
+ str
26
+ else
27
+ Iconv.iconv(to, from, str).join
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module Smbhash
2
+ module Methods19
3
+ def str_to_key(str)
4
+ key = "\000" * 8
5
+ key.setbyte(0, str.getbyte(0) >> 1);
6
+ key.setbyte(1, ((str.getbyte(0) & 0x01) << 6) | (str.getbyte(1) >> 2));
7
+ key.setbyte(2, ((str.getbyte(1) & 0x03) << 5) | (str.getbyte(2) >> 3));
8
+ key.setbyte(3, ((str.getbyte(2) & 0x07) << 4) | (str.getbyte(3) >> 4));
9
+ key.setbyte(4, ((str.getbyte(3) & 0x0F) << 3) | (str.getbyte(4) >> 5));
10
+ key.setbyte(5, ((str.getbyte(4) & 0x1F) << 2) | (str.getbyte(5) >> 6));
11
+ key.setbyte(6, ((str.getbyte(5) & 0x3F) << 1) | (str.getbyte(6) >> 7));
12
+ key.setbyte(7, str.getbyte(6) & 0x7F);
13
+
14
+ key.size.times do |i|
15
+ key.setbyte(i, (key.getbyte(i) << 1));
16
+ end
17
+
18
+ key
19
+ end
20
+
21
+ def convert_encoding(to, from, str)
22
+ if same_encoding?(to, from)
23
+ str
24
+ else
25
+ str.encode(to, from)
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/smbhash.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'openssl'
2
+
3
+ module Smbhash
4
+ module_function
5
+ def lm_hash(password, encoding=nil)
6
+ dos_password = Private.convert_encoding("ISO-8859-1",
7
+ encoding || "UTF-8",
8
+ password.upcase)
9
+ if dos_password.size > 14
10
+ warn("password is truncated to 14 characters")
11
+ dos_password = dos_password[0, 14]
12
+ end
13
+ Private.encrypt_14characters(dos_password).unpack("C*").collect do |char|
14
+ "%02X" % char
15
+ end.join
16
+ end
17
+
18
+ def ntlm_hash(password, encoding=nil)
19
+ ucs2_password = Private.convert_encoding("UTF-16LE",
20
+ encoding || "UTF-8",
21
+ password)
22
+ if ucs2_password.size > 256
23
+ raise ArgumentError.new("must be <= 256 characters in UTF-16LE")
24
+ end
25
+ hex = OpenSSL::Digest::MD4.new(ucs2_password).hexdigest.upcase
26
+ hex
27
+ end
28
+
29
+ def ntlmgen(password, encoding=nil)
30
+ [
31
+ lm_hash(password, encoding),
32
+ ntlm_hash(password, encoding)
33
+ ]
34
+ end
35
+
36
+ module Private
37
+ module_function
38
+
39
+ case RUBY_VERSION
40
+ when /^1\.9/, /^2/
41
+ require "smbhash/methods19"
42
+ extend Methods19
43
+ when /^1\.8/
44
+ require "smbhash/methods18"
45
+ extend Methods18
46
+ else
47
+ raise NotImplementedError, "Ruby #{RUBY_VERSION} is not supported"
48
+ end
49
+
50
+ def normalize_encoding(encoding)
51
+ encoding.downcase.gsub(/-/, "_")
52
+ end
53
+
54
+ def same_encoding?(a, b)
55
+ na = normalize_encoding(a)
56
+ nb = normalize_encoding(b)
57
+ na == nb or na.gsub(/_/, '') == nb.gsub(/_/, '')
58
+ end
59
+
60
+ def des_crypt56(input, key_str, forward_only)
61
+ key = str_to_key(key_str)
62
+ encoder = OpenSSL::Cipher::DES.new
63
+ encoder.encrypt
64
+ encoder.key = key
65
+ encoder.update(input)
66
+ end
67
+
68
+ LM_MAGIC = "KGS!@\#$%"
69
+ def encrypt_14characters(chars)
70
+ raise ArgumentError.new("must be <= 14 characters") if chars.size > 14
71
+ chars = chars.to_s.ljust(14, "\000")
72
+ des_crypt56(LM_MAGIC, chars[0, 7], true) +
73
+ des_crypt56(LM_MAGIC, chars[7, 7], true)
74
+ end
75
+ end
76
+ end
data/smbhash.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'smbhash'
4
+ s.version = '1.0.0'
5
+ s.license = 'MIT'
6
+ s.summary = "Lanman/NT hash generator"
7
+ s.description = "An implementation of lanman and nt md4 hash functions for use in Samba style smbpasswd entries"
8
+ s.homepage = 'https://github.com/krissi/ruby-smbhash'
9
+ s.author = 'Christian Haase'
10
+
11
+ s.files = `git ls-files`.split($/)
12
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
13
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
14
+ s.require_paths = ["lib"]
15
+
16
+ s.required_ruby_version = '>= 1.8.7'
17
+
18
+ s.add_development_dependency "rake"
19
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/unit'
2
+ require 'stringio'
3
+ require 'smbhash'
4
+
5
+ class SambaEncryptTest < Test::Unit::TestCase
6
+ def test_lm_hash
7
+ assert_equal("E52CAC67419A9A224A3B108F3FA6CB6D",
8
+ Smbhash.lm_hash("password"))
9
+ assert_equal("E52CAC67419A9A224A3B108F3FA6CB6D",
10
+ Smbhash.lm_hash("paSSWOrd"))
11
+ assert_equal("E0C510199CC66ABDE0C510199CC66ABD",
12
+ Smbhash.lm_hash("abcdefgabcdefg"))
13
+ assert_equal("FF3750BCC2B22412C2265B23734E0DAC",
14
+ Smbhash.lm_hash("SecREt01"))
15
+ begin
16
+ stderr = $stderr
17
+ $stderr = StringIO.new
18
+ assert_equal("E0C510199CC66ABDE0C510199CC66ABD",
19
+ Smbhash.lm_hash("abcdefgabcdefg" + "X"))
20
+ assert_equal("E0C510199CC66ABDE0C510199CC66ABD",
21
+ Smbhash.lm_hash("abcdefgabcdefg" + "X" * 100))
22
+ assert_equal("password is truncated to 14 characters\n" * 2,
23
+ $stderr.string)
24
+ ensure
25
+ $stderr = stderr
26
+ end
27
+ end
28
+
29
+ def test_ntlm_hash
30
+ assert_equal("8846F7EAEE8FB117AD06BDD830B7586C",
31
+ Smbhash.ntlm_hash("password"))
32
+ end
33
+
34
+ def test_ntlmgen
35
+ assert_equal(["E52CAC67419A9A224A3B108F3FA6CB6D", "8846F7EAEE8FB117AD06BDD830B7586C"],
36
+ Smbhash.ntlmgen("password"))
37
+ end
38
+
39
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smbhash
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christian Haase
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &20347200 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *20347200
25
+ description: An implementation of lanman and nt md4 hash functions for use in Samba
26
+ style smbpasswd entries
27
+ email:
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .travis.yml
33
+ - README.md
34
+ - Rakefile
35
+ - lib/smbhash.rb
36
+ - lib/smbhash/methods18.rb
37
+ - lib/smbhash/methods19.rb
38
+ - smbhash.gemspec
39
+ - test/test_samba_encrypt.rb
40
+ homepage: https://github.com/krissi/ruby-smbhash
41
+ licenses:
42
+ - MIT
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: 1.8.7
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 1.8.15
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Lanman/NT hash generator
65
+ test_files:
66
+ - test/test_samba_encrypt.rb