1package s3crypto_test
2
3import (
4	"bytes"
5	"fmt"
6	"io/ioutil"
7
8	"github.com/aws/aws-sdk-go/aws"
9	"github.com/aws/aws-sdk-go/aws/session"
10	"github.com/aws/aws-sdk-go/service/kms"
11	"github.com/aws/aws-sdk-go/service/s3"
12	"github.com/aws/aws-sdk-go/service/s3/s3crypto"
13)
14
15// ExampleNewEncryptionClientV2_migration00 provides a migration example for how users can migrate from the V1
16// encryption client to the V2 encryption client. This example demonstrates how an application using  the `kms` key wrap
17// algorithm with `AES/CBC/PKCS5Padding` can migrate their application to `kms+context` key wrapping with
18// `AES/GCM/NoPadding` content encryption.
19func ExampleNewEncryptionClientV2_migration00() {
20	sess := session.Must(session.NewSession())
21	kmsClient := kms.New(sess)
22	cmkID := "1234abcd-12ab-34cd-56ef-1234567890ab"
23
24	// Usage of NewKMSKeyGenerator (kms) key wrapping algorithm must be migrated to NewKMSContextKeyGenerator (kms+context) key wrapping algorithm
25	//
26	// cipherDataGenerator := s3crypto.NewKMSKeyGenerator(kmsClient, cmkID)
27	cipherDataGenerator := s3crypto.NewKMSContextKeyGenerator(kmsClient, cmkID, s3crypto.MaterialDescription{})
28
29	// Usage of AESCBCContentCipherBuilder (AES/CBC/PKCS5Padding) must be migrated to AESGCMContentCipherBuilder (AES/GCM/NoPadding)
30	//
31	// contentCipherBuilder := s3crypto.AESCBCContentCipherBuilder(cipherDataGenerator, s3crypto.AESCBCPadder)
32	contentCipherBuilder := s3crypto.AESGCMContentCipherBuilderV2(cipherDataGenerator)
33
34	// Construction of an encryption client should be done using NewEncryptionClientV2
35	//
36	// encryptionClient := s3crypto.NewEncryptionClient(sess, contentCipherBuilder)
37	encryptionClient, err := s3crypto.NewEncryptionClientV2(sess, contentCipherBuilder)
38	if err != nil {
39		fmt.Printf("failed to construct encryption client: %v", err)
40		return
41	}
42
43	_, err = encryptionClient.PutObject(&s3.PutObjectInput{
44		Bucket: aws.String("your_bucket"),
45		Key:    aws.String("your_key"),
46		Body:   bytes.NewReader([]byte("your content")),
47	})
48	if err != nil {
49		fmt.Printf("put object error: %v\n", err)
50		return
51	}
52	fmt.Println("put object completed")
53}
54
55// ExampleNewEncryptionClientV2_migration01 provides a more advanced migration example for how users can
56// migrate from the V1 encryption client to the V2 encryption client using more complex client construction.
57func ExampleNewEncryptionClientV2_migration01() {
58	sess := session.Must(session.NewSession())
59	kmsClient := kms.New(sess)
60	cmkID := "1234abcd-12ab-34cd-56ef-1234567890ab"
61
62	cipherDataGenerator := s3crypto.NewKMSContextKeyGenerator(kmsClient, cmkID, s3crypto.MaterialDescription{})
63
64	contentCipherBuilder := s3crypto.AESGCMContentCipherBuilderV2(cipherDataGenerator)
65
66	// Overriding of the encryption client options is possible by passing in functional arguments that override the
67	// provided EncryptionClientOptions.
68	//
69	// encryptionClient := s3crypto.NewEncryptionClient(cipherDataGenerator, contentCipherBuilder, func(o *s3crypto.EncryptionClient) {
70	//	 o.S3Client = s3.New(sess, &aws.Config{Region: aws.String("us-west-2")}),
71	// })
72	encryptionClient, err := s3crypto.NewEncryptionClientV2(sess, contentCipherBuilder, func(o *s3crypto.EncryptionClientOptions) {
73		o.S3Client = s3.New(sess, &aws.Config{Region: aws.String("us-west-2")})
74	})
75	if err != nil {
76		fmt.Printf("failed to construct encryption client: %v", err)
77		return
78	}
79
80	_, err = encryptionClient.PutObject(&s3.PutObjectInput{
81		Bucket: aws.String("your_bucket"),
82		Key:    aws.String("your_key"),
83		Body:   bytes.NewReader([]byte("your content")),
84	})
85	if err != nil {
86		fmt.Printf("put object error: %v\n", err)
87		return
88	}
89	fmt.Println("put object completed")
90}
91
92// ExampleNewDecryptionClientV2_migration00 provides a migration example for how users can migrate
93// from the V1 Decryption Clients to the V2 Decryption Clients.
94func ExampleNewDecryptionClientV2_migration00() {
95	sess := session.Must(session.NewSession())
96
97	// Construction of an decryption client must be done using NewDecryptionClientV2
98	// The V2 decryption client is able to decrypt object encrypted by the V1 client.
99	//
100	// decryptionClient := s3crypto.NewDecryptionClient(sess)
101
102	// The V2 decryption client requires you to explicitly register the key wrap algorithms and content encryption algorithms
103	// that you want to explicitly support decryption for.
104	registry := s3crypto.NewCryptoRegistry()
105
106	kmsClient := kms.New(sess)
107
108	// If you need support for unwrapping data keys wrapped using the `kms` wrap algorithm you can use RegisterKMSWrapWithAnyCMK.
109	// Alternatively you may use RegisterKMSWrapWithCMK if you wish to limit KMS decrypt calls to a specific CMK.
110	if err := s3crypto.RegisterKMSWrapWithAnyCMK(registry, kmsClient); err != nil {
111		fmt.Printf("error: %v", err)
112		return
113	}
114
115	// For unwrapping data keys wrapped using the new `kms+context` key wrap algorithm you can use RegisterKMSContextWrapWithAnyCMK.
116	// Alternatively you may use RegisterKMSWrapWithCMK if you wish to limit KMS decrypt calls to a specific CMK.
117	if err := s3crypto.RegisterKMSContextWrapWithAnyCMK(registry, kmsClient); err != nil {
118		fmt.Printf("error: %v", err)
119		return
120	}
121
122	// If you need to decrypt objects encrypted using the V1 AES/CBC/PCKS5Padding cipher you can do so with RegisterAESCBCContentCipher
123	if err := s3crypto.RegisterAESCBCContentCipher(registry, s3crypto.AESCBCPadder); err != nil {
124		fmt.Printf("error: %v", err)
125		return
126	}
127
128	// For decrypting objects encrypted in V1 or V2 using AES/GCM/NoPadding cipher you can do so with RegisterAESGCMContentCipher.
129	if err := s3crypto.RegisterAESGCMContentCipher(registry); err != nil {
130		fmt.Printf("error: %v", err)
131		return
132	}
133
134	// Instantiate a new decryption client, and provided the Wrap, cek, and Padder that have been registered
135	// with your desired algorithms.
136	decryptionClient, err := s3crypto.NewDecryptionClientV2(sess, registry)
137	if err != nil {
138		fmt.Printf("error: %v", err)
139		return
140	}
141
142	getObject, err := decryptionClient.GetObject(&s3.GetObjectInput{
143		Bucket: aws.String("your_bucket"),
144		Key:    aws.String("your_key"),
145	})
146	if err != nil {
147		fmt.Printf("get object error: %v\n", err)
148		return
149	}
150
151	_, err = ioutil.ReadAll(getObject.Body)
152	if err != nil {
153		fmt.Printf("error reading object: %v\n", err)
154	}
155	fmt.Println("get object completed")
156}
157
158// ExampleNewDecryptionClientV2_migration01 provides a more advanced migration example for how users can
159// migrate from the V1 decryption client to the V2 decryption client using more complex client construction.
160func ExampleNewDecryptionClientV2_migration01() {
161	sess := session.Must(session.NewSession())
162
163	// Construction of an decryption client must be done using NewDecryptionClientV2
164	// The V2 decryption client is able to decrypt object encrypted by the V1 client.
165	//
166	// decryptionClient := s3crypto.NewDecryptionClient(sess, func(o *s3crypto.DecryptionClient) {
167	//	 o.S3Client = s3.New(sess, &aws.Config{Region: aws.String("us-west-2")})
168	//})
169	registry := s3crypto.NewCryptoRegistry()
170
171	kmsClient := kms.New(sess)
172	if err := s3crypto.RegisterKMSWrapWithAnyCMK(registry, kmsClient); err != nil {
173		fmt.Printf("error: %v", err)
174		return
175	}
176
177	// If you need to decrypt objects encrypted using AES/GCM/NoPadding cipher you can do so with RegisterAESGCMContentCipher
178	if err := s3crypto.RegisterAESGCMContentCipher(registry); err != nil {
179		fmt.Printf("error: %v", err)
180		return
181	}
182
183	decryptionClient, err := s3crypto.NewDecryptionClientV2(sess, registry, func(o *s3crypto.DecryptionClientOptions) {
184		o.S3Client = s3.New(sess, &aws.Config{Region: aws.String("us-west-2")})
185	})
186	if err != nil {
187		fmt.Printf("error: %v", err)
188		return
189	}
190
191	getObject, err := decryptionClient.GetObject(&s3.GetObjectInput{
192		Bucket: aws.String("your_bucket"),
193		Key:    aws.String("your_key"),
194	})
195	if err != nil {
196		fmt.Printf("get object error: %v\n", err)
197		return
198	}
199
200	_, err = ioutil.ReadAll(getObject.Body)
201	if err != nil {
202		fmt.Printf("error reading object: %v\n", err)
203	}
204	fmt.Println("get object completed")
205}
206