From 7dce9c391259f1b72f949f73ac1604d6fcb79fdd Mon Sep 17 00:00:00 2001 From: william Date: Wed, 25 Feb 2015 14:58:33 -0800 Subject: document des.set_odd_parity and add example --- doc/luaossl.pdf | Bin 281822 -> 282537 bytes doc/luaossl.tex | 10 ++++++-- examples/lm.hash | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100755 examples/lm.hash diff --git a/doc/luaossl.pdf b/doc/luaossl.pdf index 8078e4b..4237910 100644 Binary files a/doc/luaossl.pdf and b/doc/luaossl.pdf differ diff --git a/doc/luaossl.tex b/doc/luaossl.tex index 239c98a..2302e3a 100644 --- a/doc/luaossl.tex +++ b/doc/luaossl.tex @@ -985,11 +985,17 @@ The routine operates internally on 64-bit unsigned integers.\footnote{Actually, \begin{Module}{openssl.des} -Binds OpenSSL's DES interfaces. These bindings are incomplete. No modern protocol would ever need to use these directly. However, legacy protocols like Windows NTLM authentication require some of these low-level interfaces. +Binds OpenSSL's DES interfaces. These bindings are incomplete. No modern protocol would ever need to use these directly. However, legacy protocols like Windows LAN Manager authentication require some of these low-level interfaces. \subsubsection[\fn{des.string\_to\_key}]{\fn{des.string\_to\_key($password$)}} -Converts an arbitrary length string, $password$, to a DES key. Returns an 8-byte string. +Converts an arbitrary length string, $password$, to a DES key using DES\_string\_to\_key. Returns an 8-byte string. + +Note that OpenSSL's DES\_string\_to\_key is not compatible with Windows LAN Manager hashing scheme. Use \fn{des.set\_odd\_parity} instead. See examples/lm.hash. + +\subsubsection[\fn{des.set\_odd\_parity}]{\fn{des.set\_odd\_parity($key$)}} + +Applies DES\_set\_odd\_parity to the string $key$. Only the first 8 bytes of $key$ are processed. Returns an 8-byte string. \end{Module} diff --git a/examples/lm.hash b/examples/lm.hash new file mode 100755 index 0000000..4d8157c --- /dev/null +++ b/examples/lm.hash @@ -0,0 +1,71 @@ +#!/bin/sh +_=[[ + : ${LUA:=$(command -v lua-5.2)} + : ${LUA:=$(command -v lua5.2)} + : ${LUA:=$(command -v lua-52)} + : ${LUA:=$(command -v lua52)} + : ${LUA:=$(command -v luajit)} + : ${LUA:=$(command -v lua)} + + exec ${LUA} "$0" "$@" +]] + +local des = require"openssl.des" +local cipher = require"openssl.cipher" +local bit32 = require"bit32" + +local function lm_encrypt(key) + return cipher.new"DES-ECB":encrypt(key, nil, false):final"KGS!@#$%" +end -- lm_encrypt + +local lshift = bit32.lshift +local band = bit32.band +local rshift = bit32.rshift +local bor = bit32.bor + +local function lm_string_to_key(s) + local s0, s1, s2, s3, s4, s5, s6 = string.byte(s, 1, 7) + local k0, k1, k2, k3, k4, k5, k6, k7 + + s0 = s0 or 0 + s1 = s1 or 0 + s2 = s2 or 0 + s3 = s3 or 0 + s4 = s4 or 0 + s5 = s5 or 0 + s6 = s6 or 0 + + k0 = s0 + k1 = bor(band(lshift(s0, 7), 255), rshift(s1, 1)) + k2 = bor(band(lshift(s1, 6), 255), rshift(s2, 2)) + k3 = bor(band(lshift(s2, 5), 255), rshift(s3, 3)) + k4 = bor(band(lshift(s3, 4), 255), rshift(s4, 4)) + k5 = bor(band(lshift(s4, 3), 255), rshift(s5, 5)) + k6 = bor(band(lshift(s5, 2), 255), rshift(s6, 6)) + k7 = band(lshift(s6, 1), 255) + + return des.set_odd_parity(string.char(k0, k1, k2, k3, k4, k5, k6, k7)) +end -- lm_string_to_key + +local function lm_hash(pass) + pass = string.upper(pass) + + if #pass < 14 then + pass = pass .. string.rep(string.char(0), 14 - #pass) + end + + local key1 = lm_string_to_key(string.sub(pass, 1, 7)) + local key2 = lm_string_to_key(string.sub(pass, 8, 14)) + + return lm_encrypt(key1) .. lm_encrypt(key2) +end -- lm_hash + +local function tohex(s) + return (string.gsub(s, ".", function (c) + return string.format("%.2x", string.byte(c)) + end)) +end -- tohex + +local pass = ... or "passphrase" + +print(pass, tohex(lm_hash(... or "passphrase"))) -- cgit v1.2.3-59-g8ed1b