From 27853d4176e5af9334138c32377bc0a885437c78 Mon Sep 17 00:00:00 2001 From: Joseph Herlant Date: Tue, 27 Mar 2018 16:02:07 -0700 Subject: [PATCH] Migrate hmac to []byte and handle transition --- decode.go | 11 +++++++++++ ds.go | 9 +++++---- encryptor.go | 7 +++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/decode.go b/decode.go index 956a4fa..59956e7 100644 --- a/decode.go +++ b/decode.go @@ -5,7 +5,18 @@ import ( "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" ) +// adjustHmac will force the hmac to be a byte array if present as string +func adjustHmac(record map[string]*dynamodb.AttributeValue) { + if val, ok := record["hmac"]; ok { + if len(val.B) == 0 && val.S != nil { + val.B = []byte(*val.S) + val.S = nil + } + } +} + // Decode decode the supplied struct from the dynamodb result map func Decode(data map[string]*dynamodb.AttributeValue, rawVal interface{}) error { + adjustHmac(data) return dynamodbattribute.UnmarshalMap(data, rawVal) } diff --git a/ds.go b/ds.go index fd4ca30..9733b61 100644 --- a/ds.go +++ b/ds.go @@ -1,6 +1,7 @@ package unicreds import ( + "bytes" "encoding/base64" "errors" "io/ioutil" @@ -62,7 +63,7 @@ type Credential struct { Version string `dynamodbav:"version"` Key string `dynamodbav:"key"` Contents string `dynamodbav:"contents"` - Hmac string `dynamodbav:"hmac"` + Hmac []byte `dynamodbav:"hmac"` CreatedAt int64 `dynamodbav:"created_at"` } @@ -168,7 +169,7 @@ func GetHighestVersionSecret(tableName *string, name string, encContext *Encrypt "#N": aws.String("name"), }, ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ - ":name": &dynamodb.AttributeValue{ + ":name": { S: aws.String(name), }, }, @@ -235,7 +236,7 @@ func GetHighestVersion(tableName *string, name string) (string, error) { "#N": aws.String("name"), }, ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ - ":name": &dynamodb.AttributeValue{ + ":name": { S: aws.String(name), }, }, @@ -548,7 +549,7 @@ func decryptCredential(cred *Credential, encContext *EncryptionContextValue) (*D hexhmac := ComputeHmac256(contents, hmacKey) - if hexhmac != cred.Hmac { + if !bytes.Equal(hexhmac, cred.Hmac) { return nil, ErrHmacValidationFailed } diff --git a/encryptor.go b/encryptor.go index 63b373b..2511a2f 100644 --- a/encryptor.go +++ b/encryptor.go @@ -28,10 +28,13 @@ func Encrypt(key, plaintext []byte) ([]byte, error) { // ComputeHmac256 compute a hmac256 signature of the supplied message and return // the value hex encoded -func ComputeHmac256(message, secret []byte) string { +func ComputeHmac256(message, secret []byte) []byte { h := hmac.New(sha256.New, secret) h.Write(message) - return hex.EncodeToString(h.Sum(nil)) + src := h.Sum(nil) + dst := make([]byte, hex.EncodedLen(len(src))) + hex.Encode(dst, src) + return dst } // Decrypt AES encryption method which matches the pycrypto package