diff --git a/api-put-object-multipart.go b/api-put-object-multipart.go index 8805ecf96..52dc069d0 100644 --- a/api-put-object-multipart.go +++ b/api-put-object-multipart.go @@ -259,7 +259,7 @@ func (c Client) uploadPart(ctx context.Context, bucketName, objectName, uploadID // Set encryption headers, if any. customHeader := make(http.Header) - if sse != nil { + if sse != nil && sse.Type() != encrypt.S3 && sse.Type() != encrypt.KMS { sse.Marshal(customHeader) } diff --git a/pkg/encrypt/server-side.go b/pkg/encrypt/server-side.go index 92f5bf5ea..f3853e7b9 100644 --- a/pkg/encrypt/server-side.go +++ b/pkg/encrypt/server-side.go @@ -20,6 +20,7 @@ package encrypt import ( "crypto/md5" "encoding/base64" + "encoding/json" "errors" "net/http" @@ -30,6 +31,11 @@ const ( // sseGenericHeader is the AWS SSE header used for SSE-S3 and SSE-KMS. sseGenericHeader = "X-Amz-Server-Side-Encryption" + // sseKmsKeyID is the AWS SSE-KMS key id. + sseKmsKeyID = sseGenericHeader + "-Aws-Kms-Key-Id" + // sseEncryptionContext is the AWS SSE-KMS Encryption Context data. + sseEncryptionContext = sseGenericHeader + "-Encryption-Context" + // sseCustomerAlgorithm is the AWS SSE-C algorithm HTTP header key. sseCustomerAlgorithm = sseGenericHeader + "-Customer-Algorithm" // sseCustomerKey is the AWS SSE-C encryption key HTTP header key. @@ -90,6 +96,18 @@ type ServerSide interface { // Using SSE-S3 the server will encrypt the object with server-managed keys. func NewSSE() ServerSide { return s3{} } +// NewSSEKMS returns a new server-side-encryption using SSE-KMS and the provided Key Id and context. +func NewSSEKMS(keyID string, context interface{}) (ServerSide, error) { + if context == nil { + return kms{key: keyID, hasContext: false}, nil + } + serializedContext, err := json.Marshal(context) + if err != nil { + return nil, err + } + return kms{key: keyID, context: serializedContext, hasContext: true}, nil +} + // NewSSEC returns a new server-side-encryption using SSE-C and the provided key. // The key must be 32 bytes long. func NewSSEC(key []byte) (ServerSide, error) { @@ -144,3 +162,19 @@ type s3 struct{} func (s s3) Type() Type { return S3 } func (s s3) Marshal(h http.Header) { h.Set(sseGenericHeader, "AES256") } + +type kms struct { + key string + context []byte + hasContext bool +} + +func (s kms) Type() Type { return KMS } + +func (s kms) Marshal(h http.Header) { + h.Set(sseGenericHeader, "aws:kms") + h.Set(sseKmsKeyID, s.key) + if s.hasContext { + h.Set(sseEncryptionContext, base64.StdEncoding.EncodeToString(s.context)) + } +}