AWS Developer Tools Blog

Using the AWS SDK for Go Encryption Client

Overview

AWS SDK for Go released the encryption client last year, and some of our customers have asked us how to use it. We’re very excited to show you some examples in this blog post. Before we get into the examples, let’s look at what client-side encryption is and why you might want to use it.

Client-side encryption is the act of encrypting or decrypting on the client’s side and not relying on a service to do the encryption for you. This has many added benefits, including enabling you to choose what to use to encrypt your data. It also enables extra security so that only those who have the master key can decrypt the data.

The crypto client has three major components: key wrap handler, cipher builder, and client. We use the key wrap handler to generate and encrypt the iv and key. Then we use those keys with the cipher builder to build a new cipher. Lastly, we use all these parts to create a client. To learn more about this process, see envelope encryption.

Prerequisite

To run these examples, we need

  • An AWS KMS encryption key
  • An Amazon S3 bucket bar

Encryption and Decryption

In our implementation, we wanted to provide interoperability across all SDKs and to give customers an easy way to extend the s3crypto package. Let’s first get into an example of putting a simple “hello world” object into S3.


	arn := "arn to our key"
	sess := session.New(&aws.Config{
        Region: aws.String("us-east-1"),
    })
	// This is our key wrap handler, used to generate cipher keys and IVs for
    // our cipher builder. Using an IV allows more “spontaneous” encryption.
    // The IV makes it more difficult for hackers to use dictionary attacks.
    // The key wrap handler behaves as the master key. Without it, you can’t
    // encrypt or decrypt the data.
	keywrap := s3crypto.NewKMSKeyGenerator(kms.New(sess), arn)
	// This is our content cipher builder, used to instantiate new ciphers
    // that enable us to encrypt or decrypt the payload.
	builder := s3crypto.AESGCMContentCipherBuilder(keywrap)
	// Let's create our crypto client!
	client := s3crypto.NewEncryptionClient(sess, builder)
	
	key := "foo"
	bucket := "bar"
	input := &s3.PutObjectInput{
    	Bucket: &bucket,
    	Key:    &key,
    	Body:   bytes.NewReader("Hello world!"),
	}

    _, err := client.PutObject(input)
	// What to expect as errors? You can expect any sort of S3 errors, http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html.
	// The s3crypto client can also return some errors:
    //  * MissingCMKIDError - when using AWS KMS, the user must specify their key's ARN
	if err != nil {
		return err
	}

Now that wasn’t too hard! It looks almost identical to the S3 PutObject! Let’s move on to an example of decryption.


	sess := session.New(&aws.Config{
        Region: aws.String("us-east-1"),
    })
	client := s3crypto.NewDecryptionClient(sess)

	key := "foo"
	bucket := "bar"
	input := &s3.GetObjectInput{
    	Bucket: &bucket,
    	Key:    &key,
	}

    result, err := client.GetObject(input)
  // Aside from the S3 errors, here is a list of decryption client errors:
  //   * InvalidWrapAlgorithmError - returned on an unsupported Wrap algorithm
  //   * InvalidCEKAlgorithmError - returned on an unsupported CEK algorithm
  //   * V1NotSupportedError - the SDK doesn’t support v1 because security is an issue for AES ECB
  // These errors don’t necessarily mean there’s something wrong. They just tell us we couldn't decrypt some data.
  // Users can choose to log this and then continue decrypting the data that they can, or simply return the error.
	if err != nil {
		return err
	}
	
	// Let's read the whole body from the response
	b, err := ioutil.ReadAll(result.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(b))

As the code shows, there’s no difference between using the Amazon S3 client’s GetObject versus the s3crypto.DecryptionClient.GetObject.

Lost or Deleted Master Key

If you lose or delete your master key, there’s no way to decrypt your data. The beauty of client-side encryption is that the master key is never stored with your data. This allows you to specify who can view your data.

Supported Algorithms

The AWS SDK for Go currently supports AWS KMS for key wrapping and AES GCM as a content cipher. However, some users might not want to use AES GCM or KMS for their ciphers. The SDK allows any user to specify any cipher as long as it satisfies our interfaces. With that said, the goal of this crypto client is to allow interoperability between the crypto clients of other SDKs and enable easy extensibility. Please let us know in the comments how you’re using or extending the crypto client.

The documentation for Amazon S3 Encryption Client can be found here.

Check out other SDKs that support the Amazon S3 Encryption Client
AWS SDK for C++
AWS SDK for Java
AWS SDK for Ruby