Sdm qmgrauth (#81)

Implement htpassword changes
This commit is contained in:
Stephen D Marshall
2020-03-27 10:09:41 +00:00
committed by GitHub Enterprise
parent 7f14cc2751
commit c8de2df2cf
383 changed files with 93261 additions and 41 deletions

32
vendor/golang.org/x/crypto/internal/subtle/aliasing.go generated vendored Normal file
View File

@@ -0,0 +1,32 @@
// Copyright 2018 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.
// +build !appengine
// Package subtle implements functions that are often useful in cryptographic
// code but require careful thought to use correctly.
package subtle // import "golang.org/x/crypto/internal/subtle"
import "unsafe"
// AnyOverlap reports whether x and y share memory at any (not necessarily
// corresponding) index. The memory beyond the slice length is ignored.
func AnyOverlap(x, y []byte) bool {
return len(x) > 0 && len(y) > 0 &&
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
}
// InexactOverlap reports whether x and y share memory at any non-corresponding
// index. The memory beyond the slice length is ignored. Note that x and y can
// have different lengths and still not have any inexact overlap.
//
// InexactOverlap can be used to implement the requirements of the crypto/cipher
// AEAD, Block, BlockMode and Stream interfaces.
func InexactOverlap(x, y []byte) bool {
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
return false
}
return AnyOverlap(x, y)
}

View File

@@ -0,0 +1,35 @@
// Copyright 2018 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.
// +build appengine
// Package subtle implements functions that are often useful in cryptographic
// code but require careful thought to use correctly.
package subtle // import "golang.org/x/crypto/internal/subtle"
// This is the Google App Engine standard variant based on reflect
// because the unsafe package and cgo are disallowed.
import "reflect"
// AnyOverlap reports whether x and y share memory at any (not necessarily
// corresponding) index. The memory beyond the slice length is ignored.
func AnyOverlap(x, y []byte) bool {
return len(x) > 0 && len(y) > 0 &&
reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() &&
reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer()
}
// InexactOverlap reports whether x and y share memory at any non-corresponding
// index. The memory beyond the slice length is ignored. Note that x and y can
// have different lengths and still not have any inexact overlap.
//
// InexactOverlap can be used to implement the requirements of the crypto/cipher
// AEAD, Block, BlockMode and Stream interfaces.
func InexactOverlap(x, y []byte) bool {
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
return false
}
return AnyOverlap(x, y)
}

View File

@@ -0,0 +1,50 @@
// Copyright 2018 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 subtle_test
import (
"testing"
"golang.org/x/crypto/internal/subtle"
)
var a, b [100]byte
var aliasingTests = []struct {
x, y []byte
anyOverlap, inexactOverlap bool
}{
{a[:], b[:], false, false},
{a[:], b[:0], false, false},
{a[:], b[:50], false, false},
{a[40:50], a[50:60], false, false},
{a[40:50], a[60:70], false, false},
{a[:51], a[50:], true, true},
{a[:], a[:], true, false},
{a[:50], a[:60], true, false},
{a[:], nil, false, false},
{nil, nil, false, false},
{a[:], a[:0], false, false},
{a[:10], a[:10:20], true, false},
{a[:10], a[5:10:20], true, true},
}
func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) {
any := subtle.AnyOverlap(x, y)
if any != anyOverlap {
t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any)
}
inexact := subtle.InexactOverlap(x, y)
if inexact != inexactOverlap {
t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any)
}
}
func TestAliasing(t *testing.T) {
for i, tt := range aliasingTests {
testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap)
testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap)
}
}

View File

@@ -0,0 +1,12 @@
This package runs a set of the Wycheproof tests provided by
https://github.com/google/wycheproof.
The JSON test files live in
https://github.com/google/wycheproof/tree/master/testvectors
and are being fetched and cached at a pinned version every time
these tests are run. To change the version of the wycheproof
repository that is being used for testing, update wycheproofModVer.
The structs for these tests are generated from the
schemas provided in https://github.com/google/wycheproof/tree/master/schemas
using https://github.com/a-h/generate.

View File

@@ -0,0 +1,127 @@
// 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
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
"testing"
)
func TestAesCbc(t *testing.T) {
// IndCpaTestVector
type IndCpaTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// the raw ciphertext (without IV)
Ct string `json:"ct,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// the initialization vector
Iv string `json:"iv,omitempty"`
// the key
Key string `json:"key,omitempty"`
// the plaintext
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// IndCpaTestGroup
type IndCpaTestGroup struct {
// the IV size in bits
IvSize int `json:"ivSize,omitempty"`
// the keySize in bits
KeySize int `json:"keySize,omitempty"`
// the expected size of the tag in bits
TagSize int `json:"tagSize,omitempty"`
Tests []*IndCpaTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*IndCpaTestGroup `json:"testGroups,omitempty"`
}
var root Root
readTestVector(t, "aes_cbc_pkcs5_test.json", &root)
for _, tg := range root.TestGroups {
tests:
for _, tv := range tg.Tests {
block, err := aes.NewCipher(decodeHex(tv.Key))
if err != nil {
t.Fatalf("#%d: %v", tv.TcId, err)
}
mode := cipher.NewCBCDecrypter(block, decodeHex(tv.Iv))
ct := decodeHex(tv.Ct)
if len(ct)%aes.BlockSize != 0 {
panic(fmt.Sprintf("#%d: ciphertext is not a multiple of the block size", tv.TcId))
}
mode.CryptBlocks(ct, ct) // decrypt the block in place
// Skip the tests that are broken due to bad padding. Panic if there are any
// tests left that are invalid for some other reason in the future, to
// evaluate what to do with those tests.
for _, flag := range tv.Flags {
if flag == "BadPadding" {
continue tests
}
}
if !shouldPass(tv.Result, tv.Flags, nil) {
panic(fmt.Sprintf("#%d: found an invalid test that is broken for some reason other than bad padding", tv.TcId))
}
// Remove the PKCS#5 padding from the given ciphertext to validate it
padding := ct[len(ct)-1]
paddingNum := int(padding)
for i := paddingNum; i > 0; i-- {
if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad
panic(fmt.Sprintf("#%d: bad padding at index=%d of %v", tv.TcId, i, ct))
}
}
ct = ct[:len(ct)-paddingNum]
if got, want := hex.EncodeToString(ct), tv.Msg; got != want {
t.Errorf("#%d, type: %s, comment: %q, decoded ciphertext not equal: %s, want %s", tv.TcId, tv.Result, tv.Comment, got, want)
}
}
}
}

View File

@@ -0,0 +1,148 @@
// 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
import (
"crypto/cipher"
"encoding/hex"
"testing"
"golang.org/x/crypto/chacha20poly1305"
)
func TestChaCha20Poly1305(t *testing.T) {
// AeadTestVector
type AeadTestVector struct {
// additional authenticated data
Aad string `json:"aad,omitempty"`
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// the ciphertext (without iv and tag)
Ct string `json:"ct,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// the nonce
Iv string `json:"iv,omitempty"`
// the key
Key string `json:"key,omitempty"`
// the plaintext
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// the authentication tag
Tag string `json:"tag,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// AeadTestGroup
type AeadTestGroup struct {
// the IV size in bits
IvSize int `json:"ivSize,omitempty"`
// the keySize in bits
KeySize int `json:"keySize,omitempty"`
// the expected size of the tag in bits
TagSize int `json:"tagSize,omitempty"`
Tests []*AeadTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*AeadTestGroup `json:"testGroups,omitempty"`
}
testAeadSealOpen := func(t *testing.T, aead cipher.AEAD, tv *AeadTestVector, recoverBadNonce func()) {
defer recoverBadNonce()
// Encrypt the message, then decrypt the new ciphertext and validate
// the decrypted message.
ciphertext := aead.Seal(nil, decodeHex(tv.Iv), decodeHex(tv.Msg), decodeHex(tv.Aad))
msg, err := aead.Open(nil, decodeHex(tv.Iv), ciphertext, decodeHex(tv.Aad))
if err != nil {
t.Fatalf("#%d: decryption failed: %v", tv.TcId, err)
}
if got, want := hex.EncodeToString(msg), tv.Msg; got != want {
t.Errorf("#%d: bad message after encrypting and decrypting: %s, want %v", tv.TcId, got, want)
}
// Decrypt the provided ciphertext and validate the decrypted message.
tv.Ct += tv.Tag // append the tag to the ciphertext
msg2, err := aead.Open(nil, decodeHex(tv.Iv), decodeHex(tv.Ct), decodeHex(tv.Aad))
wantPass := shouldPass(tv.Result, tv.Flags, nil)
if wantPass {
if err != nil {
t.Errorf("#%d, type: %s, comment: %q, decryption wanted success, got err: %v", tv.TcId, tv.Result, tv.Comment, err)
}
if got, want := hex.EncodeToString(ciphertext), tv.Ct; got != want {
t.Errorf("#%d: ciphertext doesn't match: %s, want=%s", tv.TcId, got, want)
}
if got, want := hex.EncodeToString(msg2), tv.Msg; got != want {
t.Errorf("#%d: bad message after decrypting ciphertext: %s, want %v", tv.TcId, got, want)
}
} else {
if err == nil {
t.Errorf("#%d, type: %s, comment: %q, decryption wanted error", tv.TcId, tv.Result, tv.Comment)
}
}
}
var root Root
readTestVector(t, "chacha20_poly1305_test.json", &root)
for _, tg := range root.TestGroups {
for _, tv := range tg.Tests {
aead, err := chacha20poly1305.New(decodeHex(tv.Key))
if err != nil {
t.Fatalf("#%d: %v", tv.TcId, err)
}
if tg.TagSize/8 != aead.Overhead() {
t.Fatalf("#%d: bad tag length", tv.TcId)
}
testAeadSealOpen(t, aead, tv, func() {
// A bad nonce causes a panic in AEAD.Seal and AEAD.Open,
// so should be recovered. Fail the test if it broke for
// some other reason.
if r := recover(); r != nil {
if tg.IvSize/8 == chacha20poly1305.NonceSize {
t.Errorf("#%d: unexpected panic", tv.TcId)
}
}
})
}
}
}

View File

@@ -0,0 +1,123 @@
// 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
import (
"crypto/dsa"
"testing"
wdsa "golang.org/x/crypto/internal/wycheproof/internal/dsa"
)
func TestDsa(t *testing.T) {
// AsnSignatureTestVector
type AsnSignatureTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// The message to sign
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// An ASN encoded signature for msg
Sig string `json:"sig,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// DsaPublicKey
type DsaPublicKey struct {
// the generator of the multiplicative subgroup
G string `json:"g,omitempty"`
// the key size in bits
KeySize int `json:"keySize,omitempty"`
// the modulus p
P string `json:"p,omitempty"`
// the order of the generator g
Q string `json:"q,omitempty"`
// the key type
Type string `json:"type,omitempty"`
// the public key value
Y string `json:"y,omitempty"`
}
// DsaTestGroup
type DsaTestGroup struct {
// unenocded DSA public key
Key *DsaPublicKey `json:"key,omitempty"`
// DER encoded public key
KeyDer string `json:"keyDer,omitempty"`
// Pem encoded public key
KeyPem string `json:"keyPem,omitempty"`
// the hash function used for DSA
Sha string `json:"sha,omitempty"`
Tests []*AsnSignatureTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*DsaTestGroup `json:"testGroups,omitempty"`
}
flagsShouldPass := map[string]bool{
// An encoded ASN.1 integer missing a leading zero is invalid, but accepted by some implementations.
"NoLeadingZero": false,
}
var root Root
readTestVector(t, "dsa_test.json", &root)
for _, tg := range root.TestGroups {
pub := decodePublicKey(tg.KeyDer).(*dsa.PublicKey)
h := parseHash(tg.Sha).New()
for _, sig := range tg.Tests {
h.Reset()
h.Write(decodeHex(sig.Msg))
hashed := h.Sum(nil)
hashed = hashed[:pub.Q.BitLen()/8] // Truncate to the byte-length of the subgroup (Q)
got := wdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig))
if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want {
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want)
}
}
}
}

View File

@@ -0,0 +1,166 @@
// 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
import (
"crypto/ecdsa"
"testing"
wecdsa "golang.org/x/crypto/internal/wycheproof/internal/ecdsa"
)
func TestEcdsa(t *testing.T) {
// AsnSignatureTestVector
type AsnSignatureTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// The message to sign
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// An ASN encoded signature for msg
Sig string `json:"sig,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// EcPublicKey
type EcPublicKey struct {
// the EC group used by this public key
Curve interface{} `json:"curve,omitempty"`
// the key size in bits
KeySize int `json:"keySize,omitempty"`
// the key type
Type string `json:"type,omitempty"`
// encoded public key point
Uncompressed string `json:"uncompressed,omitempty"`
// the x-coordinate of the public key point
Wx string `json:"wx,omitempty"`
// the y-coordinate of the public key point
Wy string `json:"wy,omitempty"`
}
// EcUnnamedGroup
type EcUnnamedGroup struct {
// coefficient a of the elliptic curve equation
A string `json:"a,omitempty"`
// coefficient b of the elliptic curve equation
B string `json:"b,omitempty"`
// the x-coordinate of the generator
Gx string `json:"gx,omitempty"`
// the y-coordinate of the generator
Gy string `json:"gy,omitempty"`
// the cofactor
H int `json:"h,omitempty"`
// the order of the generator
N string `json:"n,omitempty"`
// the order of the underlying field
P string `json:"p,omitempty"`
// an unnamed EC group over a prime field in Weierstrass form
Type string `json:"type,omitempty"`
}
// EcdsaTestGroup
type EcdsaTestGroup struct {
// unenocded EC public key
Key *EcPublicKey `json:"key,omitempty"`
// DER encoded public key
KeyDer string `json:"keyDer,omitempty"`
// Pem encoded public key
KeyPem string `json:"keyPem,omitempty"`
// the hash function used for ECDSA
Sha string `json:"sha,omitempty"`
Tests []*AsnSignatureTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*EcdsaTestGroup `json:"testGroups,omitempty"`
}
flagsShouldPass := map[string]bool{
// An encoded ASN.1 integer missing a leading zero is invalid, but accepted by some implementations.
"MissingZero": false,
// A signature using a weaker hash than the EC params is not a security risk, as long as the hash is secure.
// https://www.imperialviolet.org/2014/05/25/strengthmatching.html
"WeakHash": true,
}
// supportedCurves is a map of all elliptic curves supported
// by crypto/elliptic, which can subsequently be parsed and tested.
supportedCurves := map[string]bool{
"secp224r1": true,
"secp256r1": true,
"secp384r1": true,
"secp521r1": true,
}
var root Root
readTestVector(t, "ecdsa_test.json", &root)
for _, tg := range root.TestGroups {
curve := tg.Key.Curve.(string)
if !supportedCurves[curve] {
continue
}
pub := decodePublicKey(tg.KeyDer).(*ecdsa.PublicKey)
h := parseHash(tg.Sha).New()
for _, sig := range tg.Tests {
h.Reset()
h.Write(decodeHex(sig.Msg))
hashed := h.Sum(nil)
got := wecdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig))
if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want {
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want)
}
}
}
}

View File

@@ -0,0 +1,100 @@
// 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.
// +build go1.13
package wycheproof
import (
"testing"
"golang.org/x/crypto/ed25519"
)
func TestEddsa(t *testing.T) {
// Jwk the private key in webcrypto format
type Jwk struct {
}
// Key unencoded key pair
type Key struct {
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// SignatureTestVector
type SignatureTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// The message to sign
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// A signature for msg
Sig string `json:"sig,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// EddsaTestGroup
type EddsaTestGroup struct {
// the private key in webcrypto format
Jwk *Jwk `json:"jwk,omitempty"`
// unencoded key pair
Key *Key `json:"key,omitempty"`
// Asn encoded public key
KeyDer string `json:"keyDer,omitempty"`
// Pem encoded public key
KeyPem string `json:"keyPem,omitempty"`
Tests []*SignatureTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*EddsaTestGroup `json:"testGroups,omitempty"`
}
var root Root
readTestVector(t, "eddsa_test.json", &root)
for _, tg := range root.TestGroups {
pub := decodePublicKey(tg.KeyDer).(ed25519.PublicKey)
for _, sig := range tg.Tests {
got := ed25519.Verify(pub, decodeHex(sig.Msg), decodeHex(sig.Sig))
if want := shouldPass(sig.Result, sig.Flags, nil); got != want {
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want)
}
}
}
}

View File

@@ -0,0 +1,111 @@
// 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
import (
"bytes"
"io"
"testing"
"golang.org/x/crypto/hkdf"
)
func TestHkdf(t *testing.T) {
// HkdfTestVector
type HkdfTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// the key (input key material)
Ikm string `json:"ikm,omitempty"`
// additional information used in the key derivation
Info string `json:"info,omitempty"`
// the generated bytes (output key material)
Okm string `json:"okm,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// the salt for the key derivation
Salt string `json:"salt,omitempty"`
// the size of the output in bytes
Size int `json:"size,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// HkdfTestGroup
type HkdfTestGroup struct {
// the size of the ikm in bits
KeySize int `json:"keySize,omitempty"`
Tests []*HkdfTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*HkdfTestGroup `json:"testGroups,omitempty"`
}
fileHashAlgorithms := map[string]string{
"hkdf_sha1_test.json": "SHA-1",
"hkdf_sha256_test.json": "SHA-256",
"hkdf_sha384_test.json": "SHA-384",
"hkdf_sha512_test.json": "SHA-512",
}
for f := range fileHashAlgorithms {
var root Root
readTestVector(t, f, &root)
for _, tg := range root.TestGroups {
for _, tv := range tg.Tests {
h := parseHash(fileHashAlgorithms[f]).New
hkdf := hkdf.New(h, decodeHex(tv.Ikm), decodeHex(tv.Salt), decodeHex(tv.Info))
key := make([]byte, tv.Size)
wantPass := shouldPass(tv.Result, tv.Flags, nil)
_, err := io.ReadFull(hkdf, key)
if (err == nil) != wantPass {
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t, got: %v", tv.TcId, tv.Result, tv.Comment, wantPass, err)
}
if err != nil {
continue // don't validate output text if reading failed
}
if got, want := key, decodeHex(tv.Okm); !bytes.Equal(got, want) {
t.Errorf("tcid: %d, type: %s, comment: %q, output bytes don't match", tv.TcId, tv.Result, tv.Comment)
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
// 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 dsa provides an internal version of dsa.Verify
// that is used for the Wycheproof tests.
package dsa
import (
"crypto/dsa"
"math/big"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
)
// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the
// public key, pub. Its return value records whether the signature is valid.
func VerifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool {
var (
r, s = &big.Int{}, &big.Int{}
inner cryptobyte.String
)
input := cryptobyte.String(sig)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1Integer(r) ||
!inner.ReadASN1Integer(s) ||
!inner.Empty() {
return false
}
return dsa.Verify(pub, hash, r, s)
}

View File

@@ -0,0 +1,33 @@
// 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 ecdsa provides an internal version of ecdsa.Verify
// that is used for the Wycheproof tests.
package ecdsa
import (
"crypto/ecdsa"
"math/big"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
)
// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the
// public key, pub. Its return value records whether the signature is valid.
func VerifyASN1(pub *ecdsa.PublicKey, hash, sig []byte) bool {
var (
r, s = &big.Int{}, &big.Int{}
inner cryptobyte.String
)
input := cryptobyte.String(sig)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1Integer(r) ||
!inner.ReadASN1Integer(s) ||
!inner.Empty() {
return false
}
return ecdsa.Verify(pub, hash, r, s)
}

View File

@@ -0,0 +1,164 @@
// 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
import (
"crypto/rsa"
"testing"
)
func TestRsaPss(t *testing.T) {
// KeyJwk Public key in JWK format
type KeyJwk struct {
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// SignatureTestVector
type SignatureTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// The message to sign
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// A signature for msg
Sig string `json:"sig,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// RsassaPkcs1TestGroup
type RsassaPkcs1TestGroup struct {
// The private exponent
D string `json:"d,omitempty"`
// The public exponent
E string `json:"e,omitempty"`
// ASN encoding of the sequence [n, e]
KeyAsn string `json:"keyAsn,omitempty"`
// ASN encoding of the public key
KeyDer string `json:"keyDer,omitempty"`
// Public key in JWK format
KeyJwk *KeyJwk `json:"keyJwk,omitempty"`
// Pem encoded public key
KeyPem string `json:"keyPem,omitempty"`
// the size of the modulus in bits
KeySize int `json:"keySize,omitempty"`
// The modulus of the key
N string `json:"n,omitempty"`
// The salt length
SLen int `json:"sLen,omitempty"`
// the hash function used for the message
Sha string `json:"sha,omitempty"`
Tests []*SignatureTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"`
}
flagsShouldPass := map[string]bool{
// A signature using a weaker hash than the EC params is not a security risk, as long as the hash is secure.
// https://www.imperialviolet.org/2014/05/25/strengthmatching.html
"WeakHash": true,
}
// filesOverrideToPassZeroSLen is a map of all test files
// and which TcIds that should be overriden to pass if the
// rsa.PSSOptions.SaltLength is zero.
// These tests expect a failure with a PSSOptions.SaltLength: 0
// and a signature that uses a different salt length. However,
// a salt length of 0 is defined as rsa.PSSSaltLengthAuto which
// works deterministically to auto-detect the length when
// verifying, so these tests actually pass as they should.
filesOverrideToPassZeroSLen := map[string][]int{
"rsa_pss_2048_sha1_mgf1_20_test.json": []int{46, 47},
"rsa_pss_2048_sha256_mgf1_0_test.json": []int{67, 68},
"rsa_pss_2048_sha256_mgf1_32_test.json": []int{67, 68},
"rsa_pss_2048_sha512_256_mgf1_28_test.json": []int{13, 14, 15},
"rsa_pss_2048_sha512_256_mgf1_32_test.json": []int{13, 14},
"rsa_pss_3072_sha256_mgf1_32_test.json": []int{67, 68},
"rsa_pss_4096_sha256_mgf1_32_test.json": []int{67, 68},
"rsa_pss_4096_sha512_mgf1_32_test.json": []int{136, 137},
// "rsa_pss_misc_test.json": nil, // TODO: This ones seems to be broken right now, but can enable later on.
}
for f := range filesOverrideToPassZeroSLen {
var root Root
readTestVector(t, f, &root)
for _, tg := range root.TestGroups {
pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey)
ch := parseHash(tg.Sha)
h := ch.New()
opts := &rsa.PSSOptions{
Hash: ch,
SaltLength: rsa.PSSSaltLengthAuto,
}
// Run all the tests twice: the first time with the salt length
// as PSSSaltLengthAuto, and the second time with the salt length
// explictily set to tg.SLen.
for i := 0; i < 2; i++ {
for _, sig := range tg.Tests {
h.Reset()
h.Write(decodeHex(sig.Msg))
hashed := h.Sum(nil)
err := rsa.VerifyPSS(pub, ch, hashed, decodeHex(sig.Sig), opts)
want := shouldPass(sig.Result, sig.Flags, flagsShouldPass)
if opts.SaltLength == 0 {
for _, id := range filesOverrideToPassZeroSLen[f] {
if sig.TcId == id {
want = true
break
}
}
}
if (err == nil) != want {
t.Errorf("file: %v, tcid: %d, type: %s, opts.SaltLength: %v, comment: %q, wanted success: %t", f, sig.TcId, sig.Result, opts.SaltLength, sig.Comment, want)
}
}
// Update opts.SaltLength for the second run of the tests.
opts.SaltLength = tg.SLen
}
}
}
}

View File

@@ -0,0 +1,123 @@
// 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
import (
"crypto/rsa"
"testing"
)
func TestRsa(t *testing.T) {
// KeyJwk Public key in JWK format
type KeyJwk struct {
}
// Notes a description of the labels used in the test vectors
type Notes struct {
}
// SignatureTestVector
type SignatureTestVector struct {
// A brief description of the test case
Comment string `json:"comment,omitempty"`
// A list of flags
Flags []string `json:"flags,omitempty"`
// The message to sign
Msg string `json:"msg,omitempty"`
// Test result
Result string `json:"result,omitempty"`
// A signature for msg
Sig string `json:"sig,omitempty"`
// Identifier of the test case
TcId int `json:"tcId,omitempty"`
}
// RsassaPkcs1TestGroup
type RsassaPkcs1TestGroup struct {
// The private exponent
D string `json:"d,omitempty"`
// The public exponent
E string `json:"e,omitempty"`
// ASN encoding of the sequence [n, e]
KeyAsn string `json:"keyAsn,omitempty"`
// ASN encoding of the public key
KeyDer string `json:"keyDer,omitempty"`
// Public key in JWK format
KeyJwk *KeyJwk `json:"keyJwk,omitempty"`
// Pem encoded public key
KeyPem string `json:"keyPem,omitempty"`
// the size of the modulus in bits
KeySize int `json:"keySize,omitempty"`
// The modulus of the key
N string `json:"n,omitempty"`
// the hash function used for the message
Sha string `json:"sha,omitempty"`
Tests []*SignatureTestVector `json:"tests,omitempty"`
Type interface{} `json:"type,omitempty"`
}
// Root
type Root struct {
// the primitive tested in the test file
Algorithm string `json:"algorithm,omitempty"`
// the version of the test vectors.
GeneratorVersion string `json:"generatorVersion,omitempty"`
// additional documentation
Header []string `json:"header,omitempty"`
// a description of the labels used in the test vectors
Notes *Notes `json:"notes,omitempty"`
// the number of test vectors in this test
NumberOfTests int `json:"numberOfTests,omitempty"`
Schema interface{} `json:"schema,omitempty"`
TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"`
}
flagsShouldPass := map[string]bool{
// Omitting the parameter field in an ASN encoded integer is a legacy behavior.
"MissingNull": false,
// Keys with a modulus less than 2048 bits are supported by crypto/rsa.
"SmallModulus": true,
// Small public keys are supported by crypto/rsa.
"SmallPublicKey": true,
}
var root Root
readTestVector(t, "rsa_signature_test.json", &root)
for _, tg := range root.TestGroups {
pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey)
ch := parseHash(tg.Sha)
h := ch.New()
for _, sig := range tg.Tests {
h.Reset()
h.Write(decodeHex(sig.Msg))
hashed := h.Sum(nil)
err := rsa.VerifyPKCS1v15(pub, ch, hashed, decodeHex(sig.Sig))
want := shouldPass(sig.Result, sig.Flags, flagsShouldPass)
if (err == nil) != want {
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want)
}
}
}
}

View File

@@ -0,0 +1,134 @@
// 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 https://github.com/google/wycheproof.
package wycheproof
import (
"crypto"
"crypto/x509"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"testing"
_ "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)
os.Exit(0)
}
// Download the JSON test files from github.com/google/wycheproof
// using `go mod download -json` so the cached source of the testdata
// can be used in the following tests.
path := "github.com/google/wycheproof@" + 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 {
log.Fatal(err)
}
// 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")
os.Exit(m.Run())
}
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 {
panic(err)
}
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
default:
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.
default:
panic(fmt.Sprintf("unexpected result: %v", result))
}
}