libcryptx-perl/t/wycheproof.t

245 lines
9.7 KiB
Perl

# rebuild:
# rm -f src/liballinone.a && touch CryptX.xs && make && perl -Mblib t/wycheproof.t
use strict;
use warnings;
use Test::More;
plan skip_all => "No JSON::* module installed" unless eval { require JSON::PP } || eval { require JSON::XS } || eval { require Cpanel::JSON::XS };
plan tests => 1298;
use CryptX;
use Crypt::Misc 'read_rawfile';
use Crypt::Digest 'digest_data';
if (1) {
use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/aes_gcm_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type};
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId}; # 1
my $comment = $t->{comment}; # ""
my $result = $t->{result}; # "valid"
my $aad = pack "H*", $t->{aad}; # "6578616d706c65"
my $ct = pack "H*", $t->{ct}; # "5d349ead175ef6b1def6fd"
my $iv = pack "H*", $t->{iv}; # "752abad3e0afb5f434dc4310"
my $key = pack "H*", $t->{key}; # "ee8e1ed9ff2540ae8f2ba9f50bc2f27c"
my $msg = pack "H*", $t->{msg}; # "48656c6c6f20776f726c64"
my $tag = pack "H*", $t->{tag}; # "4fbcdeb7e4793f4a1d7e4faa70100af1"
# do the test
my ($ct2, $tag2) = eval { gcm_encrypt_authenticate('AES', $key, $iv, $aad, $msg) };
my $pt2 = eval { gcm_decrypt_verify('AES', $key, $iv, $aad, $ct, $tag) };
my $testname = "type=$type tcId=$tcId comment='$comment' expected-result=$result";
if ($result eq 'valid') {
is(unpack("H*", $ct2), $t->{ct}, "$testname CT-v");
is(unpack("H*", $tag2), $t->{tag}, "$testname TAG-v");
is(unpack("H*", $pt2), $t->{msg}, "$testname PT-v");
}
elsif ($result eq 'invalid') {
#isnt(unpack("H*", $ct2), $t->{ct}, "$testname CT-i");
#isnt(unpack("H*", $tag2), $t->{tag}, "$testname TAG-i");
is($pt2, undef, "$testname PT-i");
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}
if (1) {
use Crypt::PK::RSA;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/rsa_signature_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type};
my $keyDer = pack "H*", $g->{keyDer};
my $keyPem = $g->{keyPem};
my $sha = $g->{sha};
$sha =~ s/-//g; # SHA-1 >> SHA1
ok(Crypt::PK::RSA->new( \$keyDer ), "Crypt::PK::RSA->new + DER type: $type/$sha");
ok(Crypt::PK::RSA->new( \$keyPem ), "Crypt::PK::RSA->new + PEM type: $type/$sha");
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId};
my $comment = $t->{comment};
my $result = $t->{result};
my $message = pack "H*", $t->{message};
my $sig = pack "H*", $t->{sig};
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::RSA->new( \$keyPem );
my $valid = $pk->verify_message($sig, $message, $sha,"v1.5");
if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, $testname);
}
elsif ($result eq 'invalid') {
ok(!$valid, $testname);
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}
if (1) {
use Crypt::PK::DSA;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/dsa_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type}; # "DSAVer"
my $keyDer = pack "H*", $g->{keyDer};
my $keyPem = $g->{keyPem};
my $sha = $g->{sha}; # "SHA-1"
$sha =~ s/-//g; # SHA-1 >> SHA1
ok(Crypt::PK::DSA->new( \$keyDer ), "Crypt::PK::DSA->new + DER type=$type/$sha");
ok(Crypt::PK::DSA->new( \$keyPem ), "Crypt::PK::DSA->new + PEM type=$type/$sha");
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId};
my $comment = $t->{comment};
my $result = $t->{result};
my $message = pack "H*", $t->{message};
my $sig = pack "H*", $t->{sig};
# skip unsupported tests:
next if $tcId==12 && $result eq 'acceptable' && $comment eq "Legacy:ASN encoding of s misses leading 0";
next if $tcId==13 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
next if $tcId==14 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
next if $tcId==15 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
next if $tcId==16 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
next if $tcId==17 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
next if $tcId==18 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
next if $tcId==19 && $result eq 'acceptable' && $comment eq "BER:indefinite length";
next if $tcId==20 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
next if $tcId==21 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::DSA->new( \$keyPem );
my $hash = digest_data($sha, $message);
my $valid_h = $pk->verify_hash($sig, $hash);
my $valid = $pk->verify_message($sig, $message, $sha);
if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, $testname);
}
elsif ($result eq 'invalid') {
ok(!$valid, $testname);
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}
if (1) {
use Crypt::PK::ECC;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/ecdsa_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type};
my $keyDer = pack "H*", $g->{keyDer};
my $keyPem = $g->{keyPem};
my $sha = $g->{sha};
$sha =~ s/-//g; # SHA-1 >> SHA1
ok(Crypt::PK::ECC->new( \$keyDer ), "Crypt::PK::ECC->new + DER type=$type/$sha");
ok(Crypt::PK::ECC->new( \$keyPem ), "Crypt::PK::ECC->new + PEM type=$type/$sha");
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId};
my $comment = $t->{comment};
my $result = $t->{result};
my $message = pack "H*", $t->{message};
my $sig = pack "H*", $t->{sig};
# skip unsupported tests:
next if $tcId==9 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
next if $tcId==10 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
next if $tcId==12 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
next if $tcId==13 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
next if $tcId==14 && $result eq 'acceptable' && $comment eq "BER:indefinite length";
next if $tcId==15 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
next if $tcId==16 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::ECC->new( \$keyPem );
my $valid = $pk->verify_message($sig, $message, $sha);
if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, "$testname verify_message=$valid");
}
elsif ($result eq 'invalid') {
ok(!$valid, "$testname verify_message=$valid");
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}
if (1) {
use Crypt::PK::ECC;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/ecdsa_webcrypto_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type};
my $keyDer = pack "H*", $g->{keyDer};
my $keyPem = $g->{keyPem};
my $sha = $g->{sha};
my $jwk = $g->{jwk};
$sha =~ s/-//g; # SHA-1 >> SHA1
ok(Crypt::PK::ECC->new( \$keyDer ), "Crypt::PK::ECC->new + DER type=$type/$sha");
ok(Crypt::PK::ECC->new( \$keyPem ), "Crypt::PK::ECC->new + PEM type=$type/$sha");
ok(Crypt::PK::ECC->new( $jwk ), "Crypt::PK::ECC->new + JWK type=$type/$sha");
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId};
my $comment = $t->{comment};
my $result = $t->{result};
my $message = pack "H*", $t->{message};
my $sig = pack "H*", $t->{sig};
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::ECC->new( \$keyPem );
my $valid = $pk->verify_message_rfc7518($sig, $message, $sha);
if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, "$testname verify_message=$valid");
}
elsif ($result eq 'invalid') {
ok(!$valid, "$testname verify_message=$valid");
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}
if (1) {
use Crypt::PK::ECC;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/ecdh_webcrypto_test.json';
for my $g (@{$tests->{testGroups}}) {
my $type = $g->{type};
for my $t (@{$g->{tests}}) {
my $tcId = $t->{tcId};
my $comment = $t->{comment};
my $name = $t->{name};
my $result = $t->{result};
my $shared = pack "H*", $t->{shared};
# do the test
my $testname = "type=$type/$name tcId=$tcId comment='$comment' expected-result=$result";
my $pub = Crypt::PK::ECC->new( $t->{public} );
my $pri = Crypt::PK::ECC->new( $t->{private} );
my $shared_hex = unpack "H*", $pri->shared_secret($pub);
if ($result eq 'valid' || $result eq 'acceptable') {
is($shared_hex, $t->{shared}, $testname);
}
elsif ($result eq 'invalid') {
isnt($shared_hex, $t->{shared}, $testname);
}
else {
ok(0, "UNEXPECTED result=$result");
}
}
}
}