#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 230;
use File::Spec;
use Net::SSLeay;
sub digest_chunked_f1 {
my ($file, $digest) = @_;
my $md = Net::SSLeay::EVP_get_digestbyname($digest) or BAIL_OUT "digest '$digest' not available";
my $ctx = Net::SSLeay::EVP_MD_CTX_create();
Net::SSLeay::EVP_DigestInit($ctx, $md);
open my $fh, "<", $file or BAIL_OUT "cannot open file '$file'";
binmode $fh;
while(my $len = sysread($fh, my $chunk, 500)) {
Net::SSLeay::EVP_DigestUpdate($ctx,$chunk);
}
close $fh;
my $result = Net::SSLeay::EVP_DigestFinal($ctx);
Net::SSLeay::EVP_MD_CTX_destroy($ctx);
return $result;
}
sub digest_chunked_f2 {
my ($file, $digest) = @_;
my $md = Net::SSLeay::EVP_get_digestbyname($digest) or BAIL_OUT "digest '$digest' not available";
my $ctx = Net::SSLeay::EVP_MD_CTX_create();
Net::SSLeay::EVP_DigestInit_ex($ctx, $md, 0); #NULL ENGINE just to test whether the function exists
open my $fh, "<", $file or BAIL_OUT "cannot open file '$file'";
binmode $fh;
while(my $len = sysread($fh, my $chunk, 5)) {
Net::SSLeay::EVP_DigestUpdate($ctx,$chunk);
}
close $fh;
my $result = Net::SSLeay::EVP_DigestFinal_ex($ctx);
Net::SSLeay::EVP_MD_CTX_destroy($ctx);
return $result;
}
sub digest_file {
my ($file, $expected_results, $available_digests) = @_;
for my $d (sort keys %$expected_results) {
SKIP: {
skip "digest '$d' not available (or pre-1.0.0)", 2 unless $available_digests->{$d};
is( unpack("H*", digest_chunked_f1($file, $d)), $expected_results->{$d}, "$d chunked.1 [$file]");
is( unpack("H*", digest_chunked_f2($file, $d)), $expected_results->{$d}, "$d chunked.2 [$file]");
}
}
open my $f, "<", $file or BAIL_OUT "cannot open file '$file'";
binmode $f;
sysread($f, my $data, -s $file) or BAIL_OUT "sysread failed";
close $f;
is(length($data), -s $file, 'got the whole file');
SKIP: {
skip "Net::SSLeay::MD2 not available", 1
unless exists &Net::SSLeay::MD2 and exists $available_digests->{md2};
is( unpack("H*", Net::SSLeay::MD2($data)), $expected_results->{md2}, "MD2 all-in-one-go [$file]");
}
SKIP: {
skip "Net::SSLeay::MD4 not available", 1
unless exists &Net::SSLeay::MD4 and exists $available_digests->{md4};
is( unpack("H*", Net::SSLeay::MD4($data)), $expected_results->{md4}, "MD4 all-in-one-go [$file]");
}
SKIP: {
skip "Net::SSLeay::MD5 not available", 1
unless exists &Net::SSLeay::MD5 and exists $available_digests->{md5};
is( unpack("H*", Net::SSLeay::MD5($data)), $expected_results->{md5}, "MD5 all-in-one-go [$file]");
}
SKIP: {
skip "Net::SSLeay::RIPEMD160 not available", 1
unless exists &Net::SSLeay::RIPEMD160 and
exists $available_digests->{ripemd160};
is( unpack("H*", Net::SSLeay::RIPEMD160($data)), $expected_results->{ripemd160}, "RIPEMD160 all-in-one-go [$file]");
}
}
sub digest_strings {
my ($fps, $available_digests) = @_;
for my $data (sort keys %$fps) {
for my $d (sort keys %{$fps->{$data}}) {
SKIP: {
skip "digest '$d' not available (or pre-1.0.0)", 2 unless $available_digests->{$d};
my $md = Net::SSLeay::EVP_get_digestbyname($d) or BAIL_OUT "digest '$d' not available";
my $ctx = Net::SSLeay::EVP_MD_CTX_create();
Net::SSLeay::EVP_DigestInit($ctx, $md);
Net::SSLeay::EVP_DigestUpdate($ctx, $data);
my $result1 = Net::SSLeay::EVP_DigestFinal($ctx);
Net::SSLeay::EVP_MD_CTX_destroy($ctx);
is(unpack('H*', $result1), $fps->{$data}->{$d}, "$d for '$data'");
# test EVP_Digest
my $result2 = Net::SSLeay::EVP_Digest($data, Net::SSLeay::EVP_get_digestbyname($d));
is(unpack('H*', $result2), $fps->{$data}->{$d}, "EVP_Digest($d)");
}
}
SKIP: {
skip "Net::SSLeay::MD2 not available", 1
unless exists &Net::SSLeay::MD2 and exists $available_digests->{md2};
is(unpack('H*', Net::SSLeay::MD2($data)), $fps->{$data}->{md2}, "MD2 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::MD4 not available", 1
unless exists &Net::SSLeay::MD4 and exists $available_digests->{md4};
is(unpack('H*', Net::SSLeay::MD4($data)), $fps->{$data}->{md4}, "MD4 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::MD5 not available", 1
unless exists &Net::SSLeay::MD5 and exists $available_digests->{md5};
is(unpack('H*', Net::SSLeay::MD5($data)), $fps->{$data}->{md5}, "MD5 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::RIPEMD160 not available", 1
unless exists &Net::SSLeay::RIPEMD160 and
exists $available_digests->{ripemd160};
is(unpack('H*', Net::SSLeay::RIPEMD160($data)), $fps->{$data}->{ripemd160}, "RIPEMD160 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::SHA1 not available", 1
unless exists &Net::SSLeay::SHA1 and exists $available_digests->{sha1};
is(unpack('H*', Net::SSLeay::SHA1($data)), $fps->{$data}->{sha1}, "SHA1 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::SHA256 not available", 1
unless exists &Net::SSLeay::SHA256 and
exists $available_digests->{sha256};
is(unpack('H*', Net::SSLeay::SHA256($data)), $fps->{$data}->{sha256}, "SHA256 hash for '$data'");
}
SKIP: {
skip "Net::SSLeay::SHA512 not available", 1
unless exists &Net::SSLeay::SHA512 and
exists $available_digests->{sha512};
is(unpack('H*', Net::SSLeay::SHA512($data)), $fps->{$data}->{sha512}, "SHA512 hash for '$data'");
}
}
}
my %all_digests;
eval {
Net::SSLeay::initialize();
Net::SSLeay::OpenSSL_add_all_digests();
if (Net::SSLeay::SSLeay >= 0x1000000f) {
my $ctx = Net::SSLeay::EVP_MD_CTX_create();
%all_digests = map { $_=>1 } grep {
# P_EVP_MD_list_all() does not remove digests disabled in FIPS
my $md;
$md = Net::SSLeay::EVP_get_digestbyname($_) and
Net::SSLeay::EVP_DigestInit($ctx, $md)
} @{Net::SSLeay::P_EVP_MD_list_all()};
}
else {
%all_digests = ();
}
};
is($@, '', 'digest init OK');
SKIP: {
skip "pre-1.0.0", 1 unless Net::SSLeay::SSLeay >= 0x1000000f;
isnt(scalar(keys %all_digests), 0, 'non-empty digest list');
}
my $file1 = File::Spec->catfile('t', 'data', 'cert.pem');
my $results1 = {
md2 => '6d89cda9599a54d03652f9464e8b6e51',
md4 => 'ada352f40f1ca64f4168a8aae7c1a281',
md5 => 'e060f11c6afa9e1f59a8e7c873aa3423',
mdc2 => 'e9ca1fd1cfccfb450b402a0dd446db28',
ripemd160 => 'cbd50056558b01b5e9ec67901b518462b5393e5b',
sha => '79de0d0cc736d98b65f5d6b3ac89e65ca8d3b2a7',
sha1 => '0267dd25bbd8930c537716d972dd9ba128846428',
sha224 => '5b42d5a3b16a6cee821b03c41f0428b09b70695becb0aaafbc7d6419',
sha256 => '764633a51af4ef374cabb1ea859cc324680cfeff694797e90562e19ffb71ab26',
sha512 => '37e3a2e84aec822922c51d4d8d37bf003e1d85f55a4bf2fae2940a5aab5b32f7601c2a9cde5b9c6391aaa4ffef1e845f11d2f0b6a37a9b2f48fb7f6469f0a51c',
whirlpool => 'b2dc90dbbc60e5e2dc28de3bdeab45fb2fa6d13d86ff14908130624a242e38ecc195b3b11a7ef137b77a24e9a0ba5be061ac1baa11892369286d613569199458',
};
my $file2 = File::Spec->catfile('t', 'data', 'binary-test.file');
my $results2 = {
md2 => '67ae6d821be6898101414c56b1fb4f46',
md4 => '480438696e7d9a6ab3ecc1e2a3419f78',
md5 => 'cc89b43c171818c347639fa5170aee16',
mdc2 => 'ee605fe3fc966a7b17185ebdbcd13ada',
ripemd160 => 'cb70ba43fc6d263f6d7816170c1a33f28c2000fe',
sha => 'c151c6f408cb94bc5c53b17852efbe8bfbeec2b9',
sha1 => '059404d1d0e952d0457a6c99b6e68b3b44c8ef13',
sha224 => '161c65efa1b9762f7e0448b5b369a3e2c236876b0b57a35add5106bb',
sha256 => 'e416730ddaa34729adb32ec6ddad4e50fca1fe97de313e800196b1f8cd5032bd',
sha512 => '8b5e7181fc76d49e1cb7971a6980b5d8db6b23c3b0553cf42f559156fd08e64567d17c4147c864efd4d3a5e22fb6602d613a055f7f14faad22744dbc3df89d59',
whirlpool => '31079767aa2dd9b8ab01caadd954a88aaaf6001941c38d17ba43c0ef80a074c3eedf35b73c3941929dea281805c6c5ffc0a619abef4c6a3365d6cb31412d0e0c',
};
my %fps = (
'' => {
md2 => '8350e5a3e24c153df2275c9f80692773',
md4 => '31d6cfe0d16ae931b73c59d7e0c089c0',
md5 => 'd41d8cd98f00b204e9800998ecf8427e',
ripemd160 => '9c1185a5c5e9fc54612808977ee8f548b2258d31',
sha1 => 'da39a3ee5e6b4b0d3255bfef95601890afd80709',
sha256 => 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
sha512 => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
},
'a' => {
md2 => '32ec01ec4a6dac72c0ab96fb34c0b5d1',
md4 => 'bde52cb31de33e46245e05fbdbd6fb24',
md5 => '0cc175b9c0f1b6a831c399e269772661',
ripemd160 => '0bdc9d2d256b3ee9daae347be6f4dc835a467ffe',
sha1=>'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8',
sha256=>'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb',
sha512=>'1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75',
},
'38' => {
md2 => '4b85c826321a5ce87db408c908d0709e',
md4 => 'ae9c7ebfb68ea795483d270f5934b71d',
md5 => 'a5771bce93e200c36f7cd9dfd0e5deaa',
ripemd160 => '6b2d075b1cd34cd1c3e43a995f110c55649dad0e',
sha1=>'5b384ce32d8cdef02bc3a139d4cac0a22bb029e8',
sha256=>'aea92132c4cbeb263e6ac2bf6c183b5d81737f179f21efdc5863739672f0f470',
sha512=>'caae34a5e81031268bcdaf6f1d8c04d37b7f2c349afb705b575966f63e2ebf0fd910c3b05160ba087ab7af35d40b7c719c53cd8b947c96111f64105fd45cc1b2',
},
'abc' => {
md2 => 'da853b0d3f88d99b30283a69e6ded6bb',
md4 => 'a448017aaf21d8525fc10ae87aa6729d',
md5 => '900150983cd24fb0d6963f7d28e17f72',
ripemd160 => '8eb208f7e05d987a9b044a8e98c6b087f15a0bfc',
sha1=>'a9993e364706816aba3e25717850c26c9cd0d89d',
sha256=>'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
sha512=>'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f',
},
'message digest' => {
md2 => 'ab4f496bfb2a530b219ff33031fe06b0',
md4 => 'd9130a8164549fe818874806e1c7014b',
md5 => 'f96b697d7cb7938d525a2f31aaf161d0',
ripemd160 => '5d0689ef49d2fae572b881b123a85ffa21595f36',
sha1=>'c12252ceda8be8994d5fa0290a47231c1d16aae3',
sha256=>'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650',
sha512=>'107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c',
},
'abcdefghijklmnopqrstuvwxyz' => {
md2 => '4e8ddff3650292ab5a4108c3aa47940b',
md4 => 'd79e1c308aa5bbcdeea8ed63df412da9',
md5 => 'c3fcd3d76192e4007dfb496cca67e13b',
ripemd160 => 'f71c27109c692c1b56bbdceb5b9d2865b3708dbc',
sha1=>'32d10c7b8cf96570ca04ce37f2a19d84240d3a89',
sha256=>'71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73',
sha512=>'4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1',
},
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' => {
md2 => 'da33def2a42df13975352846c30338cd',
md4 => '043f8582f241db351ce627e153e7f0e4',
md5 => 'd174ab98d277d9f5a5611c2c9f419d9f',
ripemd160 => 'b0e20b6e3116640286ed3a87a5713079b21f5189',
sha1=>'761c457bf73b14d27e9e9265c46f4b4dda11f940',
sha256=>'db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0',
sha512=>'1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894',
},
'12345678901234567890123456789012345678901234567890123456789012345678901234567890' => {
md2 => 'd5976f79d83d3a0dc9806c3c66f3efd8',
md4 => 'e33b4ddc9c38f2199c3e7b164fcc0536',
md5 => '57edf4a22be3c955ac49da2e2107b67a',
ripemd160 => '9b752e45573d4b39f4dbd3323cab82bf63326bfb',
sha1=>'50abf5706a150990a08b2c5ea40fa0e585554732',
sha256=>'f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e',
sha512=>'72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843',
},
);
SKIP: {
skip "MD5 not available", 3 unless exists &Net::SSLeay::MD5;
is(Net::SSLeay::EVP_MD_type(Net::SSLeay::EVP_get_digestbyname("MD5")), 4, 'EVP_MD_type md5');
is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_get_digestbyname("MD5")), 16, 'EVP_MD_size md5');
SKIP: {
skip "pre-0.9.7", 1 unless Net::SSLeay::SSLeay >= 0x0090700f;
my $md = Net::SSLeay::EVP_get_digestbyname("md5");
my $ctx = Net::SSLeay::EVP_MD_CTX_create();
skip "MD5 not available", 1 unless Net::SSLeay::EVP_DigestInit($ctx, $md);
my $md2 = Net::SSLeay::EVP_MD_CTX_md($ctx);
is(Net::SSLeay::EVP_MD_size($md2), 16, 'EVP_MD_size via EVP_MD_CTX_md md5');
}
}
SKIP: {
skip "Net::SSLeay::EVP_sha512 not available", 1 unless exists &Net::SSLeay::EVP_sha512;
is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha512()), 64, 'EVP_MD_size sha512');
}
SKIP: {
skip "Net::SSLeay::EVP_sha256 not available", 1 unless exists &Net::SSLeay::EVP_sha256;
is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha256()), 32, 'EVP_MD_size sha256');
}
SKIP: {
skip "Net::SSLeay::EVP_sha1 not available", 1 unless exists &Net::SSLeay::EVP_sha1;
is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha1()), 20, 'EVP_MD_size sha1');
}
digest_file($file1, $results1, \%all_digests);
digest_file($file2, $results2, \%all_digests);
digest_strings(\%fps, \%all_digests);