2 # Samba LM/NT Hash Generating Library.
3 # Slightly modified to fit in with Webmin
5 # Copyright(C) 2001 Benjamin Kuit <bj@it.uts.edu.au>
8 # Works out if local system has the module Digest::MD4, and uses it
9 # if it does, otherwise uses ported version of the md4 algorithm
10 # Performance is alot better with Digest::MD4, so its recommended to
11 # get Digest::MD4 installed if you intend to generate alot of hashes
12 # in a small amount of time.
17 if ( eval "require 'Digest/MD4.pm';" ) {
23 # Generates lanman password hash for a given password, returns the hash
25 # Extracted and ported from SAMBA/source/libsmb/smbencrypt.c:nt_lm_owf_gen
30 $pass = substr($pass||"",0,129);
32 $pass = substr($pass,0,14);
34 return join("", map {sprintf("%02X",$_);} @p16);
38 # Generates nt md4 password hash for a given password, returns the hash
40 # Extracted and ported from SAMBA/source/libsmb/smbencrypt.c:nt_lm_owf_gen
45 $pass = substr($pass||"",0,128);
46 $pass =~ s/(.)/$1\000/sg;
48 if ( $HaveDigestMD4 ) {
50 $digest = new Digest::MD4;
53 $hex = $digest->hexdigest();
56 $HaveDigestMD4 = 0 unless ( $hex );
58 $hex = sprintf("%02X"x16,mdfour($pass)) unless ( $hex );
62 # ntlmgen PASSWORD, LMHASH, NTHASH
63 # Generate lanman and nt md4 password hash for given password, and assigns
64 # values to arguments. Combined function of lmhash and nthash
66 my ( $nthash, $lmhash );
67 $nthash = nthash($_[0]);
68 $lmhash = lmhash($_[0]);
73 return ( $lmhash, $nthash );
77 # Ported from SAMBA/source/lib/md4.c:F,G and H respectfully
78 sub F { my ( $X, $Y, $Z ) = @_; return ($X&$Y) | ((~$X)&$Z); }
79 sub G { my ( $X, $Y, $Z) = @_; return ($X&$Y) | ($X&$Z) | ($Y&$Z); }
80 sub H { my ($X, $Y, $Z) = @_; return $X^$Y^$Z; }
82 # Needed? because perl seems to choke on overflowing when doing bitwise
83 # operations on numbers larger than 32 bits. Well, it did on my machine =)
88 $_ = [ ($_&0xffff0000)>>16, ($_&0xffff) ];
95 $sum[0] += ($sum[1]&0xffff0000)>>16;
98 $ret = ($sum[0]<<16) | $sum[1];
101 # Ported from SAMBA/source/lib/md4.c:lshift
102 # Renamed to prevent clash with SAMBA/source/libsmb/smbdes.c:lshift
106 return (($x<<$s)&0xFFFFFFFF) | ($x>>(32-$s));
108 # Ported from SAMBA/source/lib/md4.c:ROUND1
110 my($a,$b,$c,$d,$k,$s,@X) = @_;
111 $_[0] = md4lshift(add32($a,F($b,$c,$d),$X[$k]), $s);
114 # Ported from SAMBA/source/lib/md4.c:ROUND2
116 my ($a,$b,$c,$d,$k,$s,@X) = @_;
117 $_[0] = md4lshift(add32($a,G($b,$c,$d),$X[$k],0x5A827999), $s);
120 # Ported from SAMBA/source/lib/md4.c:ROUND3
122 my ($a,$b,$c,$d,$k,$s,@X) = @_;
123 $_[0] = md4lshift(add32($a,H($b,$c,$d),$X[$k],0x6ED9EBA1), $s);
126 # Ported from SAMBA/source/lib/md4.c:mdfour64
128 my ( $A, $B, $C, $D, @M ) = @_;
129 my ( $AA, $BB, $CC, $DD );
131 @X = (map { $_?$_:0 } @M)[0..15];
132 $AA=$A; $BB=$B; $CC=$C; $DD=$D;
133 ROUND1($A,$B,$C,$D, 0, 3, @X); ROUND1($D,$A,$B,$C, 1, 7, @X);
134 ROUND1($C,$D,$A,$B, 2, 11, @X); ROUND1($B,$C,$D,$A, 3, 19, @X);
135 ROUND1($A,$B,$C,$D, 4, 3, @X); ROUND1($D,$A,$B,$C, 5, 7, @X);
136 ROUND1($C,$D,$A,$B, 6, 11, @X); ROUND1($B,$C,$D,$A, 7, 19, @X);
137 ROUND1($A,$B,$C,$D, 8, 3, @X); ROUND1($D,$A,$B,$C, 9, 7, @X);
138 ROUND1($C,$D,$A,$B, 10, 11, @X); ROUND1($B,$C,$D,$A, 11, 19, @X);
139 ROUND1($A,$B,$C,$D, 12, 3, @X); ROUND1($D,$A,$B,$C, 13, 7, @X);
140 ROUND1($C,$D,$A,$B, 14, 11, @X); ROUND1($B,$C,$D,$A, 15, 19, @X);
141 ROUND2($A,$B,$C,$D, 0, 3, @X); ROUND2($D,$A,$B,$C, 4, 5, @X);
142 ROUND2($C,$D,$A,$B, 8, 9, @X); ROUND2($B,$C,$D,$A, 12, 13, @X);
143 ROUND2($A,$B,$C,$D, 1, 3, @X); ROUND2($D,$A,$B,$C, 5, 5, @X);
144 ROUND2($C,$D,$A,$B, 9, 9, @X); ROUND2($B,$C,$D,$A, 13, 13, @X);
145 ROUND2($A,$B,$C,$D, 2, 3, @X); ROUND2($D,$A,$B,$C, 6, 5, @X);
146 ROUND2($C,$D,$A,$B, 10, 9, @X); ROUND2($B,$C,$D,$A, 14, 13, @X);
147 ROUND2($A,$B,$C,$D, 3, 3, @X); ROUND2($D,$A,$B,$C, 7, 5, @X);
148 ROUND2($C,$D,$A,$B, 11, 9, @X); ROUND2($B,$C,$D,$A, 15, 13, @X);
149 ROUND3($A,$B,$C,$D, 0, 3, @X); ROUND3($D,$A,$B,$C, 8, 9, @X);
150 ROUND3($C,$D,$A,$B, 4, 11, @X); ROUND3($B,$C,$D,$A, 12, 15, @X);
151 ROUND3($A,$B,$C,$D, 2, 3, @X); ROUND3($D,$A,$B,$C, 10, 9, @X);
152 ROUND3($C,$D,$A,$B, 6, 11, @X); ROUND3($B,$C,$D,$A, 14, 15, @X);
153 ROUND3($A,$B,$C,$D, 1, 3, @X); ROUND3($D,$A,$B,$C, 9, 9, @X);
154 ROUND3($C,$D,$A,$B, 5, 11, @X); ROUND3($B,$C,$D,$A, 13, 15, @X);
155 ROUND3($A,$B,$C,$D, 3, 3, @X); ROUND3($D,$A,$B,$C, 11, 9, @X);
156 ROUND3($C,$D,$A,$B, 7, 11, @X); ROUND3($B,$C,$D,$A, 15, 15, @X);
157 # We want to change the arguments, so assign them to $_[0] markers
158 # rather than to $A..$D
159 $_[0] = add32($A,$AA); $_[1] = add32($B,$BB);
160 $_[2] = add32($C,$CC); $_[3] = add32($D,$DD);
161 @X = map { 0 } (1..16);
164 # Ported from SAMBA/source/lib/md4.c:copy64
169 $M[$i] = ($in[$i*4+3]<<24) | ($in[$i*4+2]<<16) |
170 ($in[$i*4+1]<<8) | ($in[$i*4+0]<<0);
174 # Ported from SAMBA/source/lib/md4.c:copy4
179 $out[1] = ($x>>8)&0xFF;
180 $out[2] = ($x>>16)&0xFF;
181 $out[3] = ($x>>24)&0xFF;
182 @out = map { $_?$_:0 } @out;
185 # Ported from SAMBA/source/lib/md4.c:mdfour
187 my ( @in ) = unpack("C*",$_[0]);
188 my ( $b, @A, @M, @buf, @out );
190 @A = ( 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 );
191 while (scalar @in > 64 ) {
196 @buf = ( @in, 0x80, map {0} (1..128) )[0..127];
197 if ( scalar @in <= 55 ) {
198 @buf[56..59] = copy4( $b );
203 @buf[120..123] = copy4( $b );
206 @M = copy64( @buf[64..$#buf] );
209 @out[0..3] = copy4($A[0]);
210 @out[4..7] = copy4($A[1]);
211 @out[8..11] = copy4($A[2]);
212 @out[12..15] = copy4($A[3]);
215 # Contants used in lanlam hash calculations
216 # Ported from SAMBA/source/libsmb/smbdes.c:perm1[56]
217 my @perm1 = (57, 49, 41, 33, 25, 17, 9,
218 1, 58, 50, 42, 34, 26, 18,
219 10, 2, 59, 51, 43, 35, 27,
220 19, 11, 3, 60, 52, 44, 36,
221 63, 55, 47, 39, 31, 23, 15,
222 7, 62, 54, 46, 38, 30, 22,
223 14, 6, 61, 53, 45, 37, 29,
224 21, 13, 5, 28, 20, 12, 4);
225 # Ported from SAMBA/source/libsmb/smbdes.c:perm2[48]
226 my @perm2 = (14, 17, 11, 24, 1, 5,
227 3, 28, 15, 6, 21, 10,
228 23, 19, 12, 4, 26, 8,
229 16, 7, 27, 20, 13, 2,
230 41, 52, 31, 37, 47, 55,
231 30, 40, 51, 45, 33, 48,
232 44, 49, 39, 56, 34, 53,
233 46, 42, 50, 36, 29, 32);
234 # Ported from SAMBA/source/libsmb/smbdes.c:perm3[64]
235 my @perm3 = (58, 50, 42, 34, 26, 18, 10, 2,
236 60, 52, 44, 36, 28, 20, 12, 4,
237 62, 54, 46, 38, 30, 22, 14, 6,
238 64, 56, 48, 40, 32, 24, 16, 8,
239 57, 49, 41, 33, 25, 17, 9, 1,
240 59, 51, 43, 35, 27, 19, 11, 3,
241 61, 53, 45, 37, 29, 21, 13, 5,
242 63, 55, 47, 39, 31, 23, 15, 7);
243 # Ported from SAMBA/source/libsmb/smbdes.c:perm4[48]
244 my @perm4 = ( 32, 1, 2, 3, 4, 5,
246 8, 9, 10, 11, 12, 13,
247 12, 13, 14, 15, 16, 17,
248 16, 17, 18, 19, 20, 21,
249 20, 21, 22, 23, 24, 25,
250 24, 25, 26, 27, 28, 29,
251 28, 29, 30, 31, 32, 1);
252 # Ported from SAMBA/source/libsmb/smbdes.c:perm5[32]
253 my @perm5 = ( 16, 7, 20, 21,
261 # Ported from SAMBA/source/libsmb/smbdes.c:perm6[64]
262 my @perm6 =( 40, 8, 48, 16, 56, 24, 64, 32,
263 39, 7, 47, 15, 55, 23, 63, 31,
264 38, 6, 46, 14, 54, 22, 62, 30,
265 37, 5, 45, 13, 53, 21, 61, 29,
266 36, 4, 44, 12, 52, 20, 60, 28,
267 35, 3, 43, 11, 51, 19, 59, 27,
268 34, 2, 42, 10, 50, 18, 58, 26,
269 33, 1, 41, 9, 49, 17, 57, 25);
270 # Ported from SAMBA/source/libsmb/smbdes.c:sc[16]
271 my @sc = (1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);
272 # Ported from SAMBA/source/libsmb/smbdes.c:sbox[8][4][16]
273 # Side note, I used cut and paste for all these numbers, I did NOT
274 # type them all in =)
275 my @sbox = ([[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
276 [ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
277 [ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
278 [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]],
279 [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
280 [ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
281 [ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
282 [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]],
283 [[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
284 [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
285 [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
286 [ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]],
287 [[ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
288 [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
289 [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
290 [ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]],
291 [[ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
292 [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
293 [ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
294 [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]],
295 [[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
296 [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
297 [ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
298 [ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]],
299 [[ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
300 [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
301 [ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
302 [ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]],
303 [[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
304 [ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
305 [ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
306 [ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]]);
308 # Ported from SAMBA/source/libsmb/smbdes.c:xor
309 # Hack: Split arguments in half and then xor's first half of arguments to
310 # second half of arguments. Probably proper way of doing this would
311 # be to used referenced variables
314 my ( $i, $off, @ret );
317 $ret[$i] = $in[$i] ^ $in[$i+$off+1];
322 # Ported from SAMBA/source/libsmb/smbdes.c:str_to_key
326 @str = map { $_?$_:0 } @str;
327 $key[0] = $str[0]>>1;
328 $key[1] = (($str[0]&0x01)<<6) | ($str[1]>>2);
329 $key[2] = (($str[1]&0x03)<<5) | ($str[2]>>3);
330 $key[3] = (($str[2]&0x07)<<4) | ($str[3]>>4);
331 $key[4] = (($str[3]&0x0F)<<3) | ($str[4]>>5);
332 $key[5] = (($str[4]&0x1F)<<2) | ($str[5]>>6);
333 $key[6] = (($str[5]&0x3F)<<1) | ($str[6]>>7);
334 $key[7] = $str[6]&0x7F;
336 $key[$i] = ($key[$i]<<1);
340 # Ported from SAMBA/source/libsmb/smbdes.c:permute
341 # Would probably be better to pass in by reference
344 my ( $i, $n, @in, @p, @out );
346 # Last argument is the count of the perm values
348 @in = @a[0..($#a-$n-1)];
349 @p = @_[($#a-$n)..($#a-1)];
351 for $i ( 0..($n-1) ) {
352 $out[$i] = $in[$p[$i]-1]?1:0;
357 # Ported from SAMBA/source/libsmb/smbdes.c:lshift
360 my ( $count, @d ) = @_;
362 @d = (@d,@d)[$count..($#d+$count)];
366 # Ported from SAMBA/source/libsmb/smbdes.c:dohash
369 my ( @in, @key, $forw, @pk1, @c, @d, @ki, @cd, $i, @pd1, @l, @r, @rl, @out );
372 @key = @a[64..($#_-1)];
375 @pk1 = permute( @key, @perm1, 56 );
381 @c = lshift( $sc[$i], @c );
382 @d = lshift( $sc[$i], @d );
384 @cd = map { $_?1:0 } ( @c, @d );
385 $ki[$i] = [ permute( @cd, @perm2, 48 ) ];
388 @pd1 = permute( @in, @perm3, 64 );
394 my ( $j, $k, @b, @er, @erk, @cb, @pcb, @r2 );
395 @er = permute( @r, @perm4, 48 );
396 @erk = mxor(@er, @{ @ki[$forw?$i:(15-$i)] });
400 $b[$j][$k] = $erk[$j*6 + $k];
405 $m = ($b[$j][0]<<1) | $b[$j][5];
406 $n = ($b[$j][1]<<3) | ($b[$j][2]<<2) | ($b[$j][3]<<1) | $b[$j][4];
409 $b[$j][$k]=($sbox[$j][$m][$n] & (1<<(3-$k)))?1:0;
414 $cb[$j*4+$k]=$b[$j][$k];
417 @pcb = permute( @cb, @perm5, 32);
423 @out = permute( @rl, @perm6, 64 );
427 # Ported from SAMBA/source/libsmb/smbdes.c:smbhash
429 my ( @in, @key, $forw, @outb, @out, @inb, @keyb, @key2, $i );
434 @key2 = str_to_key(@key);
437 $inb[$i] = ( $in[$i/8] & (1<<(7-($i%8)))) ? 1:0;
438 $keyb[$i] = ( $key2[$i/8] & (1<<(7-($i%8)))) ? 1:0;
441 @outb = dohash(@inb,@keyb,$forw);
447 $out[$i/8] |= (1<<(7-($i%8)));
453 # Ported from SAMBA/source/libsmb/smbdes.c:E_P16
455 my ( @p16, @p14, @sp8 );
456 @p16 = map { 0 } (1..16);
457 @p14 = unpack("C*",$_[0]);
458 @sp8 = ( 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 );
459 @p16 = (smbhash(@sp8,@p14[0..6],1),smbhash(@sp8,@p14[7..13],1));
469 Crypt::SmbHash - Perl-only implementation of lanman and nt md4 hash functions, for use in Samba style smbpasswd entries
475 ntlmgen SCALAR, LMSCALAR, NTSCALAR;
479 This module generates Lanman and NT MD4 style password hashes, using
480 perl-only code for portability. The module aids in the administration
481 of Samba style systems.
483 In the Samba distribution, authentication is referred to a private
484 smbpasswd file. Entries have similar forms to the following:
486 username:unixuid:LM:NT
488 Where LM and NT are one-way password hashes of the same password.
490 ntlmgen generates the hashes given in the first argument, and places
491 the result in the second and third arguments.
494 To generate a smbpasswd entry:
496 #!/usr/local/bin/perl
498 $username = $ARGV[0];
499 $password = $ARGV[1];
501 print "Not enough arguments\n";
502 print "Usage: $0 username password\n";
505 $uid = (getpwnam($username))[2];
506 my ($login,undef,$uid) = getpwnam($ARGV[0]);
507 ntlmgen $password, $lm, $nt;
508 printf "%s:%d:%s:%s:[%-11s]:LCT-%08X\n", $login, $uid, $lm, $nt, "U", time;
511 ntlmgen returns returns the hash values in a list context, so the alternative
512 method of using it is:
514 ( $lm, $nt ) = ntlmgen $password;
516 The functions lmhash and nthash are used by ntlmgen to generate the
517 hashes, and are available when requested:
519 use Crypt::SmbHash qw(lmhash nthash)
525 The algorithm used in nthash requires the md4 algorithm. This algorithm
526 is included in this module for completeness, but because it is written
527 in all-perl code ( rather than in C ), it's not very quick.
529 However if you have the Digest::MD4 module installed, Crypt::SmbHash will
530 try to use that module instead, making it much faster.
532 A simple test compared calling nthash without Digest::MD4 installed, and
533 with, this showed that using nthash on a system with Digest::MD4 installed
534 proved to be over 90 times faster.
538 Ported from Samba by Benjamin Kuit <lt>bj@it.uts.edu.au<gt>.
540 Samba is Copyright(C) Andrew Tridgell 1997-1998
542 Because this module is a direct port of code within the Samba
543 distribution, it follows the same license, that is:
545 This program is free software; you can redistribute it and/or modify
546 it under the terms of the GNU General Public License as published by
547 the Free Software Foundation; either version 2 of the License, or
548 (at your option) any later version.
550 This program is distributed in the hope that it will be useful,
551 but WITHOUT ANY WARRANTY; without even the implied warranty of
552 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
553 GNU General Public License for more details.