// Copyright 2022 Google LLC // // 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 signature_test import ( "encoding/hex" "math/big" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "github.com/google/tink/go/core/registry" internal "github.com/google/tink/go/internal/signature" "github.com/google/tink/go/subtle/random" "github.com/google/tink/go/tink" cpb "github.com/google/tink/go/proto/common_go_proto" rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" tinkpb "github.com/google/tink/go/proto/tink_go_proto" ) const ( rsaPKCS1PrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey" ) func TestRSASSAPKCS1SignerKeyManagerDoesSupport(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } if !skm.DoesSupport(rsaPKCS1PrivateKeyTypeURL) { t.Errorf("DoesSupport(%q) = false, want true", rsaPKCS1PrivateKeyTypeURL) } if skm.DoesSupport("not.valid.type") { t.Errorf("DoesSupport(%q) = true, want false", "not.valid.type") } } func TestRSASSAPKCS1SignerTypeURL(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } if skm.TypeURL() != rsaPKCS1PrivateKeyTypeURL { t.Errorf("TypeURL() = %q, want %q", skm.TypeURL(), rsaPKCS1PrivateKeyTypeURL) } } func TestRSASSAPKCS1SignerKeyManagerPublicKeyData(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedPrivate, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } got, err := skm.(registry.PrivateKeyManager).PublicKeyData(serializedPrivate) if err != nil { t.Fatalf("PublicKeyData() err = %v, want nil", err) } if got.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PUBLIC { t.Errorf("GetKeyMaterialType() = %q, want %q", got.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PUBLIC) } if got.GetTypeUrl() != rsaPKCS1PublicTypeURL { t.Errorf("GetTypeUrl() = %q, want %q", got.GetTypeUrl(), rsaPKCS1PublicTypeURL) } if _, err := vkm.Primitive(got.GetValue()); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveSignVerify(t *testing.T) { skm, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } privKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedPrivate, err := proto.Marshal(privKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err := skm.Primitive(serializedPrivate) if err != nil { t.Fatalf("Primitive() err = %v, want nil", err) } signer, ok := p.(*internal.RSA_SSA_PKCS1_Signer) if !ok { t.Fatalf("primitive is not of type RSA_SSA_PKCS1_Signer") } vkm, err := registry.GetKeyManager(rsaPKCS1PublicTypeURL) if err != nil { t.Fatalf("regitry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PublicTypeURL, err) } serializedPublic, err := proto.Marshal(privKey.PublicKey) if err != nil { t.Fatalf("Failed serializing public key proto: %v", err) } p, err = vkm.Primitive(serializedPublic) if err != nil { t.Fatalf("rsaSSAPKCS1VerifierKeyManager.Primitive() failed: %v", err) } v, ok := p.(*internal.RSA_SSA_PKCS1_Verifier) if !ok { t.Fatalf("primitve is not of type RSA_SSA_PKCS1_Verifier") } data := random.GetRandomBytes(1281) signature, err := signer.Sign(data) if err != nil { t.Fatalf("Sign() err = %v, want nil", err) } if err := v.Verify(signature, data); err != nil { t.Fatalf("Verify() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveWithInvalidInputFails(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } validPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } serializedValidPrivate, err := proto.Marshal(validPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedValidPrivate); err != nil { t.Fatalf("Primitive(serializedValidPrivate) err = %v, want nil", err) } type testCase struct { name string key *rsassapkcs1pb.RsaSsaPkcs1PrivateKey } for _, tc := range []testCase{ { name: "empty key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{}, }, { name: "nil key", key: nil, }, { name: "invalid version", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion() + 1, PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid hash algorithm ", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: validPrivKey.GetPublicKey().GetE(), N: validPrivKey.GetPublicKey().GetN(), Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA224, }, }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid modulus", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: validPrivKey.GetPublicKey().GetE(), N: []byte{3, 4, 5}, Params: validPrivKey.GetPublicKey().GetParams(), }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid public key exponent", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ Version: validPrivKey.GetPublicKey().GetVersion(), E: []byte{0x06}, N: validPrivKey.GetPublicKey().GetN(), Params: validPrivKey.GetPublicKey().GetParams(), }, D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key D value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: nil, P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key P value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: nil, Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid private key Q value", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: nil, Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Dp values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: nil, Dq: validPrivKey.GetDq(), Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Dq values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: nil, Crt: validPrivKey.GetCrt(), }, }, { name: "invalid precomputed Crt values in private key", key: &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ Version: validPrivKey.GetVersion(), PublicKey: validPrivKey.GetPublicKey(), D: validPrivKey.GetD(), P: validPrivKey.GetP(), Q: validPrivKey.GetQ(), Dp: validPrivKey.GetDp(), Dq: validPrivKey.GetDq(), Crt: nil, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedKey, err := proto.Marshal(tc.key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedKey); err == nil { t.Errorf("Primitive() err = nil, want error") } if _, err := km.(registry.PrivateKeyManager).PublicKeyData(serializedKey); err == nil { t.Errorf("PublicKeyData() err = nil, want error") } }) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveWithCorruptedKeyFails(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } corruptedPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } corruptedPrivKey.P[5] = byte(uint8(corruptedPrivKey.P[5] + 1)) corruptedPrivKey.P[10] = byte(uint8(corruptedPrivKey.P[10] + 1)) serializedCorruptedPrivate, err := proto.Marshal(corruptedPrivKey) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.Primitive(serializedCorruptedPrivate); err == nil { t.Errorf("Primitive() err = nil, want error") } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKey(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } validPrivKey, err := makeValidRSAPKCS1Key() if err != nil { t.Fatalf("makeValidRSAPKCS1Key() err = %v, want nil", err) } keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, ModulusSizeInBits: 3072, PublicExponent: []byte{0x01, 0x00, 0x01}, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } m, err := km.NewKey(serializedFormat) if err != nil { t.Fatalf("NewKey() err = %v, want nil", err) } privKey, ok := m.(*rsassapkcs1pb.RsaSsaPkcs1PrivateKey) if !ok { t.Fatalf("privateKey is not a RsaSsaPkcs1PrivateKey") } if privKey.GetVersion() != validPrivKey.GetVersion() { t.Errorf("GetVersion() = %d, want %d", privKey.GetVersion(), validPrivKey.GetVersion()) } wantPubKey := validPrivKey.GetPublicKey() gotPubKey := privKey.GetPublicKey() if gotPubKey.GetParams().GetHashType() != wantPubKey.GetParams().GetHashType() { t.Errorf("GetHashType() = %v, want %v", gotPubKey.GetParams().GetHashType(), wantPubKey.GetParams().GetHashType()) } if !cmp.Equal(gotPubKey.GetE(), wantPubKey.GetE()) { t.Errorf("GetE() = %v, want %v", gotPubKey.GetE(), wantPubKey.GetE()) } gotModSize := new(big.Int).SetBytes(gotPubKey.GetN()).BitLen() if gotModSize != 3072 { t.Errorf("Modulus Size = %d, want %d", gotModSize, 3072) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKeyWithInvalidInputFails(t *testing.T) { type testCase struct { name string format *rsassapkcs1pb.RsaSsaPkcs1KeyFormat } km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } for _, tc := range []testCase{ { name: "empty format", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{}, }, { name: "invalid hash", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01, 0x00, 0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA224, }, }, }, { name: "invalid public exponent", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, }, }, { name: "invalid modulus size", format: &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 1024, PublicExponent: []byte{0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, }, }, } { t.Run(tc.name, func(t *testing.T) { serializedFormat, err := proto.Marshal(tc.format) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } if _, err := km.NewKey(serializedFormat); err == nil { t.Fatalf("NewKey() err = nil, want error") } }) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNewKeyData(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{ ModulusSizeInBits: 2048, PublicExponent: []byte{0x01, 0x00, 0x01}, Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ HashType: cpb.HashType_SHA256, }, } serializedFormat, err := proto.Marshal(keyFormat) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } keyData, err := km.NewKeyData(serializedFormat) if err != nil { t.Fatalf("NewKeyData() err = %v, want nil", err) } if keyData.GetTypeUrl() != rsaPKCS1PrivateKeyTypeURL { t.Errorf("GetTypeUrl() = %v, want %v", keyData.GetTypeUrl(), rsaPKCS1PrivateKeyTypeURL) } if keyData.GetKeyMaterialType() != tinkpb.KeyData_ASYMMETRIC_PRIVATE { t.Errorf("GetKeyMaterialType() = %v, want %v", keyData.GetKeyMaterialType(), tinkpb.KeyData_ASYMMETRIC_PRIVATE) } if _, err := km.Primitive(keyData.GetValue()); err != nil { t.Errorf("Primitive() err = %v, want nil", err) } } func TestRSASSAPKCS1SignerKeyManagerPrimitiveNISTTestVectors(t *testing.T) { km, err := registry.GetKeyManager(rsaPKCS1PrivateKeyTypeURL) if err != nil { t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", rsaPKCS1PrivateKeyTypeURL, err) } for _, tc := range nistPKCS1TestVectors { t.Run(tc.name, func(t *testing.T) { key, err := tc.ToProtoKey() if err != nil { t.Fatalf("tc.ToProtoKey() err = %v, want nil", err) } serializedKey, err := proto.Marshal(key) if err != nil { t.Fatalf("proto.Marshal() err = %v, want nil", err) } p, err := km.Primitive(serializedKey) if err != nil { t.Fatalf("km.Primitive() err = %v, want nil", err) } msg, err := hex.DecodeString(tc.msg) if err != nil { t.Fatalf("hex.DecodeString(tc.msg) err = %v, want nil", err) } signer, ok := p.(tink.Signer) if !ok { t.Fatalf("primitive isn't a Tink.Signer") } sig, err := signer.Sign(msg) if err != nil { t.Fatalf("p.(tink.Signer).Sign(msg) err = %v, want nil", err) } gotSig := hex.EncodeToString(sig) if !cmp.Equal(gotSig, tc.sig) { t.Errorf("Sign() = %q, want %q", gotSig, tc.sig) } }) } }