1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package signer
16
17 import (
18 "context"
19 "crypto"
20 "crypto/ecdsa"
21 "crypto/ed25519"
22 "errors"
23 "fmt"
24 "math/big"
25 "os"
26 "path/filepath"
27 "strings"
28
29 "github.com/google/tink/go/core/registry"
30 "github.com/google/tink/go/integration/awskms"
31 "github.com/google/tink/go/integration/gcpkms"
32 "github.com/google/tink/go/integration/hcvault"
33 signatureSubtle "github.com/google/tink/go/signature/subtle"
34 "github.com/google/tink/go/subtle"
35 "github.com/google/tink/go/tink"
36
37 "github.com/golang/protobuf/proto"
38 "github.com/google/tink/go/insecurecleartextkeyset"
39 "github.com/google/tink/go/keyset"
40 commonpb "github.com/google/tink/go/proto/common_go_proto"
41 ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto"
42 ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto"
43 tinkpb "github.com/google/tink/go/proto/tink_go_proto"
44 )
45
46 var (
47 ecdsaSignerKeyVersion = 0
48 ecdsaSignerTypeURL = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"
49 ed25519SignerKeyVersion = 0
50 ed25519SignerTypeURL = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"
51 )
52
53
54 func NewTinkSigner(_ context.Context, tinkKeysetPath string, primaryKey tink.AEAD) (crypto.Signer, error) {
55 f, err := os.Open(filepath.Clean(tinkKeysetPath))
56 if err != nil {
57 return nil, err
58 }
59 defer f.Close()
60
61 kh, err := keyset.Read(keyset.NewJSONReader(f), primaryKey)
62 if err != nil {
63 return nil, err
64 }
65 signer, err := KeyHandleToSigner(kh)
66 if err != nil {
67 return nil, err
68 }
69 return signer, nil
70 }
71
72
73
74 func GetPrimaryKey(ctx context.Context, kmsKey, hcVaultToken string) (tink.AEAD, error) {
75 switch {
76 case strings.HasPrefix(kmsKey, "gcp-kms://"):
77 gcpClient, err := gcpkms.NewClientWithOptions(ctx, kmsKey)
78 if err != nil {
79 return nil, err
80 }
81 registry.RegisterKMSClient(gcpClient)
82 return gcpClient.GetAEAD(kmsKey)
83 case strings.HasPrefix(kmsKey, "aws-kms://"):
84 awsClient, err := awskms.NewClient(kmsKey)
85 if err != nil {
86 return nil, err
87 }
88 registry.RegisterKMSClient(awsClient)
89 return awsClient.GetAEAD(kmsKey)
90 case strings.HasPrefix(kmsKey, "hcvault://"):
91 hcVaultClient, err := hcvault.NewClient(kmsKey, nil, hcVaultToken)
92 if err != nil {
93 return nil, err
94 }
95 registry.RegisterKMSClient(hcVaultClient)
96 return hcVaultClient.GetAEAD(kmsKey)
97 default:
98 return nil, errors.New("unsupported Tink KMS key type")
99 }
100 }
101
102
103
104 func KeyHandleToSigner(kh *keyset.Handle) (crypto.Signer, error) {
105
106 ks := insecurecleartextkeyset.KeysetMaterial(kh)
107
108 k := getPrimaryKey(ks)
109 if k == nil {
110 return nil, errors.New("no enabled key found in keyset")
111 }
112
113 switch k.GetTypeUrl() {
114 case ecdsaSignerTypeURL:
115
116 privKey := new(ecdsapb.EcdsaPrivateKey)
117 if err := proto.Unmarshal(k.GetValue(), privKey); err != nil {
118 return nil, fmt.Errorf("error unmarshalling ecdsa private key: %w", err)
119 }
120 if err := validateEcdsaPrivKey(privKey); err != nil {
121 return nil, fmt.Errorf("error validating ecdsa private key: %w", err)
122 }
123
124 _, curve, _ := getECDSAParamNames(privKey.PublicKey.Params)
125 p := new(ecdsa.PrivateKey)
126 c := subtle.GetCurve(curve)
127 p.PublicKey.Curve = c
128 p.D = new(big.Int).SetBytes(privKey.GetKeyValue())
129 p.PublicKey.X, p.PublicKey.Y = c.ScalarBaseMult(privKey.GetKeyValue())
130 return p, nil
131 case ed25519SignerTypeURL:
132
133 privKey := new(ed25519pb.Ed25519PrivateKey)
134 if err := proto.Unmarshal(k.GetValue(), privKey); err != nil {
135 return nil, fmt.Errorf("error unmarshalling ed25519 private key: %w", err)
136 }
137 if err := validateEd25519PrivKey(privKey); err != nil {
138 return nil, fmt.Errorf("error validating ed25519 private key: %w", err)
139 }
140
141 p := ed25519.NewKeyFromSeed(privKey.GetKeyValue())
142 return p, nil
143 default:
144 return nil, fmt.Errorf("unsupported key type: %s", k.GetTypeUrl())
145 }
146 }
147
148
149 func getPrimaryKey(ks *tinkpb.Keyset) *tinkpb.KeyData {
150 for _, k := range ks.GetKey() {
151 if k.GetKeyId() == ks.GetPrimaryKeyId() && k.GetStatus() == tinkpb.KeyStatusType_ENABLED {
152 return k.GetKeyData()
153 }
154 }
155 return nil
156 }
157
158
159
160 func validateEcdsaPrivKey(key *ecdsapb.EcdsaPrivateKey) error {
161 if err := keyset.ValidateKeyVersion(key.Version, uint32(ecdsaSignerKeyVersion)); err != nil {
162 return fmt.Errorf("ecdsa_signer_key_manager: invalid key: %w", err)
163 }
164 hash, curve, encoding := getECDSAParamNames(key.PublicKey.Params)
165 return signatureSubtle.ValidateECDSAParams(hash, curve, encoding)
166 }
167
168
169
170
171 func getECDSAParamNames(params *ecdsapb.EcdsaParams) (string, string, string) {
172 hashName := commonpb.HashType_name[int32(params.HashType)]
173 curveName := commonpb.EllipticCurveType_name[int32(params.Curve)]
174 encodingName := ecdsapb.EcdsaSignatureEncoding_name[int32(params.Encoding)]
175 return hashName, curveName, encodingName
176 }
177
178
179
180 func validateEd25519PrivKey(key *ed25519pb.Ed25519PrivateKey) error {
181 if err := keyset.ValidateKeyVersion(key.Version, uint32(ed25519SignerKeyVersion)); err != nil {
182 return fmt.Errorf("ed25519_signer_key_manager: invalid key: %w", err)
183 }
184 if len(key.KeyValue) != ed25519.SeedSize {
185 return fmt.Errorf("ed2219_signer_key_manager: invalid key length, got %d", len(key.KeyValue))
186 }
187 return nil
188 }
189
View as plain text