EncryptedUploadContext encryptedUploadContext = currentMultipartUploadSecretKeys.get(uploadId);
if (encryptedUploadContext == null) throw new AmazonClientException("No client-side information available on upload ID " + uploadId);
SecretKey envelopeSymmetricKey = encryptedUploadContext.getEnvelopeEncryptionKey();
byte[] iv = encryptedUploadContext.getNextInitializationVector();
CipherFactory cipherFactory = new CipherFactory(envelopeSymmetricKey, Cipher.ENCRYPT_MODE, iv, this.cryptoConfig.getCryptoProvider());
// Create encrypted input stream
ByteRangeCapturingInputStream encryptedInputStream = EncryptionUtils.getEncryptedInputStream(uploadPartRequest, cipherFactory);
uploadPartRequest.setInputStream(encryptedInputStream);
// The last part of the multipart upload will contain extra padding from the encryption process, which
// changes the
if (uploadPartRequest.isLastPart()) {
// We only change the size of the last part
long cryptoContentLength = EncryptionUtils.calculateCryptoContentLength(cipherFactory.createCipher(), uploadPartRequest);
if (cryptoContentLength > 0) uploadPartRequest.setPartSize(cryptoContentLength);
if (encryptedUploadContext.hasFinalPartBeenSeen()) {
throw new AmazonClientException("This part was specified as the last part in a multipart upload, but a previous part was already marked as the last part. " +
"Only the last part of the upload should be marked as the last part, otherwise it will cause the encrypted data to be corrupted.");