protected override void ProcessResponseHandlers(AmazonWebServiceResponse response, IRequest request, IWebResponseData webResponseData)
{
base.ProcessResponseHandlers(response, request, webResponseData);
var initiateMultiPartUploadRequest = request.OriginalRequest as InitiateMultipartUploadRequest;
var initiateMultiPartResponse = response as InitiateMultipartUploadResponse;
if (initiateMultiPartResponse != null)
{
byte[] envelopeKey = initiateMultiPartUploadRequest.EnvelopeKey;
byte[] iv = initiateMultiPartUploadRequest.IV;
UploadPartEncryptionContext contextForEncryption = new UploadPartEncryptionContext();
contextForEncryption.EnvelopeKey = envelopeKey;
contextForEncryption.NextIV = iv;
contextForEncryption.FirstIV = iv;
contextForEncryption.PartNumber = 0;
//Add context for encryption of next part
currentMultiPartUploadKeys.Add(initiateMultiPartResponse.UploadId, contextForEncryption);
}
var uploadPartRequest = request.OriginalRequest as UploadPartRequest;
var uploadPartResponse = response as UploadPartResponse;
if (uploadPartResponse != null)
{
string uploadID = uploadPartRequest.UploadId;
UploadPartEncryptionContext encryptedUploadedContext = null;
if (!currentMultiPartUploadKeys.TryGetValue(uploadID, out encryptedUploadedContext))
throw new AmazonS3Exception("encryption context for multi part upload not found");
if (uploadPartRequest.IsLastPart == false)
{
object stream = null;
if (!uploadPartRequest.RequestState.TryGetValue(S3CryptoStream, out stream))
throw new AmazonS3Exception("cannot retrieve S3 crypto stream from request state, hence cannot get Initialization vector for next uploadPart ");
var encryptionStream = stream as AESEncryptionUploadPartStream;
encryptedUploadedContext.NextIV = encryptionStream.InitializationVector;
}
}
var getObjectResponse = response as GetObjectResponse;
if (getObjectResponse != null)
{
if (EncryptionUtils.IsEncryptionInfoInMetadata(getObjectResponse) == true)
{
DecryptObjectUsingMetadata(getObjectResponse);
}
else
{
GetObjectResponse instructionFileResponse = null;
try
{
GetObjectRequest instructionFileRequest = EncryptionUtils.GetInstructionFileRequest(getObjectResponse);
instructionFileResponse = S3ClientForInstructionFile.GetObject(instructionFileRequest);
}
catch (AmazonServiceException ace)
{
throw new AmazonServiceException(string.Format(CultureInfo.InvariantCulture, "Unable to decrypt data for object {0} in bucket {1}",
getObjectResponse.Key, getObjectResponse.BucketName), ace);
}
if (EncryptionUtils.IsEncryptionInfoInInstructionFile(instructionFileResponse) == true)
{
DecryptObjectUsingInstructionFile(getObjectResponse, instructionFileResponse);
}
}
}
var completeMultiPartUploadRequest = request.OriginalRequest as CompleteMultipartUploadRequest;
var completeMultipartUploadResponse = response as CompleteMultipartUploadResponse;
if (completeMultipartUploadResponse != null)
{
if (amazonS3CryptoConfig.StorageMode == CryptoStorageMode.InstructionFile)
{
UploadPartEncryptionContext context = currentMultiPartUploadKeys[completeMultiPartUploadRequest.UploadId];
byte[] envelopeKey = context.EnvelopeKey;
byte[] iv = context.FirstIV;
byte[] encryptedEnvelopeKey = EncryptionUtils.EncryptEnvelopeKey(envelopeKey, this.encryptionMaterials);
EncryptionInstructions instructions = new EncryptionInstructions(EncryptionMaterials.EmptyMaterialsDescription, envelopeKey, encryptedEnvelopeKey, iv);
PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequest(completeMultiPartUploadRequest, instructions);
S3ClientForInstructionFile.PutObject(instructionFileRequest);
}
//Clear Context data since encryption is completed
currentMultiPartUploadKeys.Clear();
}
}