From 449e811ebe3135a35d04afc84c2e9c9481d637fe Mon Sep 17 00:00:00 2001 From: Saksham Sharma Date: Sat, 22 Jul 2017 11:45:36 -0700 Subject: [PATCH] Add benchmarks for envelope transformer --- .../pkg/storage/value/encrypt/envelope/BUILD | 6 +- .../value/encrypt/envelope/envelope.go | 16 +++-- .../value/encrypt/envelope/envelope_test.go | 64 ++++++++++++++++++- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD index 55e6204a6f1..1cc1da54175 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD @@ -15,7 +15,6 @@ go_library( deps = [ "//vendor/github.com/hashicorp/golang-lru:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library", - "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library", ], ) @@ -24,5 +23,8 @@ go_test( srcs = ["envelope_test.go"], library = ":go_default_library", tags = ["automanaged"], - deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"], + deps = [ + "//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library", + "//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library", + ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go index 3ae4ec2b7a0..acb26e6f5ed 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go @@ -19,12 +19,12 @@ package envelope import ( "crypto/aes" + "crypto/cipher" "crypto/rand" "encoding/binary" "fmt" "k8s.io/apiserver/pkg/storage/value" - aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes" lru "github.com/hashicorp/golang-lru" ) @@ -48,13 +48,16 @@ type envelopeTransformer struct { // cacheSize is the maximum number of DEKs that are cached. cacheSize int + + // baseTransformerFunc creates a new transformer for encrypting the data with the DEK. + baseTransformerFunc func(cipher.Block) value.Transformer } // NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme. // It uses envelopeService to encrypt and decrypt DEKs. Respective DEKs (in encrypted form) are prepended to // the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently // used decrypted DEKs in memory. -func NewEnvelopeTransformer(envelopeService Service, cacheSize int) (value.Transformer, error) { +func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) (value.Transformer, error) { if cacheSize == 0 { cacheSize = defaultCacheSize } @@ -63,9 +66,10 @@ func NewEnvelopeTransformer(envelopeService Service, cacheSize int) (value.Trans return nil, err } return &envelopeTransformer{ - envelopeService: envelopeService, - transformers: cache, - cacheSize: cacheSize, + envelopeService: envelopeService, + transformers: cache, + cacheSize: cacheSize, + baseTransformerFunc: baseTransformerFunc, }, nil } @@ -141,7 +145,7 @@ func (t *envelopeTransformer) addTransformer(encKey string, key []byte) (value.T if err != nil { return nil, err } - transformer := aestransformer.NewCBCTransformer(block) + transformer := t.baseTransformerFunc(block) t.transformers.Add(encKey, transformer) return transformer, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go index 2832dd5dc78..0ba68afc63d 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go @@ -18,6 +18,7 @@ package envelope import ( "bytes" + "crypto/aes" "encoding/base64" "fmt" "strconv" @@ -25,6 +26,7 @@ import ( "testing" "k8s.io/apiserver/pkg/storage/value" + aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes" ) const ( @@ -76,7 +78,7 @@ func newTestEnvelopeService() *testEnvelopeService { // Throw error if Envelope transformer tries to contact Envelope without hitting cache. func TestEnvelopeCaching(t *testing.T) { envelopeService := newTestEnvelopeService() - envelopeTransformer, err := NewEnvelopeTransformer(envelopeService, testEnvelopeCacheSize) + envelopeTransformer, err := NewEnvelopeTransformer(envelopeService, testEnvelopeCacheSize, aestransformer.NewCBCTransformer) if err != nil { t.Fatalf("failed to initialize envelope transformer: %v", err) } @@ -108,7 +110,7 @@ func TestEnvelopeCaching(t *testing.T) { // Makes Envelope transformer hit cache limit, throws error if it misbehaves. func TestEnvelopeCacheLimit(t *testing.T) { - envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize) + envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewCBCTransformer) if err != nil { t.Fatalf("failed to initialize envelope transformer: %v", err) } @@ -141,3 +143,61 @@ func TestEnvelopeCacheLimit(t *testing.T) { } } } + +func BenchmarkEnvelopeCBCRead(b *testing.B) { + envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewCBCTransformer) + if err != nil { + b.Fatalf("failed to initialize envelope transformer: %v", err) + } + benchmarkRead(b, envelopeTransformer, 1024) +} + +func BenchmarkAESCBCRead(b *testing.B) { + block, err := aes.NewCipher(bytes.Repeat([]byte("a"), 32)) + if err != nil { + b.Fatal(err) + } + + aesCBCTransformer := aestransformer.NewCBCTransformer(block) + benchmarkRead(b, aesCBCTransformer, 1024) +} + +func BenchmarkEnvelopeGCMRead(b *testing.B) { + envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewGCMTransformer) + if err != nil { + b.Fatalf("failed to initialize envelope transformer: %v", err) + } + benchmarkRead(b, envelopeTransformer, 1024) +} + +func BenchmarkAESGCMRead(b *testing.B) { + block, err := aes.NewCipher(bytes.Repeat([]byte("a"), 32)) + if err != nil { + b.Fatal(err) + } + + aesGCMTransformer := aestransformer.NewGCMTransformer(block) + benchmarkRead(b, aesGCMTransformer, 1024) +} + +func benchmarkRead(b *testing.B, transformer value.Transformer, valueLength int) { + context := value.DefaultContext([]byte(testContextText)) + v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16) + + out, err := transformer.TransformToStorage(v, context) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + from, stale, err := transformer.TransformFromStorage(out, context) + if err != nil { + b.Fatal(err) + } + if stale { + b.Fatalf("unexpected data: %t %q", stale, from) + } + } + b.StopTimer() +}