Module: NTLM::Util

Included in:
Message
Defined in:
lib/ntlm/util.rb

Constant Summary collapse

LM_MAGIC_TEXT =
'KGS!@#$%'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create_des_keys(string) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ntlm/util.rb', line 36

def create_des_keys(string)
  keys = []
  string = string.dup
  until (key = string.slice!(0, 7)).empty?
    # key is 56 bits
    key = key.unpack('B*').first
    str = ''
    until (bits = key.slice!(0, 7)).empty?
      str << bits
      str << (bits.count('1').even? ? '1' : '0')  # parity
    end
    keys << [str].pack('B*')
  end
  keys
end

.encrypt(plain_text, key, key_length) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/ntlm/util.rb', line 52

def encrypt(plain_text, key, key_length)
  key = key.ljust(key_length, "\0")
  keys = create_des_keys(key[0, key_length])

  result = ''
  cipher = OpenSSL::Cipher::DES.new
  keys.each do |k|
    cipher.encrypt
    cipher.key = k
    result << cipher.update(plain_text)
  end

  result
end

.lm_v1_hash(password) ⇒ Object

MS-NLMP

3.3.1



68
69
70
# File 'lib/ntlm/util.rb', line 68

def lm_v1_hash(password)
  encrypt(LM_MAGIC_TEXT, password.upcase, 14)
end

.nt_v1_hash(password) ⇒ Object

MS-NLMP

3.3.1



73
74
75
# File 'lib/ntlm/util.rb', line 73

def nt_v1_hash(password)
  OpenSSL::Digest::MD4.digest(encode_utf16(password))
end

.nt_v2_hash(user, password, domain) ⇒ Object

MS-NLMP

3.3.2



94
95
96
97
# File 'lib/ntlm/util.rb', line 94

def nt_v2_hash(user, password, domain)
  user_domain = encode_utf16(user.upcase + domain)
  OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, nt_v1_hash(password), user_domain)
end

.ntlm_v1_response(challenge, password, options = {}) ⇒ Object

MS-NLMP

3.3.1



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ntlm/util.rb', line 78

def ntlm_v1_response(challenge, password, options = {})
  if options[:ntlm_v2_session]
    client_challenge = options[:client_challenge] || OpenSSL::Random.random_bytes(8)
    hash = OpenSSL::Digest::MD5.digest(challenge + client_challenge)[0, 8]
    nt_response = encrypt(hash, nt_v1_hash(password), 21)
    lm_response = client_challenge + ("\0" * 16)
  else
    nt_response = encrypt(challenge, nt_v1_hash(password), 21)
    lm_response = encrypt(challenge, lm_v1_hash(password), 21)
  end

  [nt_response, lm_response]
end

.ntlm_v2_responseObject

MS-NLMP

3.3.2

Raises:

  • (NotImplemnetedError)


100
101
102
# File 'lib/ntlm/util.rb', line 100

def ntlm_v2_response(*)
  raise NotImplemnetedError
end

Instance Method Details

#decode_utf16(str) ⇒ Object



14
15
16
# File 'lib/ntlm/util.rb', line 14

def decode_utf16(str)
  str.encode(Encoding::UTF_8, Encoding::UTF_16LE)
end

#encode_utf16(str) ⇒ Object



18
19
20
# File 'lib/ntlm/util.rb', line 18

def encode_utf16(str)
  str.to_s.encode(Encoding::UTF_16LE).force_encoding(Encoding::ASCII_8BIT)
end