Skip to content

Commit

Permalink
Use full primitives in signature key managers
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 714942030
Change-Id: I94049233cdd819d49bca402da7aa0ec205c1b841
  • Loading branch information
morambro authored and copybara-github committed Jan 13, 2025
1 parent 680497f commit d26c394
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 103 deletions.
27 changes: 15 additions & 12 deletions signature/ecdsa/signer_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"fmt"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/internal/internalapi"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
"github.com/tink-crypto/tink-go/v2/keyset"
subtleSignature "github.com/tink-crypto/tink-go/v2/signature/subtle"
"github.com/tink-crypto/tink-go/v2/subtle"
Expand All @@ -46,22 +48,23 @@ type signerKeyManager struct{}
// Primitive creates an [subtleSignature.ECDSASigner] for the given serialized
// [ecdsapb.EcdsaPrivateKey] proto.
func (km *signerKeyManager) Primitive(serializedKey []byte) (any, error) {
if len(serializedKey) == 0 {
return nil, errInvalidSignKey
}
key := new(ecdsapb.EcdsaPrivateKey)
if err := proto.Unmarshal(serializedKey, key); err != nil {
return nil, errInvalidSignKey
}
if err := km.validateKey(key); err != nil {
keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{
TypeUrl: signerTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
}, tinkpb.OutputPrefixType_RAW, 0)
if err != nil {
return nil, err
}
hash, curve, encoding := paramNames(key.GetPublicKey().GetParams())
ret, err := subtleSignature.NewECDSASigner(hash, curve, encoding, key.KeyValue)
key, err := protoserialization.ParseKey(keySerialization)
if err != nil {
return nil, fmt.Errorf("ecdsa_signer_key_manager: %s", err)
return nil, err
}
signerKey, ok := key.(*PrivateKey)
if !ok {
return nil, fmt.Errorf("ecdsa_signer_key_manager: invalid key type: got %T, want %T", key, (*PrivateKey)(nil))
}
return ret, nil
return NewSigner(signerKey, internalapi.Token{})
}

// NewKey creates a new [ecdsapb.EcdsaPrivateKey] according to specification
Expand Down
25 changes: 14 additions & 11 deletions signature/ecdsa/verifier_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"fmt"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/internal/internalapi"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
"github.com/tink-crypto/tink-go/v2/keyset"
"github.com/tink-crypto/tink-go/v2/signature/subtle"
ecdsapb "github.com/tink-crypto/tink-go/v2/proto/ecdsa_go_proto"
Expand All @@ -40,22 +42,23 @@ type verifierKeyManager struct{}
// Primitive creates an [subtleSignature.ECDSAVerifier] for the given
// serialized [ecdsapb.EcdsaPublicKey] proto.
func (km *verifierKeyManager) Primitive(serializedKey []byte) (any, error) {
if len(serializedKey) == 0 {
return nil, errInvalidVerifierKey
}
key := new(ecdsapb.EcdsaPublicKey)
if err := proto.Unmarshal(serializedKey, key); err != nil {
return nil, errInvalidVerifierKey
}
if err := km.validateKey(key); err != nil {
keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{
TypeUrl: verifierTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
}, tinkpb.OutputPrefixType_RAW, 0)
if err != nil {
return nil, err
}
hash, curve, encoding := paramNames(key.GetParams())
ret, err := subtle.NewECDSAVerifier(hash, curve, encoding, key.X, key.Y)
key, err := protoserialization.ParseKey(keySerialization)
if err != nil {
return nil, err
}
return ret, nil
verifierKey, ok := key.(*PublicKey)
if !ok {
return nil, fmt.Errorf("ecdsa_verifier_key_manager: invalid key type: got %T, want %T", key, (*PublicKey)(nil))
}
return NewVerifier(verifierKey, internalapi.Token{})
}

// NewKey is not implemented.
Expand Down
33 changes: 17 additions & 16 deletions signature/ed25519/signer_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import (
"io"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/internal/internalapi"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
"github.com/tink-crypto/tink-go/v2/keyset"
"github.com/tink-crypto/tink-go/v2/signature/subtle"
ed25519pb "github.com/tink-crypto/tink-go/v2/proto/ed25519_go_proto"
tinkpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto"
)
Expand All @@ -45,23 +46,23 @@ type signerKeyManager struct{}
// Primitive creates a [subtle.ED25519Signer] instance for the given serialized
// [ed25519pb.Ed25519PrivateKey] proto.
func (km *signerKeyManager) Primitive(serializedKey []byte) (any, error) {
if len(serializedKey) == 0 {
return nil, errInvalidSignKey
}
key := new(ed25519pb.Ed25519PrivateKey)

if err := proto.Unmarshal(serializedKey, key); err != nil {
return nil, errInvalidSignKey
}
if err := km.validateKey(key); err != nil {
keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{
TypeUrl: signerTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
}, tinkpb.OutputPrefixType_RAW, 0)
if err != nil {
return nil, err
}

ret, err := subtle.NewED25519Signer(key.KeyValue)
key, err := protoserialization.ParseKey(keySerialization)
if err != nil {
return nil, fmt.Errorf("%s", err)
return nil, err
}
signerKey, ok := key.(*PrivateKey)
if !ok {
return nil, fmt.Errorf("ed25519_signer_key_manager: invalid key type: got %T, want %T", key, (*PrivateKey)(nil))
}
return ret, nil
return NewSigner(signerKey, internalapi.Token{})
}

// NewKey creates a new [ed25519pb.Ed25519PrivateKey] according to
Expand Down Expand Up @@ -156,10 +157,10 @@ func (km *signerKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomne
// validateKey validates the given [ed25519pb.Ed25519PrivateKey].
func (km *signerKeyManager) validateKey(key *ed25519pb.Ed25519PrivateKey) error {
if err := keyset.ValidateKeyVersion(key.Version, signerKeyVersion); err != nil {
return fmt.Errorf("invalid key: %s", err)
return fmt.Errorf("ed25519_signer_key_manager: invalid key: %s", err)
}
if len(key.KeyValue) != ed25519.SeedSize {
return fmt.Errorf("invalid key length, got %d", len(key.KeyValue))
return fmt.Errorf("ed25519_signer_key_manager: invalid key length, got %d", len(key.KeyValue))
}
return nil
}
19 changes: 4 additions & 15 deletions signature/ed25519/signer_key_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/tink-crypto/tink-go/v2/signature/subtle"
"github.com/tink-crypto/tink-go/v2/subtle/random"
"github.com/tink-crypto/tink-go/v2/testutil"
"github.com/tink-crypto/tink-go/v2/tink"
ed25519pb "github.com/tink-crypto/tink-go/v2/proto/ed25519_go_proto"
tinkpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto"
)
Expand All @@ -46,23 +47,12 @@ func TestSignerKeyManagerGetPrimitiveBasic(t *testing.T) {
if err != nil {
t.Errorf("unexpect error in test case: %s ", err)
}
var s = tmp.(*subtle.ED25519Signer)
var s = tmp.(tink.Signer)

kmPub, err := registry.GetKeyManager(testutil.ED25519VerifierTypeURL)
v, err := subtle.NewED25519Verifier(pvtKey.GetPublicKey().GetKeyValue())
if err != nil {
t.Errorf("cannot obtain ED25519Signer key manager: %s", err)
t.Errorf("unexpected error when creating ED25519Verifier: %s", err)
}
pubKey := pvtKey.PublicKey
serializedKey, err = proto.Marshal(pubKey)
if err != nil {
t.Fatalf("proto.Marshal() err = %v, want nil", err)
}
tmp, err = kmPub.Primitive(serializedKey)
if err != nil {
t.Errorf("unexpect error in test case: %s ", err)
}
var v = tmp.(*subtle.ED25519Verifier)

data := random.GetRandomBytes(1281)
signature, err := s.Sign(data)
if err != nil {
Expand All @@ -72,7 +62,6 @@ func TestSignerKeyManagerGetPrimitiveBasic(t *testing.T) {
if err := v.Verify(signature, data); err != nil {
t.Errorf("unexpected error when verifying signature: %s", err)
}

}

func TestSignerKeyManagerGetPrimitiveWithInvalidInput(t *testing.T) {
Expand Down
33 changes: 18 additions & 15 deletions signature/ed25519/verifier_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import (
"fmt"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/internal/internalapi"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
"github.com/tink-crypto/tink-go/v2/keyset"
"github.com/tink-crypto/tink-go/v2/signature/subtle"
ed25519pb "github.com/tink-crypto/tink-go/v2/proto/ed25519_go_proto"
tinkpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto"
)
Expand All @@ -37,33 +38,35 @@ type verifierKeyManager struct{}
// Primitive creates a [subtle.ED25519Verifier] for the given serialized
// [ed25519pb.Ed25519PublicKey] proto.
func (km *verifierKeyManager) Primitive(serializedKey []byte) (any, error) {
if len(serializedKey) == 0 {
return nil, fmt.Errorf("invalid key")
}
key := new(ed25519pb.Ed25519PublicKey)
if err := proto.Unmarshal(serializedKey, key); err != nil {
return nil, fmt.Errorf("invalid key")
}
if err := km.validateKey(key); err != nil {
keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{
TypeUrl: verifierTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
}, tinkpb.OutputPrefixType_RAW, 0)
if err != nil {
return nil, err
}
ret, err := subtle.NewED25519Verifier(key.KeyValue)
key, err := protoserialization.ParseKey(keySerialization)
if err != nil {
return nil, fmt.Errorf("invalid key: %s", err)
return nil, err
}
verifierKey, ok := key.(*PublicKey)
if !ok {
return nil, fmt.Errorf("ed25519_verifier_key_manager: invalid key type: got %T, want %T", key, (*PublicKey)(nil))
}
return ret, nil
return NewVerifier(verifierKey, internalapi.Token{})
}

// NewKey is not implemented.
func (km *verifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
return nil, fmt.Errorf("not implemented")
return nil, fmt.Errorf("ed25519_verifier_key_manager: not implemented")
}

// NewKeyData creates a new KeyData according to specification in the given
// serialized ED25519KeyFormat. It should be used solely by the key management
// API.
func (km *verifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
return nil, fmt.Errorf("not implemented")
return nil, fmt.Errorf("ed25519_verifier_key_manager: not implemented")
}

// DoesSupport indicates if this key manager supports the given key type.
Expand All @@ -80,7 +83,7 @@ func (km *verifierKeyManager) validateKey(key *ed25519pb.Ed25519PublicKey) error
return err
}
if len(key.KeyValue) != ed25519.PublicKeySize {
return fmt.Errorf("invalid key length, required :%d", ed25519.PublicKeySize)
return fmt.Errorf("ed25519_verifier_key_manager: invalid key length, required :%d", ed25519.PublicKeySize)
}
return nil
}
2 changes: 1 addition & 1 deletion signature/rsassapkcs1/signer_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (km *signerKeyManager) Primitive(serializedKey []byte) (any, error) {
}
signerKey, ok := key.(*PrivateKey)
if !ok {
return nil, fmt.Errorf("invalid key type: got %T, want *rsassapkcs1.PrivateKey", key)
return nil, fmt.Errorf("rsassapkcs1_signer_key_manager: invalid key type: got %T, want %T", key, (*PrivateKey)(nil))
}
return NewSigner(signerKey, internalapi.Token{})
}
Expand Down
5 changes: 2 additions & 3 deletions signature/rsassapkcs1/signer_key_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/core/registry"
"github.com/tink-crypto/tink-go/v2/internal/signature"
_ "github.com/tink-crypto/tink-go/v2/signature/rsassapkcs1" // Register the key managers.
"github.com/tink-crypto/tink-go/v2/subtle/random"
"github.com/tink-crypto/tink-go/v2/tink"
Expand Down Expand Up @@ -121,9 +120,9 @@ func TestSignerKeyManagerPrimitiveSignVerify(t *testing.T) {
if err != nil {
t.Fatalf("rsaSSAPKCS1VerifierKeyManager.Primitive() failed: %v", err)
}
v, ok := p.(*signature.RSA_SSA_PKCS1_Verifier)
v, ok := p.(tink.Verifier)
if !ok {
t.Fatalf("primitve is not of type RSA_SSA_PKCS1_Verifier")
t.Fatalf("primitve is not of type tink.Verifier")
}
data := random.GetRandomBytes(1281)
signature, err := signer.Sign(data)
Expand Down
25 changes: 14 additions & 11 deletions signature/rsassapkcs1/verifier_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
package rsassapkcs1

import (
"crypto/rsa"
"errors"
"fmt"
"math/big"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/core/registry"
"github.com/tink-crypto/tink-go/v2/internal/internalapi"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
internal "github.com/tink-crypto/tink-go/v2/internal/signature"
"github.com/tink-crypto/tink-go/v2/keyset"
rsassapkcs1pb "github.com/tink-crypto/tink-go/v2/proto/rsa_ssa_pkcs1_go_proto"
Expand All @@ -40,21 +41,23 @@ type verifierKeyManager struct{}
var _ registry.KeyManager = (*verifierKeyManager)(nil)

func (km *verifierKeyManager) Primitive(serializedKey []byte) (any, error) {
if len(serializedKey) == 0 {
return nil, fmt.Errorf("rsassapkcs1_verifier_key_manager: invalid serialized public key")
}
key := &rsassapkcs1pb.RsaSsaPkcs1PublicKey{}
if err := proto.Unmarshal(serializedKey, key); err != nil {
keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{
TypeUrl: verifierTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
}, tinkpb.OutputPrefixType_RAW, 0)
if err != nil {
return nil, err
}
if err := validatePublicKey(key); err != nil {
key, err := protoserialization.ParseKey(keySerialization)
if err != nil {
return nil, err
}
keyData := &rsa.PublicKey{
E: int(new(big.Int).SetBytes(key.GetE()).Int64()),
N: new(big.Int).SetBytes(key.GetN()),
verifierKey, ok := key.(*PublicKey)
if !ok {
return nil, fmt.Errorf("rsassapkcs1_verifier_key_manager: invalid key type: got %T, want %T", key, (*PublicKey)(nil))
}
return internal.New_RSA_SSA_PKCS1_Verifier(hashName(key.GetParams().GetHashType()), keyData)
return NewVerifier(verifierKey, internalapi.Token{})
}

func validatePublicKey(pubKey *rsassapkcs1pb.RsaSsaPkcs1PublicKey) error {
Expand Down
37 changes: 34 additions & 3 deletions signature/rsassapkcs1/verifier_key_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/core/registry"
"github.com/tink-crypto/tink-go/v2/internal/signature"
internal "github.com/tink-crypto/tink-go/v2/internal/signature"
"github.com/tink-crypto/tink-go/v2/subtle/random"
"github.com/tink-crypto/tink-go/v2/tink"
commonpb "github.com/tink-crypto/tink-go/v2/proto/common_go_proto"
Expand Down Expand Up @@ -119,8 +119,39 @@ func TestVerifierKeyManagerPrimitive(t *testing.T) {
if err != nil {
t.Fatalf("Primitive() err = %v, want nil", err)
}
if _, ok := p.(*signature.RSA_SSA_PKCS1_Verifier); !ok {
t.Fatalf("primitive isn't a RSA_SSA_PKCS1_Verifier")
verifier, ok := p.(tink.Verifier)
if !ok {
t.Fatalf("primitive isn't %T, got %T", p, (tink.Verifier)(nil))
}

// Make sure it can verify RSASSA PKCS1 signatures.
rsaPrivateKey := &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: new(big.Int).SetBytes(privKey.GetPublicKey().GetN()),
E: int(new(big.Int).SetBytes(privKey.GetPublicKey().GetE()).Int64()),
},
D: new(big.Int).SetBytes(privKey.GetD()),
Primes: []*big.Int{
new(big.Int).SetBytes(privKey.GetP()),
new(big.Int).SetBytes(privKey.GetQ()),
},
}
if err := rsaPrivateKey.Validate(); err != nil {
t.Fatalf("rsaPrivateKey.Validate() err = %v, want nil", err)
}
rsaPrivateKey.Precompute()

signer, err := internal.New_RSA_SSA_PKCS1_Signer("SHA256", rsaPrivateKey)
if err != nil {
t.Fatalf("primitive isn't %T, got %T", p, (tink.Signer)(nil))
}
toSign := random.GetRandomBytes(100)
sig, err := signer.Sign(toSign)
if err != nil {
t.Fatalf("signer.Sign(toSign) err = %v, want nil", err)
}
if err := verifier.Verify(sig, toSign); err != nil {
t.Errorf("verifier.Verify(sig, toSign) err = %v, want nil", err)
}
}

Expand Down
Loading

0 comments on commit d26c394

Please sign in to comment.