github.com/trustbloc/kms-go@v1.1.2/kms/localkms/pubkey_writer.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package localkms 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "crypto/x509" 13 "fmt" 14 "io" 15 "math/big" 16 17 "github.com/golang/protobuf/proto" 18 commonpb "github.com/google/tink/go/proto/common_go_proto" 19 ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto" 20 ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto" 21 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 22 "github.com/google/tink/go/subtle" 23 24 "github.com/trustbloc/kms-go/spi/kms" 25 26 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio" 27 bbspb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/bbs_go_proto" 28 clpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/cl_go_proto" 29 secp256k1pb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/secp256k1_go_proto" 30 secp256k1subtle "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/secp256k1/subtle" 31 ) 32 33 const ( 34 ecdsaVerifierTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey" 35 ed25519VerifierTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PublicKey" 36 nistPECDHKWPublicKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.NistPEcdhKwPublicKey" 37 x25519ECDHKWPublicKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.X25519EcdhKwPublicKey" 38 bbsVerifierKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.BBSPublicKey" 39 clCredDefKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.CLCredDefKey" 40 secp256k1VerifierTypeURL = "type.googleapis.com/google.crypto.tink.secp256k1PublicKey" 41 derPrefix = "der-" 42 p13163Prefix = "p1363-" 43 ) 44 45 //nolint:gochecknoglobals 46 var ecdsaKMSKeyTypes = map[string]kms.KeyType{ 47 derPrefix + "NIST_P256": kms.ECDSAP256TypeDER, 48 derPrefix + "NIST_P384": kms.ECDSAP384TypeDER, 49 derPrefix + "NIST_P521": kms.ECDSAP521TypeDER, 50 derPrefix + "SECP256K1": kms.ECDSASecp256k1DER, 51 p13163Prefix + "NIST_P256": kms.ECDSAP256TypeIEEEP1363, 52 p13163Prefix + "NIST_P384": kms.ECDSAP384TypeIEEEP1363, 53 p13163Prefix + "NIST_P521": kms.ECDSAP521TypeIEEEP1363, 54 p13163Prefix + "SECP256K1": kms.ECDSASecp256k1IEEEP1363, 55 } 56 57 // PubKeyWriter will write the raw bytes of a Tink KeySet's primary public key 58 // The keyset must be one of the keyURLs defined above 59 // Note: Only signing public keys and ecdh key types created in tinkcrypto can be exported through this PubKeyWriter. 60 // ECHDES has its own Writer to export its public keys due to cyclic dependency. 61 type PubKeyWriter struct { 62 // KeyType is Key Type of the written key. It's needed as Write() is an interface function and can't return it. 63 KeyType kms.KeyType 64 w io.Writer 65 } 66 67 // NewWriter creates a new PubKeyWriter instance. 68 func NewWriter(w io.Writer) *PubKeyWriter { 69 return &PubKeyWriter{ 70 w: w, 71 } 72 } 73 74 // Write writes the public keyset to the underlying w.Writer. 75 func (p *PubKeyWriter) Write(keyset *tinkpb.Keyset) error { 76 keyType, err := write(p.w, keyset) 77 if err != nil { 78 return err 79 } 80 81 p.KeyType = keyType 82 83 return nil 84 } 85 86 // WriteEncrypted writes the encrypted keyset to the underlying w.Writer. 87 func (p *PubKeyWriter) WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error { 88 return fmt.Errorf("write encrypted function not supported") 89 } 90 91 func write(w io.Writer, msg *tinkpb.Keyset) (kms.KeyType, error) { 92 ks := msg.Key 93 primaryKID := msg.PrimaryKeyId 94 created := false 95 96 var ( 97 kt kms.KeyType 98 err error 99 ) 100 101 for _, key := range ks { 102 if key.KeyId == primaryKID && key.Status == tinkpb.KeyStatusType_ENABLED { 103 switch key.KeyData.TypeUrl { 104 case ecdsaVerifierTypeURL, ed25519VerifierTypeURL, bbsVerifierKeyTypeURL, clCredDefKeyTypeURL, 105 secp256k1VerifierTypeURL: 106 created, kt, err = writePubKey(w, key) 107 if err != nil { 108 return "", err 109 } 110 case nistPECDHKWPublicKeyTypeURL, x25519ECDHKWPublicKeyTypeURL: 111 pkW := keyio.NewWriter(w) 112 113 err = pkW.Write(msg) 114 if err != nil { 115 return "", err 116 } 117 118 kt = pkW.KeyType 119 created = true 120 default: 121 return "", fmt.Errorf("key type not supported for writing raw key bytes: %s", key.KeyData.TypeUrl) 122 } 123 124 break 125 } 126 } 127 128 if !created { 129 return "", fmt.Errorf("key not written") 130 } 131 132 return kt, nil 133 } 134 135 // nolint:gocyclo,funlen 136 func writePubKey(w io.Writer, key *tinkpb.Keyset_Key) (bool, kms.KeyType, error) { 137 var ( 138 marshaledRawPubKey []byte 139 kt kms.KeyType 140 ) 141 142 // TODO add other key types than the ones below and other than nistPECDHKWPublicKeyTypeURL and 143 // TODO x25519ECDHKWPublicKeyTypeURL(eg: secp256k1 when introduced in KMS). 144 switch key.KeyData.TypeUrl { 145 case ecdsaVerifierTypeURL: 146 pubKeyProto := new(ecdsapb.EcdsaPublicKey) 147 148 err := proto.Unmarshal(key.KeyData.Value, pubKeyProto) 149 if err != nil { 150 return false, "", err 151 } 152 153 marshaledRawPubKey, kt, err = getMarshalledECDSAKeyValueFromProto(pubKeyProto) 154 if err != nil { 155 return false, "", err 156 } 157 case ed25519VerifierTypeURL: 158 pubKeyProto := new(ed25519pb.Ed25519PublicKey) 159 160 err := proto.Unmarshal(key.KeyData.Value, pubKeyProto) 161 if err != nil { 162 return false, "", err 163 } 164 165 marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue)) 166 copy(marshaledRawPubKey, pubKeyProto.KeyValue) 167 168 kt = kms.ED25519Type 169 case bbsVerifierKeyTypeURL: 170 pubKeyProto := new(bbspb.BBSPublicKey) 171 172 err := proto.Unmarshal(key.KeyData.Value, pubKeyProto) 173 if err != nil { 174 return false, "", err 175 } 176 177 marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue)) 178 copy(marshaledRawPubKey, pubKeyProto.KeyValue) 179 180 kt = kms.BLS12381G2Type 181 case clCredDefKeyTypeURL: 182 pubKeyProto := new(clpb.CLCredDefPublicKey) 183 184 err := proto.Unmarshal(key.KeyData.Value, pubKeyProto) 185 if err != nil { 186 return false, "", err 187 } 188 189 marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue)) 190 copy(marshaledRawPubKey, pubKeyProto.KeyValue) 191 192 kt = kms.CLCredDefType 193 case secp256k1VerifierTypeURL: 194 pubKeyProto := new(secp256k1pb.Secp256K1PublicKey) 195 196 err := proto.Unmarshal(key.KeyData.Value, pubKeyProto) 197 if err != nil { 198 return false, "", err 199 } 200 201 marshaledRawPubKey, kt, err = getMarshalledSecp256K1KeyValueFromProto(pubKeyProto) 202 if err != nil { 203 return false, "", err 204 } 205 default: 206 return false, "", fmt.Errorf("can't export key with keyURL:%s", key.KeyData.TypeUrl) 207 } 208 209 n, err := w.Write(marshaledRawPubKey) 210 if err != nil { 211 return false, "", nil //nolint:nilerr 212 } 213 214 return n > 0, kt, nil 215 } 216 217 func getMarshalledECDSAKeyValueFromProto(pubKeyProto *ecdsapb.EcdsaPublicKey) ([]byte, kms.KeyType, error) { 218 var ( 219 marshaledRawPubKey []byte 220 err error 221 kt kms.KeyType 222 ) 223 224 curveName := commonpb.EllipticCurveType_name[int32(pubKeyProto.Params.Curve)] 225 226 curve := subtle.GetCurve(curveName) 227 if curve == nil { 228 return nil, "", fmt.Errorf("undefined curve") 229 } 230 231 pubKey := ecdsa.PublicKey{ 232 Curve: curve, 233 X: new(big.Int), 234 Y: new(big.Int), 235 } 236 237 pubKey.X.SetBytes(pubKeyProto.X) 238 pubKey.Y.SetBytes(pubKeyProto.Y) 239 240 switch pubKeyProto.Params.Encoding { 241 case ecdsapb.EcdsaSignatureEncoding_DER: 242 marshaledRawPubKey, err = x509.MarshalPKIXPublicKey(&pubKey) // DER format not supported here. 243 if err != nil { 244 return nil, "", err 245 } 246 247 kt = ecdsaKMSKeyTypes[derPrefix+curveName] 248 case ecdsapb.EcdsaSignatureEncoding_IEEE_P1363: 249 marshaledRawPubKey = elliptic.Marshal(curve, pubKey.X, pubKey.Y) 250 kt = ecdsaKMSKeyTypes[p13163Prefix+curveName] 251 default: 252 return nil, "", fmt.Errorf("can't export key with bad key encoding: '%s'", pubKeyProto.Params.Encoding) 253 } 254 255 return marshaledRawPubKey, kt, nil 256 } 257 258 func getMarshalledSecp256K1KeyValueFromProto(pkPB *secp256k1pb.Secp256K1PublicKey) ([]byte, kms.KeyType, error) { 259 var ( 260 marshaledRawPubKey []byte 261 err error 262 kt kms.KeyType 263 ) 264 265 curveName := secp256k1pb.BitcoinCurveType_name[int32(pkPB.Params.Curve)] 266 267 curve := secp256k1subtle.GetCurve(curveName) 268 if curve == nil { 269 return nil, "", fmt.Errorf("undefined curve") 270 } 271 272 pubKey := ecdsa.PublicKey{ 273 Curve: curve, 274 X: new(big.Int), 275 Y: new(big.Int), 276 } 277 278 pubKey.X.SetBytes(pkPB.X) 279 pubKey.Y.SetBytes(pkPB.Y) 280 281 switch pkPB.Params.Encoding { 282 case secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_DER: 283 marshaledRawPubKey, err = x509.MarshalPKIXPublicKey(&pubKey) 284 if err != nil { 285 return nil, "", err 286 } 287 288 kt = ecdsaKMSKeyTypes[derPrefix+curveName] 289 case secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_IEEE_P1363: 290 marshaledRawPubKey = elliptic.Marshal(curve, pubKey.X, pubKey.Y) 291 kt = ecdsaKMSKeyTypes[p13163Prefix+curveName] 292 default: 293 return nil, "", fmt.Errorf("can't export key with bad key encoding: '%s'", pkPB.Params.Encoding) 294 } 295 296 return marshaledRawPubKey, kt, nil 297 }