Asynchronous programming in the Amazon S3 Encryption Client for Java
Version 3.x of the Amazon S3 Encryption Client provides a nonblocking asynchronous client that implements high concurrency across a few threads. The asynchronous client enables you to perform requests sequentially without waiting to view results between each request.
The default Amazon S3 Encryption Client uses synchronous methods that block your thread’s execution until the client receives a response from Amazon S3. The asynchronous client returns immediately, giving control back to the calling thread without waiting for a response. Because an asynchronous method returns before a response is available, you need a way to get the response when it’s ready. The methods in version 3.x of the Amazon S3 Encryption Client return CompletableFuture objects that allow you to access the response when it’s ready.
Instantiating the asynchronous client
To use the asynchronous client, you must specify the
S3AsyncEncryptionClient
builder and the builder parameter that
identifies your wrapping key when you instantiate
your client. The Amazon S3 Encryption Client supports the following wrapping keys: symmetric AWS KMS keys, raw AES-GCM keys, and raw RSA
keys.
Note
If you use Raw RSA or Raw AES-GCM wrapping keys, you are responsible for generating, storing, and protecting the key material, preferably in a hardware security module (HSM) or key management system.
The following examples instantiate the asynchronous Amazon S3 Encryption Client with the default decryption mode. This means that all objects will be decrypted using the fully supported buffered decryption mode. For more information, see Decryption modes (Version 3.x and later).
You can customize your asynchronous client by specifying different builder parameters to enable the features you need. By default, version 3.x of the Amazon S3 Encryption Client does not support legacy decryption, ranged 'GET' requests, or multipart uploads (via the high-level API).
For example, if you need to decrypt data keys that were encrypted with a legacy wrapping algorithm, specify the enableLegacyWrappingAlgorithms parameter when you instantiate your client. The following example specifies a raw AES key as the wrapping key.
// v3 class v3EnableLegacyModesAsyncClientExample { public static void main(String[] args) { S3AsyncClient v3Client = S3AsyncEncryptionClient.builder() .aesKey(AES_KEY) .enableLegacyWrappingAlgorithms(
true
) .build(); } }
Encrypt and decrypt with the asynchronous client
The following walkthrough demonstrates how encrypt and decrypt asynchronously with version 3.x of the Amazon S3 Encryption Client.
-
Instantiate your asynchronous client with the
S3AsyncEncryptionClient
builder.The following example specifies a raw AES key as the wrapping key.
// v3 class v3EnableAsyncClientExample { public static void main(String[] args) { S3AsyncClient v3Client = S3AsyncEncryptionClient.builder() .aesKey(AES_KEY) .build(); } }
-
Call
PutObject
to encrypt a plaintext object and upload it to Amazon S3.The asynchronous client stores the response to confirm that the
PutObject
request completed when you callGetObject
in the future.// v3 class v3PutObjectAsyncClientExample { public static void main(String[] args) { CompletableFuture<PutObjectResponse> futurePut = v3AsyncClient.putObject(builder -> builder .bucket(
bucket
) .key(objectKey
) .build(), AsyncRequestBody.fromString(objectContent
)); // Block on completion of the futurePut futurePut.join(); } } -
Call
GetObject
to download and decrypt the encrypted object.// v3 class v3GetObjectAsyncClientExample { public static void main(String[] args) { CompletableFuture<ResponseBytes<GetObjectResponse>> futureGet = v3AsyncClient.getObject(builder -> builder .bucket(
bucket
) .key(objectKey
) .build(), AsyncResponseTransformer.toBytes()); // Wait for the future to complete ResponseBytes<GetObjectResponse> getResponse = futureGet.join(); } } -
Optional: verify that the decrypted object matches the original plaintext object that you uploaded.
assert output.equals(
objectContent
); -
The Amazon S3 Encryption Client implements the
AutoClosable
interface, which automatically callsclose()
when you exit atry-with-resources
block for which the object has been declared in the resource specification header. As a best practice, you should either usetry-with-resources
or explicitly call theclose()
method.s3Client.close();
Note
The default decryption mode cannot decrypt objects larger than 64 MB. This decryption mode automatically buffers stream contents into memory to prevent the release of unauthenticated objects. If you attempt to decrypt an object larger than 64 MB, you will receive an exception directing you to enable the delayed authentication decryption mode. For more information, see Decryption modes.