blob: d57a88c279e6579d4c6683685a74cb7d14991c90 [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package wycheproof runs a set of the Wycheproof tests
// provided by
package wycheproof
import (
_ "crypto/sha1"
_ "crypto/sha256"
_ "crypto/sha512"
const wycheproofModVer = "v0.0.0-20191126014559-06e5e105eeb9"
var wycheproofTestVectorsDir string
func TestMain(m *testing.M) {
if _, err := exec.LookPath("go"); err != nil {
log.Printf("skipping test because 'go' command is unavailable: %v", err)
if runtime.GOARCH == "386" || runtime.GOARCH == "arm" {
os.Exit(0) // skip tests
// Download the JSON test files from
// using `go mod download -json` so the cached source of the testdata
// can be used in the following tests.
path := "" + wycheproofModVer
cmd := exec.Command("go", "mod", "download", "-json", path)
// TODO: enable the sumdb once the Trybots proxy supports it.
cmd.Env = append(os.Environ(), "GONOSUMDB=*")
output, err := cmd.Output()
if err != nil {
log.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output)
var dm struct {
Dir string // absolute path to cached source root directory
if err := json.Unmarshal(output, &dm); err != nil {
// Now that the module has been downloaded, use the absolute path of the
// cached source as the root directory for all tests going forward.
wycheproofTestVectorsDir = filepath.Join(dm.Dir, "testvectors")
func readTestVector(t *testing.T, f string, dest interface{}) {
b, err := ioutil.ReadFile(filepath.Join(wycheproofTestVectorsDir, f))
if err != nil {
t.Fatalf("failed to read json file: %v", err)
if err := json.Unmarshal(b, &dest); err != nil {
t.Fatalf("failed to unmarshal json file: %v", err)
func decodeHex(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
return b
func decodePublicKey(der string) interface{} {
d := decodeHex(der)
pub, err := x509.ParsePKIXPublicKey(d)
if err != nil {
panic(fmt.Sprintf("failed to parse DER encoded public key: %v", err))
return pub
func parseHash(h string) crypto.Hash {
switch h {
case "SHA-1":
return crypto.SHA1
case "SHA-256":
return crypto.SHA256
case "SHA-224":
return crypto.SHA224
case "SHA-384":
return crypto.SHA384
case "SHA-512":
return crypto.SHA512
case "SHA-512/224":
return crypto.SHA512_224
case "SHA-512/256":
return crypto.SHA512_256
panic(fmt.Sprintf("could not identify SHA hash algorithm: %q", h))
// shouldPass returns whether or not the test should pass.
// flagsShouldPass is a map associated with whether or not
// a flag for an "acceptable" result should pass.
// Every possible flag value that's associated with an
// "acceptable" result should be explicitly specified,
// otherwise the test will panic.
func shouldPass(result string, flags []string, flagsShouldPass map[string]bool) bool {
switch result {
case "valid":
return true
case "invalid":
return false
case "acceptable":
for _, flag := range flags {
pass, ok := flagsShouldPass[flag]
if !ok {
panic(fmt.Sprintf("unspecified flag: %q", flag))
if !pass {
return false
return true // There are no flags, or all are meant to pass.
panic(fmt.Sprintf("unexpected result: %v", result))