1// Copyright 2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package signature 18 19import ( 20 "crypto/rand" 21 "crypto/rsa" 22 "errors" 23 "fmt" 24 "math/big" 25 26 "google.golang.org/protobuf/proto" 27 "github.com/google/tink/go/core/registry" 28 internal "github.com/google/tink/go/internal/signature" 29 "github.com/google/tink/go/keyset" 30 rsassapkcs1pb "github.com/google/tink/go/proto/rsa_ssa_pkcs1_go_proto" 31 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 32) 33 34const ( 35 rsaSSAPKCS1SignerKeyVersion = 0 36 rsaSSAPKCS1SignerTypeURL = "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey" 37) 38 39var ( 40 errInvalidRSASSAPKCS1SignKey = errors.New("rsassapkcs1_signer_key_manager: invalid key") 41 errInvalidRSASSAPKCS1SignKeyFormat = errors.New("rsassapkcs1_signer_key_manager: invalid key format") 42) 43 44type rsaSSAPKCS1SignerKeyManager struct{} 45 46var _ registry.PrivateKeyManager = (*rsaSSAPKCS1SignerKeyManager)(nil) 47 48func (km *rsaSSAPKCS1SignerKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 49 if false { 50 return nil, errInvalidRSASSAPKCS1SignKey 51 } 52 key := &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{} 53 if err := proto.Unmarshal(serializedKey, key); err != nil { 54 return nil, err 55 } 56 if err := validateRSAPKCS1PrivateKey(key); err != nil { 57 return nil, err 58 } 59 privKey := &rsa.PrivateKey{ 60 D: bytesToBigInt(key.GetD()), 61 PublicKey: rsa.PublicKey{ 62 N: bytesToBigInt(key.GetPublicKey().GetN()), 63 E: int(bytesToBigInt(key.GetPublicKey().GetE()).Int64()), 64 }, 65 Primes: []*big.Int{ 66 bytesToBigInt(key.GetP()), 67 bytesToBigInt(key.GetQ()), 68 }, 69 Precomputed: rsa.PrecomputedValues{ 70 Dp: bytesToBigInt(key.GetDp()), 71 Dq: bytesToBigInt(key.GetDq()), 72 Qinv: bytesToBigInt(key.GetCrt()), 73 }, 74 } 75 h := hashName(key.GetPublicKey().GetParams().GetHashType()) 76 if err := internal.Validate_RSA_SSA_PKCS1(h, privKey); err != nil { 77 return nil, err 78 } 79 return internal.New_RSA_SSA_PKCS1_Signer(h, privKey) 80} 81 82func validateRSAPKCS1PrivateKey(privKey *rsassapkcs1pb.RsaSsaPkcs1PrivateKey) error { 83 if err := keyset.ValidateKeyVersion(privKey.Version, rsaSSAPKCS1SignerKeyVersion); err != nil { 84 return err 85 } 86 if len(privKey.GetD()) == 0 || 87 len(privKey.GetPublicKey().GetN()) == 0 || 88 len(privKey.GetPublicKey().GetE()) == 0 || 89 len(privKey.GetP()) == 0 || 90 len(privKey.GetQ()) == 0 || 91 len(privKey.GetDp()) == 0 || 92 len(privKey.GetDq()) == 0 || 93 len(privKey.GetCrt()) == 0 { 94 return errInvalidRSASSAPKCS1SignKey 95 } 96 return validateRSAPKCS1PublicKey(privKey.GetPublicKey()) 97} 98 99func (km *rsaSSAPKCS1SignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 100 if len(serializedKeyFormat) == 0 { 101 return nil, errInvalidRSASSAPKCS1SignKeyFormat 102 } 103 keyFormat := &rsassapkcs1pb.RsaSsaPkcs1KeyFormat{} 104 if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil { 105 return nil, err 106 } 107 if err := validateRSAPubKeyParams( 108 keyFormat.GetParams().GetHashType(), 109 int(keyFormat.GetModulusSizeInBits()), 110 keyFormat.GetPublicExponent()); err != nil { 111 return nil, err 112 } 113 rsaKey, err := rsa.GenerateKey(rand.Reader, int(keyFormat.ModulusSizeInBits)) 114 if err != nil { 115 return nil, fmt.Errorf("generating RSA key: %s", err) 116 } 117 pubKey := &rsassapkcs1pb.RsaSsaPkcs1PublicKey{ 118 Version: rsaSSAPKCS1SignerKeyVersion, 119 Params: &rsassapkcs1pb.RsaSsaPkcs1Params{ 120 HashType: keyFormat.Params.HashType, 121 }, 122 N: rsaKey.PublicKey.N.Bytes(), 123 E: big.NewInt(int64(rsaKey.PublicKey.E)).Bytes(), 124 } 125 return &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{ 126 Version: rsaSSAPKCS1SignerKeyVersion, 127 PublicKey: pubKey, 128 D: rsaKey.D.Bytes(), 129 P: rsaKey.Primes[0].Bytes(), 130 Q: rsaKey.Primes[1].Bytes(), 131 Dp: rsaKey.Precomputed.Dp.Bytes(), 132 Dq: rsaKey.Precomputed.Dq.Bytes(), 133 Crt: rsaKey.Precomputed.Qinv.Bytes(), 134 }, nil 135} 136 137func (km *rsaSSAPKCS1SignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 138 key, err := km.NewKey(serializedKeyFormat) 139 if err != nil { 140 return nil, err 141 } 142 serializedKey, err := proto.Marshal(key) 143 if err != nil { 144 return nil, errInvalidRSASSAPKCS1SignKeyFormat 145 } 146 return &tinkpb.KeyData{ 147 TypeUrl: rsaSSAPKCS1SignerTypeURL, 148 Value: serializedKey, 149 KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, 150 }, nil 151} 152 153// PublicKeyData extracts the public key data from the private key. 154func (km *rsaSSAPKCS1SignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { 155 privKey := &rsassapkcs1pb.RsaSsaPkcs1PrivateKey{} 156 if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { 157 return nil, err 158 } 159 if err := validateRSAPKCS1PrivateKey(privKey); err != nil { 160 return nil, err 161 } 162 serializedPubKey, err := proto.Marshal(privKey.GetPublicKey()) 163 if err != nil { 164 return nil, err 165 } 166 return &tinkpb.KeyData{ 167 TypeUrl: rsaSSAPKCS1VerifierTypeURL, 168 Value: serializedPubKey, 169 KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, 170 }, nil 171} 172 173// DoesSupport indicates if this key manager supports the given key type. 174func (km *rsaSSAPKCS1SignerKeyManager) DoesSupport(typeURL string) bool { 175 return typeURL == rsaSSAPKCS1SignerTypeURL 176} 177 178// TypeURL returns the key type of keys managed by this key manager. 179func (km *rsaSSAPKCS1SignerKeyManager) TypeURL() string { 180 return rsaSSAPKCS1SignerTypeURL 181} 182