Skip to content
Snippets Groups Projects
Commit cd3117f7 authored by Thanh Bui's avatar Thanh Bui Committed by Thai Duong
Browse files

Add ECDSA implementation.

To test ECDSA, also add test vectors from Wycheproof.

Change-Id: I08157184e727acecf854b2d4dda766ae8e613217
ORIGINAL_AUTHOR=Thanh Bui <thanhb@google.com>
GitOrigin-RevId: adfb86b2ebb474386f3aa51906a3cfdf632977c3
parent 26714347
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,46 @@ package(
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
# ecdsa subtles
ECDSA_SRCS = [
"ecdsa/ecdsa.go",
"ecdsa/ecdsa_sign.go",
"ecdsa/ecdsa_verify.go",
"ecdsa/encoding.go",
]
ECDSA_TEST_SRCS = [
"ecdsa/ecdsa_test.go",
"ecdsa/ecdsa_sign_verify_test.go",
]
ECDSA_DEPS = [
":random",
":util",
"//go/tink",
"//go/util",
"//proto:common_go_proto",
"//proto:ecdsa_go_proto",
]
go_library(
name = "ecdsa",
srcs = ECDSA_SRCS,
deps = ECDSA_DEPS,
)
go_test(
name = "ecdsa_test",
srcs = ECDSA_TEST_SRCS,
data = [
"//testdata:ecdsa",
],
deps = ECDSA_DEPS + [
":ecdsa",
"//go/util:testutil",
],
)
# hmac subtle
HMAC_SRCS = [
"hmac/hmac.go",
......
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa
import (
"fmt"
"math/big"
commonpb "github.com/google/tink/proto/common_go_proto"
ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
)
var errUnsupportedEncoding = fmt.Errorf("ecdsa: unsupported encoding")
// ecdsaSignature is a struct holding r and s values of an ECDSA signature.
type EcdsaSignature struct {
R, S *big.Int
}
// newSignature creates a new ecdsaSignature object.
func NewSignature(r, s *big.Int) *EcdsaSignature {
return &EcdsaSignature{R: r, S: s}
}
// Encode converts the signature to the given encoding format.
// Only DER encoding is supported now.
func (sig *EcdsaSignature) Encode(encoding ecdsapb.EcdsaSignatureEncoding) ([]byte, error) {
switch encoding {
case ecdsapb.EcdsaSignatureEncoding_DER:
return asn1encode(sig)
default:
return nil, errUnsupportedEncoding
}
}
// NewSignatureFromBytes creates a new ECDSA signature using the given byte slice.
// The function assumes that the byte slice is the concatenation of the BigEndian
// representation of two big integer r and s.
func DecodeSignature(encodedBytes []byte,
encoding ecdsapb.EcdsaSignatureEncoding) (*EcdsaSignature, error) {
switch encoding {
case ecdsapb.EcdsaSignatureEncoding_DER:
return asn1decode(encodedBytes)
default:
return nil, errUnsupportedEncoding
}
}
// ValidatePrivateKey validates the given EcdsaPrivateKey proto.
func ValidatePrivateKey(privateKey *ecdsapb.EcdsaPrivateKey) error {
if privateKey == nil {
return fmt.Errorf("private key must not be nil")
}
if err := ValidatePublicKey(privateKey.PublicKey); err != nil {
return err
}
return nil
}
// ValidatePublicKey validates the given EcdsaPublicKey proto.
func ValidatePublicKey(publicKey *ecdsapb.EcdsaPublicKey) error {
if publicKey == nil {
return fmt.Errorf("public key must not be nil")
}
if err := ValidateParams(publicKey.Params); err != nil {
return err
}
return nil
}
// ValidateEcdsaParams validates ECDSA parameters.
// The hash's strength must not be weaker than the curve's strength.
// Only DER encoding is supported now.
func ValidateParams(params *ecdsapb.EcdsaParams) error {
switch params.Encoding {
case ecdsapb.EcdsaSignatureEncoding_DER:
break
default:
return errUnsupportedEncoding
}
switch params.Curve {
case commonpb.EllipticCurveType_NIST_P256:
if params.HashType != commonpb.HashType_SHA256 {
return fmt.Errorf("invalid hash type, expect SHA-256 or SHA-512")
}
case commonpb.EllipticCurveType_NIST_P384,
commonpb.EllipticCurveType_NIST_P521:
if params.HashType != commonpb.HashType_SHA512 {
return fmt.Errorf("invalid hash type, expect SHA-512")
}
default:
return fmt.Errorf("unsupported curve: %d", params.Curve)
}
return nil
}
\ No newline at end of file
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa
import (
"fmt"
"math/big"
"crypto/ecdsa"
"crypto/rand"
"github.com/google/tink/go/tink/tink"
"github.com/google/tink/go/subtle/util"
ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
commonpb "github.com/google/tink/proto/common_go_proto"
)
// ecdsaSign is an implementation of PublicKeySign for ECDSA.
// At the moment, the implementation only accepts DER encoding.
type ecdsaSign struct {
privateKey *ecdsa.PrivateKey
hashType commonpb.HashType
encoding ecdsapb.EcdsaSignatureEncoding
}
// Assert that ecdsaSign implements the PublicKeySign interface.
var _ tink.PublicKeySign = (*ecdsaSign)(nil)
// NewEcdsaSign creates a new instance of EcdsaSign.
func NewEcdsaSign(privateKey *ecdsapb.EcdsaPrivateKey) (*ecdsaSign, error) {
if err := ValidatePrivateKey(privateKey); err != nil {
return nil, fmt.Errorf("ecdsa_sign: %s", err)
}
params := privateKey.PublicKey.Params
publicKey := ecdsa.PublicKey{Curve: util.GetCurve(params.Curve), X: nil, Y: nil}
d := new(big.Int).SetBytes(privateKey.KeyValue)
return &ecdsaSign{
privateKey: &ecdsa.PrivateKey{PublicKey: publicKey, D: d},
hashType: params.HashType,
encoding: params.Encoding,
}, nil
}
// Sign computes a signature for the given data.
func (e *ecdsaSign) Sign(data []byte) ([]byte, error) {
hashed := util.GetHash(e.hashType, data)
r, s, err := ecdsa.Sign(rand.Reader, e.privateKey, hashed)
if err != nil {
return nil, fmt.Errorf("ecdsa_sign: signing failed: %s", err)
}
// format the signature
sig := NewSignature(r, s)
ret, err := sig.Encode(e.encoding)
if err != nil {
return nil, fmt.Errorf("ecdsa_sign: signing failed: %s", err)
}
return ret, nil
}
\ No newline at end of file
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa_test
import (
"fmt"
"testing"
"os"
"encoding/json"
"encoding/hex"
// "reflect"
"github.com/google/tink/go/subtle/random"
"github.com/google/tink/go/subtle/ecdsa"
subtleUtil "github.com/google/tink/go/subtle/util"
"github.com/google/tink/go/util/util"
"github.com/google/tink/go/util/testutil"
ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
commonpb "github.com/google/tink/proto/common_go_proto"
)
var _ = fmt.Println
func TestSignVerify(t *testing.T) {
data := random.GetRandomBytes(20)
priv := testutil.NewP256EcdsaPrivateKey()
signer, err := ecdsa.NewEcdsaSign(priv)
if err != nil {
t.Errorf("unexpected error when creating EcdsaSign: %s", err)
}
verifier, err := ecdsa.NewEcdsaVerify(priv.PublicKey)
if err != nil {
t.Errorf("unexpected error when creating EcdsaVerify: %s", err)
}
signature, err := signer.Sign(data)
if err != nil {
t.Errorf("unexpected error when signing: %s", err)
}
err = verifier.Verify(signature, data)
if err != nil {
t.Errorf("unexpected error when verifying: %s", err)
}
}
type testData struct {
Algorithm string
GeneratorVersion string
NumberOfTests uint32
TestGroups []*testGroup
}
type testGroup struct {
KeyDer string
KeyPem string
Sha string
Type string
Key *testKey
Tests []*testcase
}
type testKey struct {
Curve string
Type string
Wx string
Wy string
}
type testcase struct {
Comment string
Message string
Result string
Sig string
TcId uint32
}
func TestVectors(t *testing.T) {
f, err := os.Open("../../testdata/ecdsa_test.json")
if err != nil {
t.Errorf("cannot open file: %s", err)
}
parser := json.NewDecoder(f)
content := new(testData)
if err := parser.Decode(content); err != nil {
t.Errorf("cannot decode content of file: %s", err)
}
for _, g := range content.TestGroups {
hashType := subtleUtil.HashNameToHashType(g.Sha)
curveType := subtleUtil.CurveNameToCurveType(g.Key.Curve)
if hashType == commonpb.HashType_UNKNOWN_HASH ||
curveType == commonpb.EllipticCurveType_UNKNOWN_CURVE {
continue
}
encoding := ecdsapb.EcdsaSignatureEncoding_DER
x, err := subtleUtil.NewBigIntFromHex(g.Key.Wx)
if err != nil {
t.Errorf("cannot decode wx: %s", err)
}
y, err := subtleUtil.NewBigIntFromHex(g.Key.Wy)
if err != nil {
t.Errorf("cannot decode wy: %s", err)
}
pub := util.NewEcdsaPublicKey(0, hashType, curveType, encoding, x.Bytes(), y.Bytes())
verifier, err := ecdsa.NewEcdsaVerify(pub)
if err != nil {
continue
}
for _, tc := range g.Tests {
message, err := hex.DecodeString(tc.Message)
if err != nil {
t.Errorf("cannot decode message in test case %d: %s", tc.TcId, err)
}
sig, err := hex.DecodeString(tc.Sig)
if err != nil {
t.Errorf("cannot decode signature in test case %d: %s", tc.TcId, err)
}
err = verifier.Verify(sig, message)
if (tc.Result == "valid" && err != nil) ||
(tc.Result == "invalid" && err == nil) {
fmt.Println("failed in test case ", tc.TcId, err)
}
}
}
}
\ No newline at end of file
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa_test
import (
"fmt"
"testing"
"math/big"
"encoding/asn1"
. "github.com/google/tink/go/subtle/ecdsa"
"github.com/google/tink/go/subtle/random"
"github.com/google/tink/go/util/util"
commonpb "github.com/google/tink/proto/common_go_proto"
ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
)
var _ = fmt.Println
func TestEncodeDecode(t *testing.T) {
nTest := 1000
for i := 0; i < nTest; i++ {
sig := newRandomSignature()
encoding := ecdsapb.EcdsaSignatureEncoding_DER
encoded, err := sig.Encode(encoding)
if err != nil {
t.Errorf("unexpected error during encoding: %s", err)
}
// first byte is 0x30
if encoded[0] != byte(0x30) {
t.Errorf("first byte is incorrect, expected 48, got %v", encoded[0])
}
// tag is 2
if encoded[2] != byte(2) || encoded[4+encoded[3]] != byte(2) {
t.Errorf("expect tag to be 2 (integer), got %d and %d", encoded[2], encoded[4+encoded[3]])
}
// length
if len(encoded) != int(encoded[1])+2 {
t.Errorf("incorrect length, expected %d, got %d", len(encoded), encoded[1]+2)
}
decodedSig, err := DecodeSignature(encoded, encoding)
if err != nil {
t.Errorf("unexpected error during decoding: %s", err)
}
if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 {
t.Errorf("decoded signature doesn't match original value")
}
}
}
func TestEncodeWithInvalidInput(t *testing.T) {
sig := newRandomSignature()
_, err := sig.Encode(ecdsapb.EcdsaSignatureEncoding_UNKNOWN_ENCODING)
if err == nil {
t.Errorf("expect an error when encoding is invalid")
}
}
func TestDecodeWithInvalidInput(t *testing.T) {
var sig *EcdsaSignature
var encoded []byte
encoding := ecdsapb.EcdsaSignatureEncoding_DER
// modified first byte
sig = newRandomSignature()
encoded, _ = sig.Encode(encoding)
encoded[0] = 0x31
if _, err := DecodeSignature(encoded, encoding); err == nil {
t.Errorf("expect an error when first byte is not 0x30")
}
// modified tag
sig = newRandomSignature()
encoded, _ = sig.Encode(encoding)
encoded[2] = encoded[2] + 1
if _, err := DecodeSignature(encoded, encoding); err == nil {
t.Errorf("expect an error when tag is modified")
}
// modified length
sig = newRandomSignature()
encoded, _ = sig.Encode(encoding)
encoded[1] = encoded[1] + 1
if _, err := DecodeSignature(encoded, encoding); err == nil {
t.Errorf("expect an error when length is modified")
}
// append unused 0s
sig = newRandomSignature()
encoded, _ = sig.Encode(encoding)
tmp := make([]byte, len(encoded)+4)
copy(tmp, encoded)
if _, err := DecodeSignature(tmp, encoding); err == nil {
t.Errorf("expect an error when unused 0s are appended to signature")
}
// a struct with three numbers
randomStruct := struct{X, Y, Z *big.Int}{
X: new(big.Int).SetBytes(random.GetRandomBytes(32)),
Y: new(big.Int).SetBytes(random.GetRandomBytes(32)),
Z: new(big.Int).SetBytes(random.GetRandomBytes(32)),
}
encoded, _ = asn1.Marshal(randomStruct)
if _, err := DecodeSignature(encoded, encoding); err == nil {
t.Errorf("expect an error when input is not an EcdsaSignature")
}
}
func TestValidatePrivateKey(t *testing.T) {
// valid
params := genValidParams()
for i := 0; i < len(params); i++ {
pub := new(ecdsapb.EcdsaPublicKey)
pub.Params = params[i]
priv := new(ecdsapb.EcdsaPrivateKey)
priv.PublicKey = pub
if err := ValidatePrivateKey(priv); err != nil {
t.Errorf("unexpected error for valid private key: %s, i = %d", err, i)
}
}
// nil private key
if err := ValidatePrivateKey(nil); err == nil {
t.Errorf("expected an error when private key is nil")
}
// nil public key
if err := ValidatePrivateKey(util.NewEcdsaPrivateKey(0, nil, nil)); err == nil {
t.Errorf("expected an error when public key is nil")
}
// invalid params
params = genInvalidParams()
for i := 0; i < len(params); i++ {
pub := new(ecdsapb.EcdsaPublicKey)
pub.Params = params[i]
priv := new(ecdsapb.EcdsaPrivateKey)
priv.PublicKey = pub
if err := ValidatePrivateKey(priv); err == nil {
t.Errorf("expected an error when private key is invalid, i = %d", i)
}
}
}
func TestValidatePublicKey(t *testing.T) {
// valid
params := genValidParams()
for i := 0; i < len(params); i++ {
pub := new(ecdsapb.EcdsaPublicKey)
pub.Params = params[i]
if err := ValidatePublicKey(pub); err != nil {
t.Errorf("unexpected error for valid public key: %s, i = %d", err, i)
}
}
// nil public key
if err := ValidatePublicKey(nil); err == nil {
t.Errorf("expected an error when public key is nil")
}
// invalid params
params = genInvalidParams()
for i := 0; i < len(params); i++ {
pub := new(ecdsapb.EcdsaPublicKey)
pub.Params = params[i]
if err := ValidatePublicKey(pub); err == nil {
t.Errorf("expected an error when public key is invalid, i = %d", i)
}
}
}
func TestValidateParams(t *testing.T) {
params := genValidParams()
for i := 0; i < len(params); i++ {
if err := ValidateParams(params[i]); err != nil {
t.Errorf("unexpected error for valid params: %s, i = %d", err, i)
}
}
params = genInvalidParams()
for i := 0; i < len(params); i++ {
if err := ValidateParams(params[i]); err == nil {
t.Errorf("expect an error when params are invalid, i = %d", i)
}
}
}
func genInvalidParams() []*ecdsapb.EcdsaParams {
return []*ecdsapb.EcdsaParams{
// invalid encoding
util.NewEcdsaParams(commonpb.HashType_SHA256,
commonpb.EllipticCurveType_NIST_P256,
ecdsapb.EcdsaSignatureEncoding_UNKNOWN_ENCODING),
// invalid curve
util.NewEcdsaParams(commonpb.HashType_SHA256,
commonpb.EllipticCurveType_UNKNOWN_CURVE,
ecdsapb.EcdsaSignatureEncoding_DER),
// invalid hash: P256 and SHA-512
util.NewEcdsaParams(commonpb.HashType_SHA512,
commonpb.EllipticCurveType_NIST_P256,
ecdsapb.EcdsaSignatureEncoding_DER),
// invalid hash: P521 and SHA-256
util.NewEcdsaParams(commonpb.HashType_SHA256,
commonpb.EllipticCurveType_NIST_P521,
ecdsapb.EcdsaSignatureEncoding_DER),
// invalid hash: P384 and SHA-256
util.NewEcdsaParams(commonpb.HashType_SHA256,
commonpb.EllipticCurveType_NIST_P384,
ecdsapb.EcdsaSignatureEncoding_DER),
}
}
func genValidParams() []*ecdsapb.EcdsaParams {
return []*ecdsapb.EcdsaParams{
util.NewEcdsaParams(commonpb.HashType_SHA256,
commonpb.EllipticCurveType_NIST_P256,
ecdsapb.EcdsaSignatureEncoding_DER),
util.NewEcdsaParams(commonpb.HashType_SHA512,
commonpb.EllipticCurveType_NIST_P384,
ecdsapb.EcdsaSignatureEncoding_DER),
util.NewEcdsaParams(commonpb.HashType_SHA512,
commonpb.EllipticCurveType_NIST_P521,
ecdsapb.EcdsaSignatureEncoding_DER),
}
}
func newRandomSignature() *EcdsaSignature {
r := new(big.Int).SetBytes(random.GetRandomBytes(32))
s := new(big.Int).SetBytes(random.GetRandomBytes(32))
return NewSignature(r, s)
}
\ No newline at end of file
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa
import (
"fmt"
"math/big"
"crypto/ecdsa"
"github.com/google/tink/go/tink/tink"
"github.com/google/tink/go/subtle/util"
ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
commonpb "github.com/google/tink/proto/common_go_proto"
)
var ErrInvalidSignature = fmt.Errorf("ecdsa_verify: invalid signature")
// ecdsaVerify is an implementation of PublicKeyVerify for ECDSA.
// At the moment, the implementation only accepts signatures with strict DER encoding.
type ecdsaVerify struct {
publicKey *ecdsa.PublicKey
hashType commonpb.HashType
encoding ecdsapb.EcdsaSignatureEncoding
}
// Assert that ecdsaVerify implements the PublicKeyVerify interface.
var _ tink.PublicKeyVerify = (*ecdsaVerify)(nil)
// NewEcdsaVerify creates a new instance of ecdsaVerify.
func NewEcdsaVerify(publicKey *ecdsapb.EcdsaPublicKey) (*ecdsaVerify, error) {
if err := ValidatePublicKey(publicKey); err != nil {
return nil, fmt.Errorf("ecdsa_sign: %s", err)
}
params := publicKey.Params
x := new(big.Int).SetBytes(publicKey.X)
y := new(big.Int).SetBytes(publicKey.Y)
return &ecdsaVerify{
publicKey: &ecdsa.PublicKey{Curve: util.GetCurve(params.Curve), X: x, Y: y},
hashType: params.HashType,
encoding: params.Encoding,
}, nil
}
// Verify verifies whether the given signature is valid for the given data.
// It returns an error if the signature is not valid; nil otherwise.
func (e *ecdsaVerify) Verify(signatureBytes []byte, data []byte) error {
signature, err := DecodeSignature(signatureBytes, e.encoding)
if err != nil {
return ErrInvalidSignature
}
hashed := util.GetHash(e.hashType, data)
valid := ecdsa.Verify(e.publicKey, hashed, signature.R, signature.S)
if valid {
return nil
}
return ErrInvalidSignature
}
// Copyright 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package ecdsa
import (
"bytes"
"encoding/asn1"
"fmt"
)
var errInvalidLength = fmt.Errorf("invalid length")
// asn1encode encodes the given ECDSA signature using ASN.1 encoding.
func asn1encode(sig *EcdsaSignature) ([]byte, error) {
ret, err := asn1.Marshal(*sig)
if err != nil {
return nil, fmt.Errorf("asn.1 encoding failed")
}
return ret, nil
}
var errAsn1Decoding = fmt.Errorf("asn.1 decoding failed")
// asn1decode verifies the given ECDSA signature and decodes it if it is valid.
// Since asn1.Unmarshal() doesn't do a strict verification on its input, it will
// accept signatures with trailing data. Thus, we add an additional check to make sure
// that the input follows strict DER encoding: after unmarshalling the signature bytes,
// we marshal the obtained signature object again. Since DER encoding is deterministic,
// we expect that the obtained bytes would be equal to the input.
func asn1decode(b []byte) (*EcdsaSignature, error) {
// parse the signature
sig := new(EcdsaSignature)
_, err := asn1.Unmarshal(b, sig)
if err != nil {
return nil, errAsn1Decoding
}
// encode the signature again
encoded, err := asn1.Marshal(*sig)
if err != nil {
return nil, errAsn1Decoding
}
if !bytes.Equal(b, encoded) {
return nil, errAsn1Decoding
}
return sig, nil
}
\ No newline at end of file
......@@ -16,12 +16,14 @@
package util
import (
"errors"
"fmt"
"hash"
"math/big"
"encoding/hex"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/elliptic"
commonpb "github.com/google/tink/proto/common_go_proto"
)
......@@ -34,11 +36,77 @@ func ValidateVersion(version uint32, maxExpected uint32) error {
msg := fmt.Sprintf("key has version %v; " +
"only keys with version in range [0..%v] are supported",
version, maxExpected)
return errors.New("subtle/util: " + msg)
return fmt.Errorf("subtle/util: " + msg)
}
return nil
}
/**
* Checks if {@code sizeInBytes} is a valid AES key size.
*/
func ValidateAesKeySize(sizeInBytes uint32) error {
switch sizeInBytes {
case 16, 24, 32:
return nil
default:
return fmt.Errorf("invalid AES key size %d", sizeInBytes)
}
}
/**
* Checks if {@code curveType} is valid.
*/
func ValidateCurveType(curveType commonpb.EllipticCurveType) error {
switch curveType {
case commonpb.EllipticCurveType_NIST_P256,
commonpb.EllipticCurveType_NIST_P384,
commonpb.EllipticCurveType_NIST_P521:
return nil
default:
return fmt.Errorf("unsupported curve type: %v", curveType)
}
}
/**
* Checks if {@code hashType} is supported.
*/
func ValidateHashType(hashType commonpb.HashType) error {
switch hashType {
case commonpb.HashType_SHA1,
commonpb.HashType_SHA256,
commonpb.HashType_SHA512:
return nil
default:
return fmt.Errorf("unsupported hash type: %v", hashType)
}
}
func HashNameToHashType(name string) commonpb.HashType {
switch name {
case "SHA-256":
return commonpb.HashType_SHA256
case "SHA-512":
return commonpb.HashType_SHA512
case "SHA-1":
return commonpb.HashType_SHA1
default:
return commonpb.HashType_UNKNOWN_HASH
}
}
func CurveNameToCurveType(name string) commonpb.EllipticCurveType {
switch name {
case "secp256r1":
return commonpb.EllipticCurveType_NIST_P256
case "secp384r1":
return commonpb.EllipticCurveType_NIST_P384
case "secp521r1":
return commonpb.EllipticCurveType_NIST_P521
default:
return commonpb.EllipticCurveType_UNKNOWN_CURVE
}
}
/**
* @return the corresponding hash function of {@code hashType}
*/
......@@ -55,14 +123,43 @@ func GetHashFunc(hashType commonpb.HashType) func() hash.Hash {
}
}
/**
* Checks if {@code sizeInBytes} is a valid AES key size.
*/
func ValidateAesKeySize(sizeInBytes uint32) error {
switch sizeInBytes {
case 16, 24, 32:
return nil
// GetCurve returns the curve object that corresponds to the given curve type.
// It returns null if the curve type is not supported.
func GetCurve(curveType commonpb.EllipticCurveType) elliptic.Curve {
switch curveType {
case commonpb.EllipticCurveType_NIST_P224:
return elliptic.P224()
case commonpb.EllipticCurveType_NIST_P256:
return elliptic.P256()
case commonpb.EllipticCurveType_NIST_P384:
return elliptic.P384()
case commonpb.EllipticCurveType_NIST_P521:
return elliptic.P521()
default:
return fmt.Errorf("invalid AES key size %d", sizeInBytes)
return nil
}
}
// GetHash calculates a hash of the given data using the given hash function.
func GetHash(hashType commonpb.HashType, data []byte) []byte {
hashFunc := GetHashFunc(hashType)
if hashFunc == nil {
return nil
}
h := hashFunc()
h.Write(data)
ret := h.Sum(nil)
return ret
}
func NewBigIntFromHex(s string) (*big.Int, error) {
if len(s)%2 == 1 {
s = "0" + s
}
b, err := hex.DecodeString(s)
if err != nil {
return nil, err
}
ret := new(big.Int).SetBytes(b)
return ret, nil
}
\ No newline at end of file
......@@ -16,9 +16,31 @@
package testutil
import (
"fmt"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"github.com/google/tink/go/util/util"
// "github.com/google/tink/go/tink/tink"
// "github.com/google/tink/go/mac/mac"
. "github.com/google/tink/proto/tink_go_proto"
// . "github.com/google/tink/proto/hmac_go_proto"
. "github.com/google/tink/proto/common_go_proto"
// . "github.com/google/tink/proto/aes_gcm_go_proto"
. "github.com/google/tink/proto/ecdsa_go_proto"
)
// DummyAead is a dummy implementation of Aead interface.
type DummyAead struct {}
func (_ *DummyAead) Encrypt(plaintext []byte, additionalData []byte) ([]byte, error) {
return nil, fmt.Errorf("dummy aead encrypt")
}
func (_ *DummyAead) Decrypt(ciphertext []byte, additionalData []byte) ([]byte, error) {
return nil, fmt.Errorf("dummy aead decrypt")
}
// DummyMac is a dummy implementation of Mac interface.
type DummyMac struct {
Name string
......@@ -35,6 +57,17 @@ func (h *DummyMac) VerifyMac(mac []byte, data []byte) (bool, error) {
return true, nil
}
// Return a key set with 4 keys.
func NewTestKeyset(keyData *KeyData,
primaryOutputPrefixType OutputPrefixType) *Keyset {
primaryKey := util.NewKey(keyData, KeyStatusType_ENABLED, 42, primaryOutputPrefixType)
rawKey := util.NewKey(keyData, KeyStatusType_ENABLED, 43, OutputPrefixType_RAW)
legacyKey := util.NewKey(keyData, KeyStatusType_ENABLED, 44, OutputPrefixType_LEGACY)
tinkKey := util.NewKey(keyData, KeyStatusType_ENABLED, 45, OutputPrefixType_TINK)
keys := []*Keyset_Key{primaryKey, rawKey, legacyKey, tinkKey}
return util.NewKeyset(primaryKey.KeyId, keys)
}
func NewDummyKey(keyId int, status KeyStatusType, outputPrefixType OutputPrefixType) *Keyset_Key {
return &Keyset_Key{
KeyData: new(KeyData),
......@@ -42,4 +75,14 @@ func NewDummyKey(keyId int, status KeyStatusType, outputPrefixType OutputPrefixT
KeyId: uint32(keyId),
OutputPrefixType: outputPrefixType,
}
}
func NewP256EcdsaPrivateKey() *EcdsaPrivateKey {
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
publicKey := util.NewEcdsaPublicKey(0,
HashType_SHA256,
EllipticCurveType_NIST_P256,
EcdsaSignatureEncoding_DER,
priv.X.Bytes(), priv.Y.Bytes())
return util.NewEcdsaPrivateKey(0, publicKey, priv.D.Bytes())
}
\ No newline at end of file
......@@ -22,6 +22,11 @@ import (
"github.com/google/tink/go/util/testutil"
)
func TestDummyAead(t *testing.T) {
// Assert that DummyAead implements the Aead interface.
var _ tink.Aead = (*testutil.DummyAead)(nil)
}
func TestDummyMac(t *testing.T) {
// Assert that DummyMac implements the Aead interface.
var _ tink.Mac = (*testutil.DummyMac)(nil)
......
......@@ -18,6 +18,14 @@ filegroup(
],
)
filegroup(
name = "ecdsa",
testonly = 1,
srcs = [
"ecdsa_test.json",
],
)
filegroup(
name = "ecies_keysets",
testonly = 1,
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment