| // 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 ( |
| "crypto/rand" |
| "crypto/rsa" |
| "fmt" |
| "math/big" |
| "testing" |
| |
| internal "github.com/google/tink/go/internal/signature" |
| "github.com/google/tink/go/subtle/random" |
| "github.com/google/tink/go/subtle" |
| "github.com/google/tink/go/testutil" |
| ) |
| |
| func TestRSASSAPKCS1SignVerify(t *testing.T) { |
| data := random.GetRandomBytes(20) |
| hash := "SHA256" |
| privKey, err := rsa.GenerateKey(rand.Reader, 2048) |
| if err != nil { |
| t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) |
| } |
| signer, err := internal.New_RSA_SSA_PKCS1_Signer(hash, privKey) |
| if err != nil { |
| t.Fatalf("New_RSA_SSA_PKCS1_Signer() err = %v, want nil", err) |
| } |
| verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, &privKey.PublicKey) |
| if err != nil { |
| t.Fatalf("New_RSA_SSA_PKCS1_Verifier() err = %v, want nil", err) |
| } |
| signature, err := signer.Sign(data) |
| if err != nil { |
| t.Fatalf("Sign() err = %v, want nil", err) |
| } |
| if err := verifier.Verify(signature, data); err != nil { |
| t.Fatalf("Verify() err = %v, want nil", err) |
| } |
| } |
| |
| func TestRSASSAPKCS1ModifySignatureFails(t *testing.T) { |
| data := random.GetRandomBytes(20) |
| hash := "SHA256" |
| privKey, err := rsa.GenerateKey(rand.Reader, 2048) |
| if err != nil { |
| t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) |
| } |
| signer, err := internal.New_RSA_SSA_PKCS1_Signer(hash, privKey) |
| if err != nil { |
| t.Fatalf("New_RSA_SSA_PKCS1_Signer() err = %v, want nil", err) |
| } |
| signature, err := signer.Sign(data) |
| if err != nil { |
| t.Fatalf("Sign() err = %v, want nil", err) |
| } |
| verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, &privKey.PublicKey) |
| if err != nil { |
| t.Fatalf("New_RSA_SSA_PKCS1_Verifier() err = %v, want nil", err) |
| } |
| appendSig := append(signature, 0x01) |
| if err := verifier.Verify(appendSig, data); err == nil { |
| t.Fatalf("Verify() err = nil, want error") |
| } |
| truncSig := signature[:len(signature)-2] |
| if err := verifier.Verify(truncSig, data); err == nil { |
| t.Fatalf("Verify() err = nil, want error") |
| } |
| signature[0] = byte(uint8(signature[0] + 1)) |
| if err := verifier.Verify(truncSig, data); err == nil { |
| t.Fatalf("Verify() err = nil, want error") |
| } |
| } |
| |
| func TestNewRSASSAPKCS1SignerVerifierInvalidInput(t *testing.T) { |
| validPrivKey, err := rsa.GenerateKey(rand.Reader, 2048) |
| if err != nil { |
| t.Fatalf("rsa.GenerateKey(rand.Reader, 2048) err = %v, want nil", err) |
| } |
| rsaShortModulusKey, err := rsa.GenerateKey(rand.Reader, 1024) |
| if err != nil { |
| t.Fatalf("decoding rsa short modulus: %v", err) |
| } |
| testCases := []struct { |
| name string |
| hash string |
| privKey *rsa.PrivateKey |
| }{ |
| { |
| name: "weak signature hash algorithm", |
| hash: "SHA1", |
| privKey: validPrivKey, |
| }, |
| { |
| name: "invalid public key exponent", |
| hash: "SHA256", |
| privKey: &rsa.PrivateKey{ |
| D: validPrivKey.D, |
| Primes: validPrivKey.Primes, |
| Precomputed: validPrivKey.Precomputed, |
| PublicKey: rsa.PublicKey{ |
| N: validPrivKey.PublicKey.N, |
| E: 3, |
| }, |
| }, |
| }, |
| { |
| name: "small modulus size", |
| hash: "SHA256", |
| privKey: rsaShortModulusKey, |
| }, |
| } |
| for _, tc := range testCases { |
| t.Run(tc.name, func(t *testing.T) { |
| if _, err := internal.New_RSA_SSA_PKCS1_Signer(tc.hash, tc.privKey); err == nil { |
| t.Errorf("New_RSA_SSA_PKCS1_Signer() err = nil, want error") |
| } |
| if _, err := internal.New_RSA_SSA_PKCS1_Verifier(tc.hash, &tc.privKey.PublicKey); err == nil { |
| t.Errorf("New_RSA_SSA_PKCS1_Verifier() err = nil, want error") |
| } |
| }) |
| } |
| } |
| |
| type rsaSSAPKCS1Suite struct { |
| testutil.WycheproofSuite |
| TestGroups []*rsaSSAPKCS1Group `json:"testGroups"` |
| } |
| |
| type rsaSSAPKCS1Group struct { |
| testutil.WycheproofGroup |
| SHA string `json:"sha"` |
| E testutil.HexBytes `json:"e"` |
| N testutil.HexBytes `json:"n"` |
| Type string `json:"type"` |
| Tests []*rsaSSAPKCS1Case `json:"tests"` |
| } |
| |
| type rsaSSAPKCS1Case struct { |
| testutil.WycheproofCase |
| Message testutil.HexBytes `json:"msg"` |
| Signature testutil.HexBytes `json:"sig"` |
| } |
| |
| func TestRSASSAPKCS1WycheproofCases(t *testing.T) { |
| testutil.SkipTestIfTestSrcDirIsNotSet(t) |
| |
| testsRan := 0 |
| for _, v := range []string{ |
| "rsa_signature_2048_sha256_test.json", |
| "rsa_signature_3072_sha512_test.json", |
| "rsa_signature_4096_sha512_test.json", |
| } { |
| suite := &rsaSSAPKCS1Suite{} |
| if err := testutil.PopulateSuite(suite, v); err != nil { |
| t.Fatalf("testutil.PopulateSuite() err = %v, want nil", err) |
| } |
| for _, group := range suite.TestGroups { |
| hash := subtle.ConvertHashName(group.SHA) |
| if hash == "" { |
| t.Fatalf("invalid hash name") |
| } |
| publicKey := &rsa.PublicKey{ |
| E: int(new(big.Int).SetBytes(group.E).Uint64()), |
| N: new(big.Int).SetBytes(group.N), |
| } |
| if publicKey.E != 65537 { |
| // golang "crypto/rsa" only supports 65537 as an exponent. |
| if _, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, publicKey); err == nil { |
| t.Errorf("NewRSASSAPKCS1Verifier() err = nil, want error") |
| } |
| continue |
| } |
| verifier, err := internal.New_RSA_SSA_PKCS1_Verifier(hash, publicKey) |
| if err != nil { |
| t.Fatalf("NewRSASSAPKCS1Verifier() err = %v, want nil", err) |
| } |
| for _, test := range group.Tests { |
| caseName := fmt.Sprintf("%s: %s-%s:Case-%d", v, group.Type, group.SHA, test.CaseID) |
| t.Run(caseName, func(t *testing.T) { |
| testsRan++ |
| err := verifier.Verify(test.Signature, test.Message) |
| switch test.Result { |
| case "valid": |
| if err != nil { |
| t.Errorf("Verify() err = %v, want nil", err) |
| } |
| case "invalid": |
| if err == nil { |
| t.Errorf("Verify() err = nil, want error") |
| } |
| case "acceptable": |
| // TODO(b/230489047): Inspect flags to appropriately handle acceptable test cases. |
| default: |
| t.Errorf("unsupported test result: %q", test.Result) |
| } |
| }) |
| } |
| } |
| } |
| if testsRan != 716 { |
| t.Errorf("testsRan = %d, want = %d", testsRan, 716) |
| } |
| } |