aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/luaossl.pdfbin281822 -> 282537 bytes
-rw-r--r--doc/luaossl.tex10
-rwxr-xr-xexamples/lm.hash71
3 files changed, 79 insertions, 2 deletions
diff --git a/doc/luaossl.pdf b/doc/luaossl.pdf
index 8078e4b..4237910 100644
--- a/doc/luaossl.pdf
+++ b/doc/luaossl.pdf
Binary files 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")))