k8s.io/apiserver@v0.31.1/pkg/storage/value/encrypt/secretbox/secretbox_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package secretbox 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/rand" 23 "encoding/hex" 24 "fmt" 25 "io" 26 "reflect" 27 "testing" 28 29 "k8s.io/apiserver/pkg/storage/value" 30 ) 31 32 var ( 33 key1 = [32]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01} 34 key2 = [32]byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} 35 ) 36 37 func TestSecretboxKeyRotation(t *testing.T) { 38 testErr := fmt.Errorf("test error") 39 ctx := context.Background() 40 dataCtx := value.DefaultContext([]byte("authenticated_data")) 41 42 p := value.NewPrefixTransformers(testErr, 43 value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)}, 44 value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)}, 45 ) 46 out, err := p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx) 47 if err != nil { 48 t.Fatal(err) 49 } 50 if !bytes.HasPrefix(out, []byte("first:")) { 51 t.Fatalf("unexpected prefix: %q", out) 52 } 53 from, stale, err := p.TransformFromStorage(ctx, out, dataCtx) 54 if err != nil { 55 t.Fatal(err) 56 } 57 if stale || !bytes.Equal([]byte("firstvalue"), from) { 58 t.Fatalf("unexpected data: %t %q", stale, from) 59 } 60 61 // verify changing the context does not fails storage 62 // Secretbox is not currently an authenticating store 63 _, _, err = p.TransformFromStorage(ctx, out, value.DefaultContext([]byte("incorrect_context"))) 64 if err != nil { 65 t.Fatalf("secretbox is not authenticated") 66 } 67 68 // reverse the order, use the second key 69 p = value.NewPrefixTransformers(testErr, 70 value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)}, 71 value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)}, 72 ) 73 from, stale, err = p.TransformFromStorage(ctx, out, dataCtx) 74 if err != nil { 75 t.Fatal(err) 76 } 77 if !stale || !bytes.Equal([]byte("firstvalue"), from) { 78 t.Fatalf("unexpected data: %t %q", stale, from) 79 } 80 } 81 82 func BenchmarkSecretboxRead(b *testing.B) { 83 tests := []struct { 84 keyLength int 85 valueLength int 86 expectStale bool 87 }{ 88 {keyLength: 32, valueLength: 1024, expectStale: false}, 89 {keyLength: 32, valueLength: 16384, expectStale: false}, 90 {keyLength: 32, valueLength: 16384, expectStale: true}, 91 } 92 for _, t := range tests { 93 name := fmt.Sprintf("%vKeyLength/%vValueLength/%vExpectStale", t.keyLength, t.valueLength, t.expectStale) 94 b.Run(name, func(b *testing.B) { 95 benchmarkSecretboxRead(b, t.keyLength, t.valueLength, t.expectStale) 96 }) 97 } 98 } 99 100 func BenchmarkSecretboxWrite(b *testing.B) { 101 tests := []struct { 102 keyLength int 103 valueLength int 104 }{ 105 {keyLength: 32, valueLength: 1024}, 106 {keyLength: 32, valueLength: 16384}, 107 } 108 for _, t := range tests { 109 name := fmt.Sprintf("%vKeyLength/%vValueLength", t.keyLength, t.valueLength) 110 b.Run(name, func(b *testing.B) { 111 benchmarkSecretboxWrite(b, t.keyLength, t.valueLength) 112 }) 113 } 114 } 115 116 func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, expectStale bool) { 117 p := value.NewPrefixTransformers(nil, 118 value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)}, 119 value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)}, 120 ) 121 122 ctx := context.Background() 123 dataCtx := value.DefaultContext([]byte("authenticated_data")) 124 v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16) 125 126 out, err := p.TransformToStorage(ctx, v, dataCtx) 127 if err != nil { 128 b.Fatal(err) 129 } 130 // reverse the key order if expecting stale 131 if expectStale { 132 p = value.NewPrefixTransformers(nil, 133 value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)}, 134 value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)}, 135 ) 136 } 137 138 b.ResetTimer() 139 for i := 0; i < b.N; i++ { 140 from, stale, err := p.TransformFromStorage(ctx, out, dataCtx) 141 if err != nil { 142 b.Fatal(err) 143 } 144 if expectStale != stale { 145 b.Fatalf("unexpected data: %q, expect stale %t but got %t", from, expectStale, stale) 146 } 147 } 148 b.StopTimer() 149 } 150 151 func benchmarkSecretboxWrite(b *testing.B, keyLength int, valueLength int) { 152 p := value.NewPrefixTransformers(nil, 153 value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)}, 154 value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)}, 155 ) 156 157 ctx := context.Background() 158 dataCtx := value.DefaultContext([]byte("authenticated_data")) 159 v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16) 160 161 b.ResetTimer() 162 for i := 0; i < b.N; i++ { 163 _, err := p.TransformToStorage(ctx, v, dataCtx) 164 if err != nil { 165 b.Fatal(err) 166 } 167 } 168 b.StopTimer() 169 } 170 171 func TestRoundTrip(t *testing.T) { 172 lengths := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 128, 1024} 173 174 ctx := context.Background() 175 tests := []struct { 176 name string 177 dataCtx value.Context 178 t value.Transformer 179 }{ 180 {name: "Secretbox 32 byte key", t: NewSecretboxTransformer(key1)}, 181 } 182 for _, tt := range tests { 183 t.Run(tt.name, func(t *testing.T) { 184 dataCtx := tt.dataCtx 185 if dataCtx == nil { 186 dataCtx = value.DefaultContext([]byte("")) 187 } 188 for _, l := range lengths { 189 data := make([]byte, l) 190 if _, err := io.ReadFull(rand.Reader, data); err != nil { 191 t.Fatalf("unable to read sufficient random bytes: %v", err) 192 } 193 original := append([]byte{}, data...) 194 195 ciphertext, err := tt.t.TransformToStorage(ctx, data, dataCtx) 196 if err != nil { 197 t.Errorf("TransformToStorage error = %v", err) 198 continue 199 } 200 201 result, stale, err := tt.t.TransformFromStorage(ctx, ciphertext, dataCtx) 202 if err != nil { 203 t.Errorf("TransformFromStorage error = %v", err) 204 continue 205 } 206 if stale { 207 t.Errorf("unexpected stale output") 208 continue 209 } 210 211 switch { 212 case l == 0: 213 if len(result) != 0 { 214 t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result)) 215 } 216 case !reflect.DeepEqual(original, result): 217 t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result)) 218 } 219 } 220 }) 221 } 222 }