1package s3crypto 2 3import ( 4 "encoding/base64" 5 "encoding/hex" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/awstesting/unit" 13 "github.com/aws/aws-sdk-go/service/kms" 14) 15 16func TestWrapFactory(t *testing.T) { 17 o := DecryptionClientOptions{ 18 CryptoRegistry: initCryptoRegistryFrom(map[string]WrapEntry{ 19 KMSWrap: (kmsKeyHandler{ 20 kms: kms.New(unit.Session), 21 }).decryptHandler, 22 }, map[string]CEKEntry{ 23 AESGCMNoPadding: newAESGCMContentCipher, 24 }, map[string]Padder{}), 25 } 26 env := Envelope{ 27 WrapAlg: KMSWrap, 28 MatDesc: `{"kms_cmk_id":""}`, 29 } 30 wrap, err := wrapFromEnvelope(o, env) 31 w, ok := wrap.(*kmsKeyHandler) 32 33 if err != nil { 34 t.Errorf("expected no error, but received %v", err) 35 } 36 if wrap == nil { 37 t.Error("expected non-nil value") 38 } 39 if !ok { 40 t.Errorf("expected kmsKeyHandler, but received %v", *w) 41 } 42} 43func TestWrapFactoryErrorNoWrap(t *testing.T) { 44 o := DecryptionClientOptions{ 45 CryptoRegistry: initCryptoRegistryFrom(map[string]WrapEntry{ 46 KMSWrap: (kmsKeyHandler{ 47 kms: kms.New(unit.Session), 48 }).decryptHandler, 49 }, map[string]CEKEntry{ 50 AESGCMNoPadding: newAESGCMContentCipher, 51 }, map[string]Padder{}), 52 } 53 env := Envelope{ 54 WrapAlg: "none", 55 MatDesc: `{"kms_cmk_id":""}`, 56 } 57 wrap, err := wrapFromEnvelope(o, env) 58 59 if err == nil { 60 t.Error("expected error, but received none") 61 } 62 if wrap != nil { 63 t.Errorf("expected nil wrap value, received %v", wrap) 64 } 65} 66 67func TestWrapFactoryCustomEntry(t *testing.T) { 68 o := DecryptionClientOptions{ 69 CryptoRegistry: initCryptoRegistryFrom(map[string]WrapEntry{ 70 "custom": (kmsKeyHandler{ 71 kms: kms.New(unit.Session), 72 }).decryptHandler, 73 }, map[string]CEKEntry{ 74 AESGCMNoPadding: newAESGCMContentCipher, 75 }, map[string]Padder{}), 76 } 77 env := Envelope{ 78 WrapAlg: "custom", 79 MatDesc: `{"kms_cmk_id":""}`, 80 } 81 wrap, err := wrapFromEnvelope(o, env) 82 83 if err != nil { 84 t.Errorf("expected no error, but received %v", err) 85 } 86 if wrap == nil { 87 t.Errorf("expected nil wrap value, received %v", wrap) 88 } 89} 90 91func TestCEKFactory(t *testing.T) { 92 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 93 keyB64 := base64.URLEncoding.EncodeToString(key) 94 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 95 fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`)) 96 })) 97 defer ts.Close() 98 99 sess := unit.Session.Copy(&aws.Config{ 100 MaxRetries: aws.Int(0), 101 Endpoint: aws.String(ts.URL), 102 DisableSSL: aws.Bool(true), 103 S3ForcePathStyle: aws.Bool(true), 104 Region: aws.String("us-west-2"), 105 }) 106 107 o := DecryptionClientOptions{ 108 CryptoRegistry: initCryptoRegistryFrom(map[string]WrapEntry{ 109 KMSWrap: (kmsKeyHandler{ 110 kms: kms.New(sess), 111 }).decryptHandler, 112 }, map[string]CEKEntry{ 113 AESGCMNoPadding: newAESGCMContentCipher, 114 }, map[string]Padder{ 115 NoPadder.Name(): NoPadder, 116 }), 117 } 118 iv, err := hex.DecodeString("0d18e06c7c725ac9e362e1ce") 119 if err != nil { 120 t.Errorf("expected no error, but received %v", err) 121 } 122 ivB64 := base64.URLEncoding.EncodeToString(iv) 123 124 cipherKey, err := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 125 if err != nil { 126 t.Errorf("expected no error, but received %v", err) 127 } 128 cipherKeyB64 := base64.URLEncoding.EncodeToString(cipherKey) 129 130 env := Envelope{ 131 WrapAlg: KMSWrap, 132 CEKAlg: AESGCMNoPadding, 133 CipherKey: cipherKeyB64, 134 IV: ivB64, 135 MatDesc: `{"kms_cmk_id":""}`, 136 } 137 wrap, err := wrapFromEnvelope(o, env) 138 cek, err := cekFromEnvelope(o, aws.BackgroundContext(), env, wrap) 139 140 if err != nil { 141 t.Errorf("expected no error, but received %v", err) 142 } 143 if cek == nil { 144 t.Errorf("expected non-nil cek") 145 } 146} 147 148func TestCEKFactoryNoCEK(t *testing.T) { 149 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 150 keyB64 := base64.URLEncoding.EncodeToString(key) 151 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 152 fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`)) 153 })) 154 defer ts.Close() 155 156 sess := unit.Session.Copy(&aws.Config{ 157 MaxRetries: aws.Int(0), 158 Endpoint: aws.String(ts.URL), 159 DisableSSL: aws.Bool(true), 160 S3ForcePathStyle: aws.Bool(true), 161 Region: aws.String("us-west-2"), 162 }) 163 164 o := DecryptionClientOptions{ 165 CryptoRegistry: initCryptoRegistryFrom( 166 map[string]WrapEntry{ 167 KMSWrap: (kmsKeyHandler{ 168 kms: kms.New(sess), 169 }).decryptHandler, 170 }, 171 map[string]CEKEntry{ 172 AESGCMNoPadding: newAESGCMContentCipher, 173 }, 174 map[string]Padder{ 175 NoPadder.Name(): NoPadder, 176 }), 177 } 178 iv, err := hex.DecodeString("0d18e06c7c725ac9e362e1ce") 179 if err != nil { 180 t.Errorf("expected no error, but received %v", err) 181 } 182 ivB64 := base64.URLEncoding.EncodeToString(iv) 183 184 cipherKey, err := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 185 if err != nil { 186 t.Errorf("expected no error, but received %v", err) 187 } 188 cipherKeyB64 := base64.URLEncoding.EncodeToString(cipherKey) 189 190 env := Envelope{ 191 WrapAlg: KMSWrap, 192 CEKAlg: "none", 193 CipherKey: cipherKeyB64, 194 IV: ivB64, 195 MatDesc: `{"kms_cmk_id":""}`, 196 } 197 wrap, err := wrapFromEnvelope(o, env) 198 cek, err := cekFromEnvelope(o, aws.BackgroundContext(), env, wrap) 199 200 if err == nil { 201 t.Error("expected error, but received none") 202 } 203 if cek != nil { 204 t.Errorf("expected nil cek value, received %v", wrap) 205 } 206} 207 208func TestCEKFactoryCustomEntry(t *testing.T) { 209 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 210 keyB64 := base64.URLEncoding.EncodeToString(key) 211 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 212 fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`)) 213 })) 214 defer ts.Close() 215 216 sess := unit.Session.Copy(&aws.Config{ 217 MaxRetries: aws.Int(0), 218 Endpoint: aws.String(ts.URL), 219 DisableSSL: aws.Bool(true), 220 S3ForcePathStyle: aws.Bool(true), 221 Region: aws.String("us-west-2"), 222 }) 223 224 o := DecryptionClientOptions{ 225 CryptoRegistry: initCryptoRegistryFrom( 226 map[string]WrapEntry{ 227 KMSWrap: (kmsKeyHandler{ 228 kms: kms.New(sess), 229 }).decryptHandler, 230 }, map[string]CEKEntry{ 231 "custom": newAESGCMContentCipher, 232 }, map[string]Padder{}), 233 } 234 iv, err := hex.DecodeString("0d18e06c7c725ac9e362e1ce") 235 if err != nil { 236 t.Errorf("expected no error, but received %v", err) 237 } 238 ivB64 := base64.URLEncoding.EncodeToString(iv) 239 240 cipherKey, err := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 241 if err != nil { 242 t.Errorf("expected no error, but received %v", err) 243 } 244 cipherKeyB64 := base64.URLEncoding.EncodeToString(cipherKey) 245 246 env := Envelope{ 247 WrapAlg: KMSWrap, 248 CEKAlg: "custom", 249 CipherKey: cipherKeyB64, 250 IV: ivB64, 251 MatDesc: `{"kms_cmk_id":""}`, 252 } 253 wrap, err := wrapFromEnvelope(o, env) 254 cek, err := cekFromEnvelope(o, aws.BackgroundContext(), env, wrap) 255 256 if err != nil { 257 t.Errorf("expected no error, but received %v", err) 258 } 259 if cek == nil { 260 t.Errorf("expected non-nil cek") 261 } 262} 263