-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathexampleUtils.go
More file actions
336 lines (287 loc) · 9.66 KB
/
exampleUtils.go
File metadata and controls
336 lines (287 loc) · 9.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package utils
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
"github.com/aws/aws-cryptographic-material-providers-library/primitives/awscryptographyprimitivessmithygeneratedtypes"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/google/uuid"
)
const (
testKmsRsaPublicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA27Uc/fBaMVhxCE/SpCMQ
oSBRSzQJw+o2hBaA+FiPGtiJ/aPy7sn18aCkelaSj4kwoC79b/arNHlkjc7OJFsN
/GoFKgNvaiY4lOeJqEiWQGSSgHtsJLdbO2u4OOSxh8qIRAMKbMgQDVX4FR/PLKeK
fc2aCDvcNSpAM++8NlNmv7+xQBJydr5ce91eISbHkFRkK3/bAM+1iddupoRw4Wo2
r3avzrg5xBHmzR7u1FTab22Op3Hgb2dBLZH43wNKAceVwKqKA8UNAxashFON7xK9
yy4kfOL0Z/nhxRKe4jRZ/5v508qIzgzCksYy7Y3QbMejAtiYnr7s5/d5KWw0swou
twIDAQAB
-----END PUBLIC KEY-----`
testKmsRsaKeyID = "arn:aws:kms:us-west-2:370957321024:key/mrk-63d386cb70614ea59b32ad65c9315297"
testDefaultKMSKeyId = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"
defaultKmsKeyRegion = "us-west-2"
testAlternateRegionKMSKeyId = "arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2"
testAlternateRegionKMSKeyRegion = "eu-central-1"
testDefaultMRKKeyId = "arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7"
defaultMRKKeyRegion = "us-east-1"
testAlternateRegionMrkKeyId = "arn:aws:kms:eu-west-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7"
alternateRegionMrkKeyRegion = "eu-west-1"
testKeyStoreKMSKeyRegion = "us-west-2"
testKeyStoreKMSKeyID = "arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"
testLogicalKeyStoreName = "KeyStoreDdbTable"
testKeyStoreName = "KeyStoreDdbTable"
testKeyStoreRegion = "us-west-2"
defaultKMSKeyAccountID = "658956600833"
eccPrivateKeyFileNameSender = "sender_private.pem"
eccPrivateKeyFileNameRecipient = "recipient_private.pem"
eccPublicKeyFileNameRecipient = "recipient_public.pem"
kmsEccPublicKeyFileNameRecipient = "KmsEccKeyringExamplePublicKeyRecipient.pem"
kmsEccPublicKeyFileNameSender = "KmsEccKeyringExamplePublicKeySender.pem"
testKmsEcdhKeyIdP256SenderKeyId = "arn:aws:kms:us-west-2:370957321024:key/eabdf483-6be2-4d2d-8ee4-8c2583d416e9"
testKmsEcdhKeyIdP256RecipientKeyId = "arn:aws:kms:us-west-2:370957321024:key/0265c8e9-5b6a-4055-8f70-63719e09fda5"
)
// Getter functions
func KmsEcdhKeyIdP256SenderKeyId() string {
return testKmsEcdhKeyIdP256SenderKeyId
}
func KmsEcdhKeyIdP256RecipientKeyId() string {
return testKmsEcdhKeyIdP256RecipientKeyId
}
func KmsEccPublicKeyFileNameRecipient() string {
return kmsEccPublicKeyFileNameRecipient
}
func KmsEccPublicKeyFileNameSender() string {
return kmsEccPublicKeyFileNameSender
}
func EccPrivateKeyFileNameSender() string {
return eccPrivateKeyFileNameSender
}
func EccPrivateKeyFileNameRecipient() string {
return eccPrivateKeyFileNameRecipient
}
func EccPublicKeyFileNameRecipient() string {
return eccPublicKeyFileNameRecipient
}
func RegionsOfMRKKeys() []string {
return []string{defaultMRKKeyRegion, alternateRegionMrkKeyRegion}
}
func Regions() []string {
return []string{defaultKmsKeyRegion, testAlternateRegionKMSKeyRegion}
}
func DefaultKmsKeyRegion() string {
return defaultKmsKeyRegion
}
func DefaultMRKKeyRegion() string {
return defaultMRKKeyRegion
}
func AlternateRegionMrkKeyRegion() string {
return alternateRegionMrkKeyRegion
}
func AlternateRegionMrkKeyArn() string {
return testAlternateRegionMrkKeyId
}
func DefaultRegionMrkKeyArn() string {
return testDefaultMRKKeyId
}
func AlternateRegionKMSKeyRegion() string {
return testAlternateRegionKMSKeyRegion
}
func AlternateRegionKMSKeyId() string {
return testAlternateRegionKMSKeyId
}
func DefaultKMSKeyAccountID() string {
return defaultKMSKeyAccountID
}
func DefaultKMSKeyId() string {
return testDefaultKMSKeyId
}
func TestKmsRsaKeyID() string {
return testKmsRsaKeyID
}
func KmsRSAPublicKey() []byte {
return []byte(testKmsRsaPublicKey)
}
func KeyStoreRegion() string {
return testKeyStoreRegion
}
func KeyStoreKMSKeyRegion() string {
return testKeyStoreKMSKeyRegion
}
func KeyStoreKMSKeyID() string {
return testKeyStoreKMSKeyID
}
func LogicalKeyStoreName() string {
return testLogicalKeyStoreName
}
func KeyStoreName() string {
return testKeyStoreName
}
// Utility functions
func WriteRawEcdhEccKeys(ecdhCurveSpec awscryptographyprimitivessmithygeneratedtypes.ECDHCurveSpec) error {
// Safety check: Validate neither file is present
if FileExists(eccPrivateKeyFileNameSender) ||
FileExists(eccPrivateKeyFileNameRecipient) ||
FileExists(eccPublicKeyFileNameRecipient) {
return errors.New("WriteRawEcdhEccKeys will not overwrite existing PEM files")
}
// Generate key pairs
_, privateKeySender, err := generateRawEccKeyPair(ecdhCurveSpec)
if err != nil {
return err
}
publicKeyRecipient, privateKeyRecipient, err := generateRawEccKeyPair(ecdhCurveSpec)
if err != nil {
return err
}
// Create PEM blocks
privateKeySenderPEM := &pem.Block{
Type: "PRIVATE KEY",
Bytes: privateKeySender,
}
privateKeyRecipientPEM := &pem.Block{
Type: "PRIVATE KEY",
Bytes: privateKeyRecipient,
}
publicKeyRecipientPEM := &pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyRecipient,
}
// Write private key for sender in PEM format
err = os.WriteFile(
eccPrivateKeyFileNameSender,
pem.EncodeToMemory(privateKeySenderPEM),
0600,
)
if err != nil {
return fmt.Errorf("failed to write sender's private key: %w", err)
}
// Write private key for recipient in PEM format
err = os.WriteFile(
eccPrivateKeyFileNameRecipient,
pem.EncodeToMemory(privateKeyRecipientPEM),
0600,
)
if err != nil {
return fmt.Errorf("failed to write recipient's private key: %w", err)
}
// Write public key for recipient in PEM format
err = os.WriteFile(
eccPublicKeyFileNameRecipient,
pem.EncodeToMemory(publicKeyRecipientPEM),
0600,
)
if err != nil {
return fmt.Errorf("failed to write recipient's public key: %w", err)
}
return nil
}
func LoadPublicKeyFromPEM(filename string) ([]byte, error) {
// Read the PEM file content as string
pemContent, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read PEM file: %w", err)
}
// Parse PEM block
block, _ := pem.Decode(pemContent)
if block == nil {
return nil, fmt.Errorf("failed to decode PEM block")
}
// The block.Bytes contains the DER encoded key
return block.Bytes, nil
}
func FileExists(filename string) bool {
_, err := os.Stat(filename)
return !os.IsNotExist(err)
}
func generateRawEccKeyPair(curveSpec awscryptographyprimitivessmithygeneratedtypes.ECDHCurveSpec) ([]byte, []byte, error) {
// Select the appropriate elliptic curve based on the specification
var curve elliptic.Curve
switch curveSpec {
case awscryptographyprimitivessmithygeneratedtypes.ECDHCurveSpecEccNistP256:
curve = elliptic.P256()
case awscryptographyprimitivessmithygeneratedtypes.ECDHCurveSpecEccNistP384:
curve = elliptic.P384()
case awscryptographyprimitivessmithygeneratedtypes.ECDHCurveSpecEccNistP521:
curve = elliptic.P521()
default:
return nil, nil, fmt.Errorf("unsupported curve specification: %s", curveSpec)
}
// Generate the private key
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, nil, fmt.Errorf("failed to generate private key: %w", err)
}
// Extract the public key
publicKey := &privateKey.PublicKey
// Marshal the private key to bytes (X.509 PKCS#8 format)
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal private key: %w", err)
}
// Marshal the public key to bytes (X.509 SPKI format)
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal public key: %w", err)
}
return publicKeyBytes, privateKeyBytes, nil
}
func WriteKmsEcdhEccPublicKey(eccKeyArn, publicKeyFileName string, kmsClient *kms.Client) error {
// Safety check: Validate neither file is present
if FileExists(publicKeyFileName) {
return errors.New("WriteKmsEcdhEccPublicKey will not overwrite existing PEM files")
}
// Generate public key
publicKey, err := GenerateKmsEccPublicKey(eccKeyArn, kmsClient)
if err != nil {
return fmt.Errorf("failed to generate public key: %w", err)
}
// Create PEM block
pemBlock := &pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKey,
}
// Encode PEM
pemData := pem.EncodeToMemory(pemBlock)
if pemData == nil {
return errors.New("failed to encode PEM data")
}
// Write file with proper permissions
err = os.WriteFile(publicKeyFileName, pemData, 0600)
if err != nil {
return fmt.Errorf("failed to write public key file: %w", err)
}
return nil
}
func GenerateKmsEccPublicKey(eccKeyArn string, kmsClient *kms.Client) ([]byte, error) {
ctx := context.Background()
// Get public key from KMS
response, err := kmsClient.GetPublicKey(ctx, &kms.GetPublicKeyInput{
KeyId: &eccKeyArn,
})
if err != nil {
return nil, fmt.Errorf("failed to get public key from KMS: %w", err)
}
// Check if public key is present
if response.PublicKey == nil {
return nil, errors.New("no public key in KMS response")
}
return response.PublicKey, nil
}
// GenerateUUIDTestData creates an array of random UUID strings
func GenerateUUIDTestData(count int) []string {
testData := make([]string, count)
for i := 0; i < count; i++ {
// Generate a random UUID
uuid := uuid.New()
testData[i] = uuid.String()
}
return testData
}