[JAVA] Envelope encryption with AWS Key Management Service

Introduction

AWS Key Management Service (KMS) is a managed service that manages the encryption keys used to encrypt your data. KMS can handle data securely by using an encryption method called envelope encryption.

I have summarized the Java implementation examples of envelope encryption because there are few Japanese documents.

What is envelope encryption?

Roughly speaking

It is a mechanism to make it secure by using properly.

e076de0e-e74e-0f63-a339-f6d565b89743.png

A common encryption method protects plaintext data by encrypting it with some key. At this time, if this key is stolen together with the data, the code will be decrypted and the raw data will be visible. Therefore, the idea of envelope encryption is to protect the data more strongly by further encrypting the key that encrypted the data with another key.

Data encryption using KMS can be achieved by the following flow.

--Generate a master key on the KMS console screen --Generate data key from master key --Encrypt plaintext data using a data key --Encrypt data key --Keep your encrypted data key and encrypted data in a safe place

Implementation example

The following is an implementation example in Java for implementing envelope encryption.

We will assume that the master key has been generated in advance from the KMS console screen. For the master key generation procedure, see AWS Manual or [Developers.IO](http: / Please refer to articles such as /dev.classmethod.jp/cloud/aws/cm-advent-calendar-2015-aws-relearning-key-management-service/).

Advance preparation

AWS provides an SDK for using KMS. Here is an example of using the library via Gradle. Add the following dependency to build.gradle.

dependencies {
    compile "com.amazonaws:aws-java-sdk-kms:1.11.202"
}

encryption

First, create an instance of ʻAWSKMSClient` using the AWS access key and secret key.

BasicAWSCredentials credentials = new BasicAWSCredentials("accessKey...", "SecretKey...");
AWSKMSClient client = (AWSKMSClient) AWSKMSClientBuilder.standard()
    .withRegion("ap-northeast-1")
    .withCredentials(new AWSStaticCredentialsProvider(credentials))
    .build();

Generate a data key using the generated client. You can get the data key by creating an instance of GenerateDataKeyRequest and doing generateDataKey by specifying the KeyId as the ARN of the master key generated from the KMS console.

GenerateDataKeyRequest generateDataKeyRequest = new GenerateDataKeyRequest()
    .withKeyId("arn:aws:kms:...")
    .withKeySpec(DataKeySpec.AES_128);
GenerateDataKeyResult dataKeyResult = client.generateDataKey(generateDataKeyRequest);

Encrypt plaintext data using the generated data key. Here, AES is used for encryption, but you can use any encryption method.

try {
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE,
                new SecretKeySpec(dataKeyResult.getPlaintext().array(), "AES"));
    String decriptedText = Base64.getEncoder()
        .encodeToString(cipher.doFinal("plainText...".getBytes()));
} catch (Exception e) {
    // do something.
}

The generated decriptedText and the encrypted data key (you can get the encrypted one withdataKeyResult.getCiphertextBlob ()) are encoded in Base64, copied to a yaml file, etc. and saved. Let's go.

Decryption

Next is the procedure for decrypting encrypted data. Decryption is done by generating a decryptRequest from the encrypted data key.

DecryptRequest decryptRequest = new DecryptRequest()
    .withCiphertextBlob(ByteBuffer.wrap(Base64.getDecoder().decode("decryptedDatakey...".getBytes())));
ByteBuffer plainTextKey = client.decrypt(decryptRequest).getPlaintext();

With the above steps, you have successfully converted the encrypted data key back to the plaintext data key. Then, use the obtained data key to decrypt the encrypted data.

byte[] decodeBase64src = Base64.getDecoder().decode("decryptedText...");
try {
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, plainTextKey);
    String plainText = new String(cipher.doFinal(decodeBase64src));
} catch (Exception e) {
    // do something.
}

Discard the extracted plaintext data key (plainTextKey) immediately.

plainTextKey.clear();

Reference material

-What is AWS Key Management Service -AWS Key Management Service Concept -Reintroduction to AWS-Amazon KMS

Recommended Posts

Envelope encryption with AWS Key Management Service
KMS) Envelope encryption with openssl and java decryption
I tried using Alibaba Cloud's KMS (Key Management Service) service