1// Copyright 2017 Google Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17// Package awskms provides integration with the AWS Key Management Service. 18package awskms 19 20import ( 21 "encoding/hex" 22 23 "github.com/aws/aws-sdk-go/aws" 24 "github.com/aws/aws-sdk-go/service/kms" 25 "github.com/aws/aws-sdk-go/service/kms/kmsiface" 26) 27 28// AWSAEAD is an implementation of the AEAD interface which performs 29// cryptographic operations remotely via the AWS KMS service using a specific 30// key URI. 31type AWSAEAD struct { 32 keyURI string 33 kms kmsiface.KMSAPI 34 encryptionContextName EncryptionContextName 35} 36 37// newAWSAEAD returns a new AWSAEAD instance. 38// 39// keyURI must have the following format: 40// 41// aws-kms://arn:<partition>:kms:<region>:[<path>] 42// 43// See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html. 44func newAWSAEAD(keyURI string, kms kmsiface.KMSAPI, name EncryptionContextName) *AWSAEAD { 45 return &AWSAEAD{ 46 keyURI: keyURI, 47 kms: kms, 48 encryptionContextName: name, 49 } 50} 51 52// Encrypt encrypts the plaintext with associatedData. 53func (a *AWSAEAD) Encrypt(plaintext, associatedData []byte) ([]byte, error) { 54 req := &kms.EncryptInput{ 55 KeyId: aws.String(a.keyURI), 56 Plaintext: plaintext, 57 } 58 if len(associatedData) > 0 { 59 ad := hex.EncodeToString(associatedData) 60 req.EncryptionContext = map[string]*string{a.encryptionContextName.String(): &ad} 61 } 62 resp, err := a.kms.Encrypt(req) 63 if err != nil { 64 return nil, err 65 } 66 return resp.CiphertextBlob, nil 67} 68 69// Decrypt decrypts the ciphertext and verifies the associated data. 70func (a *AWSAEAD) Decrypt(ciphertext, associatedData []byte) ([]byte, error) { 71 req := &kms.DecryptInput{ 72 KeyId: aws.String(a.keyURI), 73 CiphertextBlob: ciphertext, 74 } 75 if len(associatedData) > 0 { 76 ad := hex.EncodeToString(associatedData) 77 req.EncryptionContext = map[string]*string{a.encryptionContextName.String(): &ad} 78 } 79 resp, err := a.kms.Decrypt(req) 80 if err != nil { 81 return nil, err 82 } 83 return resp.Plaintext, nil 84} 85