final boolean isLastPart = req.isLastPart();
final String uploadId = req.getUploadId();
final long partSize = req.getPartSize();
final boolean partSizeMultipleOfCipherBlockSize = 0 == (partSize % blockSize);
if (!isLastPart && !partSizeMultipleOfCipherBlockSize) {
throw new AmazonClientException(
"Invalid part size: part sizes for encrypted multipart uploads must be multiples "
+ "of the cipher block size ("
+ blockSize
+ ") with the exception of the last part.");
}
// Generate the envelope symmetric key and initialize a cipher to encrypt the object's data
MultipartUploadCryptoContext uploadContext = multipartUploadContexts.get(uploadId);
if (uploadContext == null) {
throw new AmazonClientException(
"No client-side information available on upload ID " + uploadId);
}
CipherLite cipherLite = uploadContext.getCipherLite();
req.setInputStream(newMultipartS3CipherInputStream(req, cipherLite));
// Treat all encryption requests as input stream upload requests, not as
// file upload requests.
req.setFile(null);
req.setFileOffset(0);
// The last part of the multipart upload will contain an extra 16-byte mac
if (req.isLastPart()) {
// We only change the size of the last part
req.setPartSize(partSize + (contentCryptoScheme.getTagLengthInBits()/8));
if (uploadContext.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.");
}
uploadContext.setHasFinalPartBeenSeen(true);
}