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
|
package kms
import (
"context"
"fmt"
)
// KMSProvider defines the interface for Key Management Service implementations
type KMSProvider interface {
// GenerateDataKey creates a new data encryption key encrypted under the specified KMS key
GenerateDataKey(ctx context.Context, req *GenerateDataKeyRequest) (*GenerateDataKeyResponse, error)
// Decrypt decrypts an encrypted data key using the KMS
Decrypt(ctx context.Context, req *DecryptRequest) (*DecryptResponse, error)
// DescribeKey validates that a key exists and returns its metadata
DescribeKey(ctx context.Context, req *DescribeKeyRequest) (*DescribeKeyResponse, error)
// GetKeyID resolves a key alias or ARN to the actual key ID
GetKeyID(ctx context.Context, keyIdentifier string) (string, error)
// Close cleans up any resources used by the provider
Close() error
}
// GenerateDataKeyRequest contains parameters for generating a data key
type GenerateDataKeyRequest struct {
KeyID string // KMS key identifier (ID, ARN, or alias)
KeySpec KeySpec // Specification for the data key
EncryptionContext map[string]string // Additional authenticated data
}
// GenerateDataKeyResponse contains the generated data key
type GenerateDataKeyResponse struct {
KeyID string // The actual KMS key ID used
Plaintext []byte // The plaintext data key (sensitive - clear from memory ASAP)
CiphertextBlob []byte // The encrypted data key for storage
}
// DecryptRequest contains parameters for decrypting a data key
type DecryptRequest struct {
CiphertextBlob []byte // The encrypted data key
EncryptionContext map[string]string // Must match the context used during encryption
}
// DecryptResponse contains the decrypted data key
type DecryptResponse struct {
KeyID string // The KMS key ID that was used for encryption
Plaintext []byte // The decrypted data key (sensitive - clear from memory ASAP)
}
// DescribeKeyRequest contains parameters for describing a key
type DescribeKeyRequest struct {
KeyID string // KMS key identifier (ID, ARN, or alias)
}
// DescribeKeyResponse contains key metadata
type DescribeKeyResponse struct {
KeyID string // The actual key ID
ARN string // The key ARN
Description string // Key description
KeyUsage KeyUsage // How the key can be used
KeyState KeyState // Current state of the key
Origin KeyOrigin // Where the key material originated
}
// KeySpec specifies the type of data key to generate
type KeySpec string
const (
KeySpecAES256 KeySpec = "AES_256" // 256-bit AES key
)
// KeyUsage specifies how a key can be used
type KeyUsage string
const (
KeyUsageEncryptDecrypt KeyUsage = "ENCRYPT_DECRYPT"
KeyUsageGenerateDataKey KeyUsage = "GENERATE_DATA_KEY"
)
// KeyState represents the current state of a KMS key
type KeyState string
const (
KeyStateEnabled KeyState = "Enabled"
KeyStateDisabled KeyState = "Disabled"
KeyStatePendingDeletion KeyState = "PendingDeletion"
KeyStateUnavailable KeyState = "Unavailable"
)
// KeyOrigin indicates where the key material came from
type KeyOrigin string
const (
KeyOriginAWS KeyOrigin = "AWS_KMS"
KeyOriginExternal KeyOrigin = "EXTERNAL"
KeyOriginCloudHSM KeyOrigin = "AWS_CLOUDHSM"
KeyOriginAzure KeyOrigin = "AZURE_KEY_VAULT"
KeyOriginGCP KeyOrigin = "GCP_KMS"
KeyOriginOpenBao KeyOrigin = "OPENBAO"
KeyOriginLocal KeyOrigin = "LOCAL"
)
// KMSError represents an error from the KMS service
type KMSError struct {
Code string // Error code (e.g., "KeyUnavailableException")
Message string // Human-readable error message
KeyID string // Key ID that caused the error (if applicable)
}
func (e *KMSError) Error() string {
if e.KeyID != "" {
return fmt.Sprintf("KMS error %s for key %s: %s", e.Code, e.KeyID, e.Message)
}
return fmt.Sprintf("KMS error %s: %s", e.Code, e.Message)
}
// Common KMS error codes
const (
ErrCodeKeyUnavailable = "KeyUnavailableException"
ErrCodeAccessDenied = "AccessDeniedException"
ErrCodeNotFoundException = "NotFoundException"
ErrCodeInvalidKeyUsage = "InvalidKeyUsageException"
ErrCodeKMSInternalFailure = "KMSInternalException"
ErrCodeInvalidCiphertext = "InvalidCiphertextException"
)
// EncryptionContextKey constants for building encryption context
const (
EncryptionContextS3ARN = "aws:s3:arn"
EncryptionContextS3Bucket = "aws:s3:bucket"
EncryptionContextS3Object = "aws:s3:object"
)
// BuildS3EncryptionContext creates the standard encryption context for S3 objects
// Following AWS S3 conventions from the documentation
func BuildS3EncryptionContext(bucketName, objectKey string, useBucketKey bool) map[string]string {
context := make(map[string]string)
if useBucketKey {
// When using S3 Bucket Keys, use bucket ARN as encryption context
context[EncryptionContextS3ARN] = fmt.Sprintf("arn:aws:s3:::%s", bucketName)
} else {
// For individual object encryption, use object ARN as encryption context
context[EncryptionContextS3ARN] = fmt.Sprintf("arn:aws:s3:::%s/%s", bucketName, objectKey)
}
return context
}
// ClearSensitiveData securely clears sensitive byte slices
func ClearSensitiveData(data []byte) {
if data != nil {
for i := range data {
data[i] = 0
}
}
}
|