1const INIT_A: u32 = 0x67452301;
28const INIT_B: u32 = 0xefcdab89;
29const INIT_C: u32 = 0x98badcfe;
30const INIT_D: u32 = 0x10325476;
31
32const SQRT_2: u32 = 0x5a827999;
33const SQRT_3: u32 = 0x6ed9eba1;
34
35const ITOA16: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
36
37pub fn ntlm_crypt(nt_buffer: [u32; 16]) -> [u32; 4]
39{
40 let mut a = INIT_A;
41 let mut b = INIT_B;
42 let mut c = INIT_C;
43 let mut d = INIT_D;
44
45 a = a.wrapping_add(d ^ (b & (c ^ d))).wrapping_add(nt_buffer[0]);a = (a << 3 ) | (a >> 29);
47 d = d.wrapping_add(c ^ (a & (b ^ c))).wrapping_add(nt_buffer[1]);d = (d << 7 ) | (d >> 25);
48 c = c.wrapping_add(b ^ (d & (a ^ b))).wrapping_add(nt_buffer[2]);c = (c << 11) | (c >> 21);
49 b = b.wrapping_add(a ^ (c & (d ^ a))).wrapping_add(nt_buffer[3]);b = (b << 19) | (b >> 13);
50
51 a = a.wrapping_add(d ^ (b & (c ^ d))).wrapping_add(nt_buffer[4]);a = (a << 3 ) | (a >> 29);
52 d = d.wrapping_add(c ^ (a & (b ^ c))).wrapping_add(nt_buffer[5]);d = (d << 7 ) | (d >> 25);
53 c = c.wrapping_add(b ^ (d & (a ^ b))).wrapping_add(nt_buffer[6]);c = (c << 11) | (c >> 21);
54 b = b.wrapping_add(a ^ (c & (d ^ a))).wrapping_add(nt_buffer[7]);b = (b << 19) | (b >> 13);
55
56 a = a.wrapping_add(d ^ (b & (c ^ d))).wrapping_add(nt_buffer[8]);a = (a << 3 ) | (a >> 29);
57 d = d.wrapping_add(c ^ (a & (b ^ c))).wrapping_add(nt_buffer[9]);d = (d << 7 ) | (d >> 25);
58 c = c.wrapping_add(b ^ (d & (a ^ b))).wrapping_add(nt_buffer[10]);c = (c << 11) | (c >> 21);
59 b = b.wrapping_add(a ^ (c & (d ^ a))).wrapping_add(nt_buffer[11]);b = (b << 19) | (b >> 13);
60
61 a = a.wrapping_add(d ^ (b & (c ^ d))).wrapping_add(nt_buffer[12]);a = (a << 3 ) | (a >> 29);
62 d = d.wrapping_add(c ^ (a & (b ^ c))).wrapping_add(nt_buffer[13]);d = (d << 7 ) | (d >> 25);
63 c = c.wrapping_add(b ^ (d & (a ^ b))).wrapping_add(nt_buffer[14]);c = (c << 11) | (c >> 21);
64 b = b.wrapping_add(a ^ (c & (d ^ a))).wrapping_add(nt_buffer[15]);b = (b << 19) | (b >> 13);
65
66
67 a = a.wrapping_add((b & (c | d)) | (c & d)).wrapping_add(nt_buffer[0]).wrapping_add(SQRT_2); a = (a<<3 ) | (a>>29);
69 d = d.wrapping_add((a & (b | c)) | (b & c)).wrapping_add(nt_buffer[4]).wrapping_add(SQRT_2); d = (d<<5 ) | (d>>27);
70 c = c.wrapping_add((d & (a | b)) | (a & b)).wrapping_add(nt_buffer[8]).wrapping_add(SQRT_2); c = (c<<9 ) | (c>>23);
71 b = b.wrapping_add((c & (d | a)) | (d & a)).wrapping_add(nt_buffer[12]).wrapping_add(SQRT_2); b = (b<<13) | (b>>19);
72
73 a = a.wrapping_add((b & (c | d)) | (c & d)).wrapping_add(nt_buffer[1]).wrapping_add(SQRT_2); a = (a<<3 ) | (a>>29);
74 d = d.wrapping_add((a & (b | c)) | (b & c)).wrapping_add(nt_buffer[5]).wrapping_add(SQRT_2); d = (d<<5 ) | (d>>27);
75 c = c.wrapping_add((d & (a | b)) | (a & b)).wrapping_add(nt_buffer[9]).wrapping_add(SQRT_2); c = (c<<9 ) | (c>>23);
76 b = b.wrapping_add((c & (d | a)) | (d & a)).wrapping_add(nt_buffer[13]).wrapping_add(SQRT_2); b = (b<<13) | (b>>19);
77
78 a = a.wrapping_add((b & (c | d)) | (c & d)).wrapping_add(nt_buffer[2]).wrapping_add(SQRT_2); a = (a<<3 ) | (a>>29);
79 d = d.wrapping_add((a & (b | c)) | (b & c)).wrapping_add(nt_buffer[6]).wrapping_add(SQRT_2); d = (d<<5 ) | (d>>27);
80 c = c.wrapping_add((d & (a | b)) | (a & b)).wrapping_add(nt_buffer[10]).wrapping_add(SQRT_2); c = (c<<9 ) | (c>>23);
81 b = b.wrapping_add((c & (d | a)) | (d & a)).wrapping_add(nt_buffer[14]).wrapping_add(SQRT_2); b = (b<<13) | (b>>19);
82
83 a = a.wrapping_add((b & (c | d)) | (c & d)).wrapping_add(nt_buffer[3]).wrapping_add(SQRT_2); a = (a<<3 ) | (a>>29);
84 d = d.wrapping_add((a & (b | c)) | (b & c)).wrapping_add(nt_buffer[7]).wrapping_add(SQRT_2); d = (d<<5 ) | (d>>27);
85 c = c.wrapping_add((d & (a | b)) | (a & b)).wrapping_add(nt_buffer[11]).wrapping_add(SQRT_2); c = (c<<9 ) | (c>>23);
86 b = b.wrapping_add((c & (d | a)) | (d & a)).wrapping_add(nt_buffer[15]).wrapping_add(SQRT_2); b = (b<<13) | (b>>19);
87
88
89 a = a.wrapping_add(d ^ c ^ b).wrapping_add(nt_buffer[0]).wrapping_add(SQRT_3); a = (a << 3 ) | (a >> 29);
91 d = d.wrapping_add(c ^ b ^ a).wrapping_add(nt_buffer[8]).wrapping_add(SQRT_3); d = (d << 9 ) | (d >> 23);
92 c = c.wrapping_add(b ^ a ^ d).wrapping_add(nt_buffer[4]).wrapping_add(SQRT_3); c = (c << 11) | (c >> 21);
93 b = b.wrapping_add(a ^ d ^ c).wrapping_add(nt_buffer[12]).wrapping_add(SQRT_3); b = (b << 15) | (b >> 17);
94
95 a = a.wrapping_add(d ^ c ^ b).wrapping_add(nt_buffer[2]).wrapping_add(SQRT_3); a = (a << 3 ) | (a >> 29);
96 d = d.wrapping_add(c ^ b ^ a).wrapping_add(nt_buffer[10]).wrapping_add(SQRT_3); d = (d << 9 ) | (d >> 23);
97 c = c.wrapping_add(b ^ a ^ d).wrapping_add(nt_buffer[6]).wrapping_add(SQRT_3); c = (c << 11) | (c >> 21);
98 b = b.wrapping_add(a ^ d ^ c).wrapping_add(nt_buffer[14]).wrapping_add(SQRT_3); b = (b << 15) | (b >> 17);
99
100 a = a.wrapping_add(d ^ c ^ b).wrapping_add(nt_buffer[1]).wrapping_add(SQRT_3); a = (a << 3 ) | (a >> 29);
101 d = d.wrapping_add(c ^ b ^ a).wrapping_add(nt_buffer[9]).wrapping_add(SQRT_3); d = (d << 9 ) | (d >> 23);
102 c = c.wrapping_add(b ^ a ^ d).wrapping_add(nt_buffer[5]).wrapping_add(SQRT_3); c = (c << 11) | (c >> 21);
103 b = b.wrapping_add(a ^ d ^ c).wrapping_add(nt_buffer[13]).wrapping_add(SQRT_3); b = (b << 15) | (b >> 17);
104
105 a = a.wrapping_add(d ^ c ^ b).wrapping_add(nt_buffer[3]).wrapping_add(SQRT_3); a = (a << 3 ) | (a >> 29);
106 d = d.wrapping_add(c ^ b ^ a).wrapping_add(nt_buffer[11]).wrapping_add(SQRT_3); d = (d << 9 ) | (d >> 23);
107 c = c.wrapping_add(b ^ a ^ d).wrapping_add(nt_buffer[7]).wrapping_add(SQRT_3); c = (c << 11) | (c >> 21);
108 b = b.wrapping_add(a ^ d ^ c).wrapping_add(nt_buffer[15]).wrapping_add(SQRT_3); b = (b << 15) | (b >> 17);
109
110 [a.wrapping_add(INIT_A), b.wrapping_add(INIT_B), c.wrapping_add(INIT_C), d.wrapping_add(INIT_D)]
111}
112
113pub fn prepare_key(key: &[u8]) -> [u32; 16]
116{
117 let mut nt_buffer = [0u32; 16];
118 let length = key.len() as u32;
119 for i in 0..16 {
120 nt_buffer[i] = 0;
121 }
122 for i in 0usize..(length/2) as usize {
124 nt_buffer[i] = key[2*i] as u32 | ((key[2*i+1] as u32) << 16);
125 }
126
127 let i = (length/2) as usize;
128 if length % 2 == 1 {
130 nt_buffer[i] = key[(length-1) as usize] as u32 | 0x800000;
131 }
132 else {
133 nt_buffer[i]=0x80;
134 }
135 nt_buffer[14] = length << 4;
137 nt_buffer
138}
139
140pub fn convert_hex(output: &mut [u32; 4]) -> String
142{
143 let mut hex_format: [char; 32] = [' '; 32];
144 for i in 0..4
146 {
147 let mut n: u32 = output[i];
148 for j in 0..4
150 {
151 let mut convert = n % 256;
152 hex_format[i*8+j*2+1] = ITOA16[(convert%16) as usize];
153 convert = convert/16;
154 hex_format[i*8+j*2+0] = ITOA16[(convert%16) as usize];
155 n /= 256;
156 }
157 }
158 let mut out = String::new();
159 hex_format.iter().for_each(|&c| out.push(c));
160 out
161}
162
163pub fn ntlm_hash(s: &str) -> String {
165 convert_hex(&mut ntlm_crypt(prepare_key(s.as_bytes())))
166}
167
168#[test]
169fn limit() {
170 println!("{}", ntlm_hash("0123456789012345678901234567890"));
171}