SMB

 view release on metacpan or  search on metacpan

lib/SMB/Crypt.pm  view on Meta::CPAN


	my $c = permute($key, $des_perm1);
	my $d = [ splice(@$c, 28) ];

	my @ki;
	for my $i (0 .. 15) {
		lshift($c, $des_sc[$i]);
		lshift($d, $des_sc[$i]);

		$ki[$i] = permute([ @$c, @$d ], $des_perm2);
	}

	my $l = permute($arr, $des_perm3);
	my $r = [ splice(@$l, 32) ];

	for my $i (0 .. 15) {
		my $er = permute($r, $des_perm4);

		xor_inplace($er, $ki[$forw ? $i : 15 - $i]);

		my @b;
		for my $j (0 .. 7) {
			$b[$j] = [];
			for my $k (0 .. 5) {
				$b[$j][$k] = $er->[$j * 6 + $k];
			}
		}

		for my $j (0 .. 7) {
			my $m = ($b[$j][0] << 1) | ($b[$j][5] << 0);
			my $n = ($b[$j][1] << 3) | ($b[$j][2] << 2) | ($b[$j][3] << 1) | ($b[$j][4] << 0);

			for my $k (0 .. 3) {
				$b[$j][$k] = $des_sbox[$j][$m][$n] & (1 << (3 - $k)) ? 1 : 0;
			}
		}

		my @cb;
		for my $j (0 .. 7) {
			for my $k (0 .. 3) {
				$cb[$j * 4 + $k] = $b[$j][$k];
			}
		}

		my $pcb = permute(\@cb, $des_perm5);

		xor_inplace($l, $pcb);

		($l, $r) = ($r, $l);
	}

	return permute([ @$r, @$l ], $des_perm6 );
}

sub des_crypt56 ($$;$) {
	my $data = shift // die "No 8-byte data to crypt";
	my $str  = shift // die "No 7-byte key to crypt";
	my $forw = shift // 1;

	if (has_Crypt_DES()) {
		return Crypt::DES->new(des_str_to_key($str))->encrypt($data);
	}

	my $arr = [ map { ord($_) } split '', $data ];
	my $key = [ map { ord($_) } split '', des_str_to_key($str) ];

	my $arrb = [];
	my $keyb = [];
	for my $i (0 .. 63) {
		$arrb->[$i] = $arr->[$i / 8] & (1 << (7 - $i % 8)) ? 1 : 0;
		$keyb->[$i] = $key->[$i / 8] & (1 << (7 - $i % 8)) ? 1 : 0;
	}

	my $outb = des_dohash($arrb, $keyb, $forw);

	my $out = [ (0) x 8 ];
	for my $i (0 .. 63) {
		$out->[$i / 8] |= 1 << (7 - $i % 8)
			if $outb->[$i];
	}

	return join('', map { chr($_) } @$out);
}

# MD4 parts for SMB authentication, ported from samba crypto/md4.c

our @md4_state;

sub md4_F { my ($x, $y, $z) = @_; return ($x & $y) | ((~$x) & $z); }
sub md4_G { my ($x, $y, $z) = @_; return ($x & $y) | ($x & $z) | ($y & $z); }
sub md4_H { my ($x, $y, $z) = @_; return $x ^ $y ^ $z; }

# uint32 arithmetic in perl, hopefully works on all platforms
sub add32 (@) {
	my @sum = (0, 0);
	for (@_) {
		$sum[0] += $_ & 0xFFFF;
		$sum[1] += ($_ >> 16) & 0xFFFF;
	}
	$sum[1] += $sum[0] >> 16;
	$sum[0] &= 0xFFFF;
	$sum[1] &= 0xFFFF;

	return ($sum[1] << 16) + $sum[0];
}

sub lshift32 ($$) {
	my ($num, $count) = @_;

	return (($num << $count) & 0xFFFFFFFF) | ($num >> (32 - $count));
}

sub md4_ROUND1 {
	my ($a, $b, $c, $d, $X, $s) = @_;

	$md4_state[$a] = lshift32(add32($md4_state[$a], md4_F(@md4_state[$b, $c, $d]), $X, 0x00000000), $s);
}

sub md4_ROUND2 {
	my ($a, $b, $c, $d, $X, $s) = @_;

lib/SMB/Crypt.pm  view on Meta::CPAN

	md5_STEP(\&md5_F4, 3, 0, 1, 2, $_[15], 0xfe2ce6e0, 10);
	md5_STEP(\&md5_F4, 2, 3, 0, 1, $_[ 6], 0xa3014314, 15);
	md5_STEP(\&md5_F4, 1, 2, 3, 0, $_[13], 0x4e0811a1, 21);
	md5_STEP(\&md5_F4, 0, 1, 2, 3, $_[ 4], 0xf7537e82,  6);
	md5_STEP(\&md5_F4, 3, 0, 1, 2, $_[11], 0xbd3af235, 10);
	md5_STEP(\&md5_F4, 2, 3, 0, 1, $_[ 2], 0x2ad7d2bb, 15);
	md5_STEP(\&md5_F4, 1, 2, 3, 0, $_[ 9], 0xeb86d391, 21);

	$md5_state[$_] = add32($md5_state[$_], $old_state[$_]) for 0 .. 3;
}

sub md5 ($;$) {
	if (has_Digest_MD5()) {
		return Digest::MD5::md5(join '', @_);
	}

	my $data = md5_pad64(join '', @_);

	@md5_state = ( 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 );

	for my $i (0 .. length($data) / 64 - 1) {
		md5_ROUND(unpack 'V16', substr $data, $i * 64, 64);
	}

	pack 'V4', @md5_state;
}

sub hmac_md5 ($$) {
	my ($data, $key) = @_;

	$key = md5($key) if length($key) > 64;

	my $ipad = $key ^ ("\x36" x 64);
	my $opad = $key ^ ("\x5c" x 64);

	return md5($opad, md5($ipad, $data));
}

1;

__END__
# ----------------------------------------------------------------------------

=head1 NAME

SMB::Crypt - Fallback implementations of cryptography algorithms for SMB

=head1 SYNOPSIS

	use SMB::Crypt qw(md4 md5);

	my $digest1 = md4($data);

	my $digest2 = md5($data);

=head1 ABSTRACT

This module provides fallback implementations for DES, MD4 and MD5 in
pure perl to reduce dependence on non-standard perl modules.

However it is recommended to install L<Crypt::DES>, L<Digest::MD4> and
L<Digest::MD5> modules to get improved performance.

=head1 EXPORTED FUNCTIONS

By default, functions B<des_crypt56>, B<md4>, B<md5> and B<hmac_md5> are exported using the standard L<Exporter> mechanism.

=over 4

=item des_crypt56 EIGHT_BYTE_INPUT SEVEN_BYTE_KEY_STR [FORWARD=1]

Returns output of eight bytes that is a permutation of the input according to a key.

If L<Crypt::DES> is found, it is used, otherwise pure perl fallback implemenation is used.

=item md4 DATA

Returns digest of 16 bytes, similar to Digest::MD4::md4.

If L<Digest::MD4> is found, it is used, otherwise pure perl fallback implemenation is used.

=item md5 DATA ...

Returns digest of 16 bytes, similar to Digest::MD5::md5.

If L<Digest::MD5> is found, it is used, otherwise pure perl fallback implemenation is used.

=item hmac_md5 DATA KEY

Returns digest of 16 bytes, similar to Digest::HMAC_MD5::hmac_md5. Uses B<md5> internally.

=back

=head1 AUTHOR

Mikhael Goikhman <migo@cpan.org>

=head1 ACKNOWLEGDEMENTS

Ported from samba project.



( run in 0.766 second using v1.01-cache-2.11-cpan-39bf76dae61 )