Skip to content

Commit

Permalink
Changed encryption keys from hex encoded UUID to base64 encoded crypt…
Browse files Browse the repository at this point in the history
…o.Rand using AES-256 32 bytes. Releasing v0.7.3
  • Loading branch information
pdt256 committed Jan 26, 2021
1 parent e4e0265 commit 21e8240
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 175 deletions.
24 changes: 6 additions & 18 deletions pkg/crypto/aes/gcm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,15 @@ import (
"io"
)

// GCMOption defines functional option parameters for GCM.
type GCMOption func(*GCM)

// WithRandReader is a functional option to inject a random reader.
func WithRandReader(randReader io.Reader) GCMOption {
return func(e *GCM) {
e.randReader = randReader
}
}

type GCM struct {
randReader io.Reader
}

// NewGCM constructs an AES/GCM encryption engine.
func NewGCM(options ...GCMOption) *GCM {
e := &GCM{
func NewGCM() *GCM {
return &GCM{
randReader: rand.Reader,
}

for _, option := range options {
option(e)
}

return e
}

// Encrypt returns AES/GCM base64 cipher text.
Expand Down Expand Up @@ -112,3 +96,7 @@ func (e *GCM) decrypt(key, sealedCipherText []byte) ([]byte, error) {

return plainText, nil
}

func (e *GCM) SetRandReader(randReader io.Reader) {
e.randReader = randReader
}
6 changes: 4 additions & 2 deletions pkg/crypto/aes/gcm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ func TestGCM_Errors(t *testing.T) {
t.Run("unable to read nonce during encrypt", func(t *testing.T) {
// Given
failingReader := failingReader{}
encryptor := aes.NewGCM(aes.WithRandReader(failingReader))
encryptor := aes.NewGCM()
encryptor.SetRandReader(failingReader)

// When
encryptedValue, err := encryptor.Encrypt(aestest.ValidAES256Base64Key, aestest.PlainText)
Expand All @@ -32,7 +33,8 @@ func TestGCM_Errors(t *testing.T) {
// Given
const InvalidShortAESGCMBase64CipherText = "Glq32jvn9nPO/pqxN9p3YQT4pvoZuV4aQCOy/TIdEtqW8vtGMns="
failingReader := failingReader{}
encryptor := aes.NewGCM(aes.WithRandReader(failingReader))
encryptor := aes.NewGCM()
encryptor.SetRandReader(failingReader)

// When
encryptedValue, err := encryptor.Decrypt(aestest.ValidAES256Base64Key, InvalidShortAESGCMBase64CipherText)
Expand Down
29 changes: 0 additions & 29 deletions pkg/crypto/aes/key.go

This file was deleted.

39 changes: 0 additions & 39 deletions pkg/crypto/aes/key_test.go

This file was deleted.

14 changes: 7 additions & 7 deletions pkg/crypto/delete_encryption_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"fmt"
"math/rand"

"github.com/inklabs/rangedb/pkg/crypto"
"github.com/inklabs/rangedb/pkg/crypto/aes"
"github.com/inklabs/rangedb/pkg/crypto/cryptotest"
"github.com/inklabs/rangedb/pkg/crypto/eventencryptor"
"github.com/inklabs/rangedb/pkg/crypto/provider/inmemorykeystore"
"github.com/inklabs/rangedb/pkg/shortuuid"
)
Expand All @@ -15,11 +15,11 @@ func ExampleKeyStore_Delete() {
// Given
shortuuid.SetRand(100)
seededRandReader := rand.New(rand.NewSource(100))
aesEncryptor := aes.NewGCM(
aes.WithRandReader(seededRandReader),
)
aesEncryptor := aes.NewGCM()
aesEncryptor.SetRandReader(seededRandReader)
keyStore := inmemorykeystore.New()
eventEncryptor := crypto.NewEventEncryptor(keyStore, aesEncryptor)
eventEncryptor := eventencryptor.New(keyStore, aesEncryptor)
eventEncryptor.SetRandReader(seededRandReader)
event := &cryptotest.CustomerSignedUp{
ID: "62df778c16f84969a8a5448a9ce00218",
Name: "John Doe",
Expand All @@ -41,8 +41,8 @@ func ExampleKeyStore_Delete() {
// Output:
// {
// "ID": "62df778c16f84969a8a5448a9ce00218",
// "Name": "0rqOcAcpgzhCA8Q4w1VSEkTxMarX6atPEMylUm92UnBK2gnd",
// "Email": "1OlL85nL2Iu8r7grwuP5v1wusZ6GDOAWdTwn8IiBbdQx2+V2o7qpXmWH3r8=",
// "Name": "Lp5pGK8QGYw3NJyJVBsW49HESSf+NEraAQoBmpLXboZvsN/L",
// "Email": "o1H9t1BClYc5UcyUV+Roe3wz5gwRZRjgBI/xzwZs8ueQGQ5L8uGnbrTGrh8=",
// "Status": "active"
// }
// error: removed from GDPR request
Expand Down
14 changes: 7 additions & 7 deletions pkg/crypto/encrypt_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package crypto_test
import (
"math/rand"

"github.com/inklabs/rangedb/pkg/crypto"
"github.com/inklabs/rangedb/pkg/crypto/aes"
"github.com/inklabs/rangedb/pkg/crypto/cryptotest"
"github.com/inklabs/rangedb/pkg/crypto/eventencryptor"
"github.com/inklabs/rangedb/pkg/crypto/provider/inmemorykeystore"
"github.com/inklabs/rangedb/pkg/shortuuid"
)
Expand All @@ -14,11 +14,11 @@ func ExampleEventEncryptor_Encrypt() {
// Given
shortuuid.SetRand(100)
seededRandReader := rand.New(rand.NewSource(100))
aesEncryptor := aes.NewGCM(
aes.WithRandReader(seededRandReader),
)
aesEncryptor := aes.NewGCM()
aesEncryptor.SetRandReader(seededRandReader)
keyStore := inmemorykeystore.New()
eventEncryptor := crypto.NewEventEncryptor(keyStore, aesEncryptor)
eventEncryptor := eventencryptor.New(keyStore, aesEncryptor)
eventEncryptor.SetRandReader(seededRandReader)
event := &cryptotest.CustomerSignedUp{
ID: "fe65ac8d8c3a45e9b3cee407f10ee518",
Name: "John Doe",
Expand All @@ -36,8 +36,8 @@ func ExampleEventEncryptor_Encrypt() {
// Output:
// {
// "ID": "fe65ac8d8c3a45e9b3cee407f10ee518",
// "Name": "0rqOcAcpgzhCA8Q4w1VSEkTxMarX6atPEMylUm92UnBK2gnd",
// "Email": "1OlL85nL2Iu8r7grwuP5v1wusZ6GDOAWdTwn8IiBbdQx2+V2o7qpXmWH3r8=",
// "Name": "Lp5pGK8QGYw3NJyJVBsW49HESSf+NEraAQoBmpLXboZvsN/L",
// "Email": "o1H9t1BClYc5UcyUV+Roe3wz5gwRZRjgBI/xzwZs8ueQGQ5L8uGnbrTGrh8=",
// "Status": "active"
// }
// {
Expand Down
67 changes: 0 additions & 67 deletions pkg/crypto/event_encryptor.go

This file was deleted.

95 changes: 95 additions & 0 deletions pkg/crypto/eventencryptor/event_encryptor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package eventencryptor

import (
"crypto/rand"
"encoding/base64"
"io"

"github.com/inklabs/rangedb"
"github.com/inklabs/rangedb/pkg/crypto"
)

type eventEncryptor struct {
engine *engine
}

func New(store crypto.KeyStore, encryptor crypto.Encryptor) *eventEncryptor {
return &eventEncryptor{
engine: newEngine(store, encryptor),
}
}

func (e *eventEncryptor) Encrypt(event rangedb.Event) error {
if event, ok := event.(crypto.SelfEncryptor); ok {
return event.Encrypt(e.engine)
}

return nil
}

func (e *eventEncryptor) Decrypt(event rangedb.Event) error {
if event, ok := event.(crypto.SelfEncryptor); ok {
return event.Decrypt(e.engine)
}

return nil
}

func (e *eventEncryptor) SetRandReader(randReader io.Reader) {
e.engine.setRandReader(randReader)
}

type engine struct {
keyStore crypto.KeyStore
encryptor crypto.Encryptor
randReader io.Reader
}

func newEngine(store crypto.KeyStore, encryptor crypto.Encryptor) *engine {
return &engine{
keyStore: store,
encryptor: encryptor,
randReader: rand.Reader,
}
}

func (e *engine) Encrypt(subjectID, data string) (string, error) {
base64Key, err := e.keyStore.Get(subjectID)
if err == crypto.ErrKeyNotFound {
base64Key, err = e.newBase64AES256Key()
if err != nil {
return "", err
}

err = e.keyStore.Set(subjectID, base64Key)
}

if err != nil {
return "", err
}

return e.encryptor.Encrypt(base64Key, data)
}

func (e *engine) Decrypt(subjectID, cipherText string) (string, error) {
base64Key, err := e.keyStore.Get(subjectID)
if err != nil {
return "", err
}

return e.encryptor.Decrypt(base64Key, cipherText)
}

func (e *engine) newBase64AES256Key() (string, error) {
const aes256ByteLength = 32
encryptionKey := make([]byte, aes256ByteLength)
if _, err := io.ReadFull(e.randReader, encryptionKey); err != nil {
return "", err
}

return base64.StdEncoding.EncodeToString(encryptionKey), nil
}

func (e *engine) setRandReader(randReader io.Reader) {
e.randReader = randReader
}
Loading

0 comments on commit 21e8240

Please sign in to comment.