1*e7b1675dSTing-Kang Chang// Copyright 2021 Google LLC 2*e7b1675dSTing-Kang Chang// 3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang// 7*e7b1675dSTing-Kang Chang// http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang// 9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS, 11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang// limitations under the License. 14*e7b1675dSTing-Kang Chang// 15*e7b1675dSTing-Kang Chang//////////////////////////////////////////////////////////////////////////////// 16*e7b1675dSTing-Kang Chang 17*e7b1675dSTing-Kang Changpackage signature 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changimport ( 20*e7b1675dSTing-Kang Chang "crypto" 21*e7b1675dSTing-Kang Chang "crypto/rsa" 22*e7b1675dSTing-Kang Chang "fmt" 23*e7b1675dSTing-Kang Chang "hash" 24*e7b1675dSTing-Kang Chang 25*e7b1675dSTing-Kang Chang "github.com/google/tink/go/subtle" 26*e7b1675dSTing-Kang Chang "github.com/google/tink/go/tink" 27*e7b1675dSTing-Kang Chang) 28*e7b1675dSTing-Kang Chang 29*e7b1675dSTing-Kang Changconst ( 30*e7b1675dSTing-Kang Chang rsaMinModulusSizeInBits = 2048 31*e7b1675dSTing-Kang Chang rsaDefaultPublicExponent = 65537 32*e7b1675dSTing-Kang Chang) 33*e7b1675dSTing-Kang Chang 34*e7b1675dSTing-Kang Chang// RSAValidModulusSizeInBits the size in bits for an RSA key. 35*e7b1675dSTing-Kang Changfunc RSAValidModulusSizeInBits(m int) error { 36*e7b1675dSTing-Kang Chang if m < rsaMinModulusSizeInBits { 37*e7b1675dSTing-Kang Chang return fmt.Errorf("modulus size too small, must be >= %d", rsaMinModulusSizeInBits) 38*e7b1675dSTing-Kang Chang } 39*e7b1675dSTing-Kang Chang return nil 40*e7b1675dSTing-Kang Chang} 41*e7b1675dSTing-Kang Chang 42*e7b1675dSTing-Kang Chang// RSAValidPublicExponent validates a public RSA exponent. 43*e7b1675dSTing-Kang Changfunc RSAValidPublicExponent(e int) error { 44*e7b1675dSTing-Kang Chang // crypto/rsa uses the following hardcoded public exponent value. 45*e7b1675dSTing-Kang Chang if e != rsaDefaultPublicExponent { 46*e7b1675dSTing-Kang Chang return fmt.Errorf("invalid public exponent") 47*e7b1675dSTing-Kang Chang } 48*e7b1675dSTing-Kang Chang return nil 49*e7b1675dSTing-Kang Chang} 50*e7b1675dSTing-Kang Chang 51*e7b1675dSTing-Kang Chang// HashSafeForSignature checks whether a hash function is safe to use with digital signatures 52*e7b1675dSTing-Kang Chang// that require collision resistance. 53*e7b1675dSTing-Kang Changfunc HashSafeForSignature(hashAlg string) error { 54*e7b1675dSTing-Kang Chang switch hashAlg { 55*e7b1675dSTing-Kang Chang case "SHA256", "SHA384", "SHA512": 56*e7b1675dSTing-Kang Chang return nil 57*e7b1675dSTing-Kang Chang default: 58*e7b1675dSTing-Kang Chang return fmt.Errorf("hash function not safe for digital signatures: %q", hashAlg) 59*e7b1675dSTing-Kang Chang } 60*e7b1675dSTing-Kang Chang} 61*e7b1675dSTing-Kang Chang 62*e7b1675dSTing-Kang Changconst ( 63*e7b1675dSTing-Kang Chang testMsg = "Tink and Wycheproof." 64*e7b1675dSTing-Kang Chang signVerifyErrMsg = "signing with private key followed by verifying with public key failed, the key may be corrupted" 65*e7b1675dSTing-Kang Chang) 66*e7b1675dSTing-Kang Chang 67*e7b1675dSTing-Kang Chang// Validate_RSA_SSA_PKCS1 validates that the corresponding private key is valid by signing and verifying a message. 68*e7b1675dSTing-Kang Changfunc Validate_RSA_SSA_PKCS1(hashAlg string, privKey *rsa.PrivateKey) error { 69*e7b1675dSTing-Kang Chang signer, err := New_RSA_SSA_PKCS1_Signer(hashAlg, privKey) 70*e7b1675dSTing-Kang Chang if err != nil { 71*e7b1675dSTing-Kang Chang return err 72*e7b1675dSTing-Kang Chang } 73*e7b1675dSTing-Kang Chang verifier, err := New_RSA_SSA_PKCS1_Verifier(hashAlg, &privKey.PublicKey) 74*e7b1675dSTing-Kang Chang if err != nil { 75*e7b1675dSTing-Kang Chang return err 76*e7b1675dSTing-Kang Chang } 77*e7b1675dSTing-Kang Chang if err := validateSignerVerifier(signer, verifier); err != nil { 78*e7b1675dSTing-Kang Chang return fmt.Errorf("RSA-SSA-PKCS1: %q", signVerifyErrMsg) 79*e7b1675dSTing-Kang Chang } 80*e7b1675dSTing-Kang Chang return nil 81*e7b1675dSTing-Kang Chang} 82*e7b1675dSTing-Kang Chang 83*e7b1675dSTing-Kang Chang// Validate_RSA_SSA_PSS validates that the corresponding private key is valid by signing and verifying a message. 84*e7b1675dSTing-Kang Changfunc Validate_RSA_SSA_PSS(hashAlg string, saltLen int, privKey *rsa.PrivateKey) error { 85*e7b1675dSTing-Kang Chang signer, err := New_RSA_SSA_PSS_Signer(hashAlg, saltLen, privKey) 86*e7b1675dSTing-Kang Chang if err != nil { 87*e7b1675dSTing-Kang Chang return err 88*e7b1675dSTing-Kang Chang } 89*e7b1675dSTing-Kang Chang verifier, err := New_RSA_SSA_PSS_Verifier(hashAlg, saltLen, &privKey.PublicKey) 90*e7b1675dSTing-Kang Chang if err != nil { 91*e7b1675dSTing-Kang Chang return err 92*e7b1675dSTing-Kang Chang } 93*e7b1675dSTing-Kang Chang if err := validateSignerVerifier(signer, verifier); err != nil { 94*e7b1675dSTing-Kang Chang return fmt.Errorf("RSA-SSA-PSS: %q", signVerifyErrMsg) 95*e7b1675dSTing-Kang Chang } 96*e7b1675dSTing-Kang Chang return nil 97*e7b1675dSTing-Kang Chang} 98*e7b1675dSTing-Kang Chang 99*e7b1675dSTing-Kang Changfunc validateSignerVerifier(signer tink.Signer, verifier tink.Verifier) error { 100*e7b1675dSTing-Kang Chang signature, err := signer.Sign([]byte(testMsg)) 101*e7b1675dSTing-Kang Chang if err != nil { 102*e7b1675dSTing-Kang Chang return err 103*e7b1675dSTing-Kang Chang } 104*e7b1675dSTing-Kang Chang if err := verifier.Verify([]byte(signature), []byte(testMsg)); err != nil { 105*e7b1675dSTing-Kang Chang return err 106*e7b1675dSTing-Kang Chang } 107*e7b1675dSTing-Kang Chang return nil 108*e7b1675dSTing-Kang Chang} 109*e7b1675dSTing-Kang Chang 110*e7b1675dSTing-Kang Changfunc validRSAPublicKey(publicKey *rsa.PublicKey) error { 111*e7b1675dSTing-Kang Chang if err := RSAValidModulusSizeInBits(publicKey.N.BitLen()); err != nil { 112*e7b1675dSTing-Kang Chang return err 113*e7b1675dSTing-Kang Chang } 114*e7b1675dSTing-Kang Chang return RSAValidPublicExponent(publicKey.E) 115*e7b1675dSTing-Kang Chang} 116*e7b1675dSTing-Kang Chang 117*e7b1675dSTing-Kang Changfunc hashID(hashAlg string) (crypto.Hash, error) { 118*e7b1675dSTing-Kang Chang switch hashAlg { 119*e7b1675dSTing-Kang Chang case "SHA256": 120*e7b1675dSTing-Kang Chang return crypto.SHA256, nil 121*e7b1675dSTing-Kang Chang case "SHA384": 122*e7b1675dSTing-Kang Chang return crypto.SHA384, nil 123*e7b1675dSTing-Kang Chang case "SHA512": 124*e7b1675dSTing-Kang Chang return crypto.SHA512, nil 125*e7b1675dSTing-Kang Chang default: 126*e7b1675dSTing-Kang Chang return 0, fmt.Errorf("invalid hash function: %q", hashAlg) 127*e7b1675dSTing-Kang Chang } 128*e7b1675dSTing-Kang Chang} 129*e7b1675dSTing-Kang Chang 130*e7b1675dSTing-Kang Changfunc rsaHashFunc(hashAlg string) (func() hash.Hash, crypto.Hash, error) { 131*e7b1675dSTing-Kang Chang if err := HashSafeForSignature(hashAlg); err != nil { 132*e7b1675dSTing-Kang Chang return nil, 0, err 133*e7b1675dSTing-Kang Chang } 134*e7b1675dSTing-Kang Chang hashFunc := subtle.GetHashFunc(hashAlg) 135*e7b1675dSTing-Kang Chang if hashFunc == nil { 136*e7b1675dSTing-Kang Chang return nil, 0, fmt.Errorf("invalid hash function: %q", hashAlg) 137*e7b1675dSTing-Kang Chang } 138*e7b1675dSTing-Kang Chang hashID, err := hashID(hashAlg) 139*e7b1675dSTing-Kang Chang if err != nil { 140*e7b1675dSTing-Kang Chang return nil, 0, err 141*e7b1675dSTing-Kang Chang } 142*e7b1675dSTing-Kang Chang return hashFunc, hashID, nil 143*e7b1675dSTing-Kang Chang} 144