diff --git a/t/wycheproof/test.pl b/t/wycheproof/test.pl deleted file mode 100644 index c54edfa..0000000 --- a/t/wycheproof/test.pl +++ /dev/null @@ -1,206 +0,0 @@ -###XXX-FIXME unfinished - -# rm -f src/liballinone.a && touch CryptX.xs && make && perl -Mblib t/wycheproof/test.pl - -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 => 716; - -use CryptX; -use Crypt::Misc 'read_rawfile'; - -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"); - } - else { - #isnt(unpack("H*", $ct2), $t->{ct}, "$testname CT-i"); - #isnt(unpack("H*", $tag2), $t->{tag}, "$testname TAG-i"); - is($pt2, undef, "$testname PT-i"); - } - } - } -} - -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 =~ /^(valid|acceptable)$/) { - ok($valid, $testname); - } - else { - ok(!$valid, $testname); - } - - } - } -} - -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}; - # do the test - my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result"; - my $pk = Crypt::PK::DSA->new( \$keyPem ); - my $valid = $pk->verify_message($sig, $message, $sha); - if ($result =~ /^(valid|acceptable)$/) { - ok($valid, $testname); - } - else { - ok(!$valid, $testname); - } - } - } -} - -if (0) { - 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}; - # 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 =~ /^(valid|acceptable)$/) { - ok($valid, "$testname verify_message=$valid"); - } - else { - ok(!$valid, "$testname verify_message=$valid"); - } - } - } -} - -if (0) { - 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($sig, $message, $sha); - if ($result =~ /^(valid|acceptable)$/) { - ok($valid, "$testname verify_message=$valid"); - } - else { - ok(!$valid, "$testname verify_message=$valid"); - } - } - } -} - -if (0) { - 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 =~ /^(valid|acceptable)$/) { - is($shared_hex, $t->{shared}, $testname); - } - else { - isnt($shared_hex, $t->{shared}, $testname); - } - } - } -} diff --git a/t/wycheproof.t b/t/wycheproof.t new file mode 100644 index 0000000..0782d03 --- /dev/null +++ b/t/wycheproof.t @@ -0,0 +1,247 @@ +# 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 => 762; + +use CryptX; +use Crypt::Misc 'read_rawfile'; + +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 $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 (0) { + #XXX-TODO: + # not ok 749 - type=ECDSAVer/SHA256 tcId=50 comment='appending unused 0's' expected-result=invalid verify_message=1 + # not ok 819 - type=ECDSAVer/SHA256 tcId=120 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=1 + # not ok 820 - type=ECDSAVer/SHA256 tcId=121 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=1 + # not ok 821 - type=ECDSAVer/SHA256 tcId=122 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=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}; + # 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') { + ok($valid, "$testname verify_message=$valid"); + } + elsif ($result eq 'acceptable') { + #XXX-TODO + #ok($valid, "$testname verify_message=$valid"); + } + elsif ($result eq 'invalid') { + ok(!$valid, "$testname verify_message=$valid"); + } + else { + ok(0, "UNEXPECTED result=$result"); + } + } + } +} + +if (0) { + 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($sig, $message, $sha); + if ($result eq 'valid') { + ok($valid, "$testname verify_message=$valid"); + } + elsif ($result eq 'acceptable') { + #XXX-TODO + #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"); + } + } + } +}