/// <summary> /// Updates the request where the input stream contains the encrypted object contents. /// </summary> /// <param name="request"></param> private void GenerateEncryptedUploadPartRequest(UploadPartRequest request) { string uploadID = request.UploadId; UploadPartEncryptionContext contextForEncryption = this.EncryptionClient.CurrentMultiPartUploadKeys[uploadID]; byte[] envelopeKey = contextForEncryption.EnvelopeKey; byte[] IV = contextForEncryption.NextIV; EncryptionInstructions instructions = new EncryptionInstructions(EncryptionClient.EncryptionMaterials.MaterialsDescription, envelopeKey, IV); if (request.IsLastPart == false) { if (contextForEncryption.IsFinalPart == true) { throw new AmazonClientException("Last part has already been processed, cannot upload this as the last part"); } if (request.PartNumber < contextForEncryption.PartNumber) { throw new AmazonClientException("Upload Parts must in correct sequence"); } request.InputStream = EncryptionUtils.EncryptUploadPartRequestUsingInstructions(request.InputStream, instructions); contextForEncryption.PartNumber = request.PartNumber; } else { request.InputStream = EncryptionUtils.EncryptRequestUsingInstruction(request.InputStream, instructions); contextForEncryption.IsFinalPart = true; } ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)request).RequestState.Add(AmazonS3EncryptionClient.S3CryptoStream, request.InputStream); }
/// <inheritdoc/> protected override void UpdateMultipartUploadEncryptionContext(UploadPartRequest uploadPartRequest) { string uploadID = uploadPartRequest.UploadId; UploadPartEncryptionContext encryptedUploadedContext = null; if (!EncryptionClient.CurrentMultiPartUploadKeys.TryGetValue(uploadID, out encryptedUploadedContext)) { throw new AmazonS3Exception("Encryption context for multipart upload not found"); } if (!uploadPartRequest.IsLastPart) { object stream = null; if (!((IAmazonWebServiceRequest)uploadPartRequest).RequestState.TryGetValue(AmazonS3EncryptionClient.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; if (encryptionStream != null) { encryptedUploadedContext.NextIV = encryptionStream.InitializationVector; } var aesGcmEncryptStream = stream as AesGcmEncryptStream; if (aesGcmEncryptStream != null) { encryptedUploadedContext.CryptoStream = aesGcmEncryptStream; } } }
/// <inheritdoc/> protected override async System.Threading.Tasks.Task CompleteMultipartUploadAsync(CompleteMultipartUploadRequest completeMultiPartUploadRequest) { UploadPartEncryptionContext context = EncryptionClient.CurrentMultiPartUploadKeys[completeMultiPartUploadRequest.UploadId]; if (context.StorageMode == CryptoStorageMode.InstructionFile) { var instructions = EncryptionUtils.BuildEncryptionInstructionsForInstructionFileV2(context, EncryptionMaterials); PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequestV2(completeMultiPartUploadRequest, instructions); await EncryptionClient.S3ClientForInstructionFile.PutObjectAsync(instructionFileRequest).ConfigureAwait(false); } //Clear Context data since encryption is completed EncryptionClient.CurrentMultiPartUploadKeys.TryRemove(completeMultiPartUploadRequest.UploadId, out _); }
/// <inheritdoc/> protected override void CompleteMultipartUpload(CompleteMultipartUploadRequest completeMultiPartUploadRequest) { UploadPartEncryptionContext context = EncryptionClient.CurrentMultiPartUploadKeys[completeMultiPartUploadRequest.UploadId]; if (context.StorageMode == CryptoStorageMode.InstructionFile) { var instructions = EncryptionUtils.BuildEncryptionInstructionsForInstructionFileV2(context, EncryptionMaterials); var instructionFileRequest = EncryptionUtils.CreateInstructionFileRequestV2(completeMultiPartUploadRequest, instructions); EncryptionClient.S3ClientForInstructionFile.PutObject(instructionFileRequest); } //Clear Context data since encryption is completed EncryptionClient.CurrentMultiPartUploadKeys.TryRemove(completeMultiPartUploadRequest.UploadId, out _); }
private static void UpdateRequestInputStream(UploadPartRequest request, UploadPartEncryptionContext contextForEncryption, EncryptionInstructions instructions) { if (contextForEncryption.CryptoStream == null) { request.InputStream = EncryptionUtils.EncryptUploadPartRequestUsingInstructionsV2(request.InputStream, instructions); } else { request.InputStream = contextForEncryption.CryptoStream; } // Clear the buffer filled for retry request var aesGcmEncryptCachingStream = request.InputStream as AesGcmEncryptCachingStream; if (aesGcmEncryptCachingStream != null) { aesGcmEncryptCachingStream.ClearReadBufferToPosition(); } }
/// <inheritdoc/> protected override void GenerateInitiateMultiPartUploadRequest(EncryptionInstructions instructions, InitiateMultipartUploadRequest initiateMultiPartUploadRequest, bool useKMSKeyWrapping) { ValidateConfigAndMaterials(); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { EncryptionUtils.UpdateMetadataWithEncryptionInstructions(initiateMultiPartUploadRequest, instructions, useKMSKeyWrapping); } var context = new UploadPartEncryptionContext { StorageMode = EncryptionClient.S3CryptoConfig.StorageMode, EncryptedEnvelopeKey = instructions.EncryptedEnvelopeKey, EnvelopeKey = instructions.EnvelopeKey, NextIV = instructions.InitializationVector, FirstIV = instructions.InitializationVector, PartNumber = 0, WrapAlgorithm = instructions.WrapAlgorithm, CekAlgorithm = instructions.CekAlgorithm, }; EncryptionClient.AllMultiPartUploadRequestContexts[initiateMultiPartUploadRequest] = context; }
/// <summary> /// Decrypt the object being downloaded. /// </summary> /// <param name="executionContext"></param> protected void PostInvoke(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var response = executionContext.ResponseContext.Response; 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 this.EncryptionClient.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 (!this.EncryptionClient.CurrentMultiPartUploadKeys.TryGetValue(uploadID, out encryptedUploadedContext)) { throw new AmazonS3Exception("encryption context for multi part upload not found"); } if (uploadPartRequest.IsLastPart == false) { object stream = null; if (!((Amazon.Runtime.Internal.IAmazonWebServiceRequest)uploadPartRequest).RequestState.TryGetValue(AmazonS3EncryptionClient.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 = this.EncryptionClient.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 (this.EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.InstructionFile) { UploadPartEncryptionContext context = this.EncryptionClient.CurrentMultiPartUploadKeys[completeMultiPartUploadRequest.UploadId]; byte[] envelopeKey = context.EnvelopeKey; byte[] iv = context.FirstIV; byte[] encryptedEnvelopeKey = EncryptionUtils.EncryptEnvelopeKey(envelopeKey, this.EncryptionClient.EncryptionMaterials); EncryptionInstructions instructions = new EncryptionInstructions(EncryptionMaterials.EmptyMaterialsDescription, envelopeKey, encryptedEnvelopeKey, iv); PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequest(completeMultiPartUploadRequest, instructions); this.EncryptionClient.S3ClientForInstructionFile.PutObject(instructionFileRequest); } //Clear Context data since encryption is completed this.EncryptionClient.CurrentMultiPartUploadKeys.Clear(); } }
protected override void PostInvoke(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var response = executionContext.ResponseContext.Response; 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 this.EncryptionClient.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 (!this.EncryptionClient.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(AmazonS3EncryptionClient.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 = this.EncryptionClient.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 (this.EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.InstructionFile) { UploadPartEncryptionContext context = this.EncryptionClient.CurrentMultiPartUploadKeys[completeMultiPartUploadRequest.UploadId]; byte[] envelopeKey = context.EnvelopeKey; byte[] iv = context.FirstIV; byte[] encryptedEnvelopeKey = EncryptionUtils.EncryptEnvelopeKey(envelopeKey, this.EncryptionClient.EncryptionMaterials); EncryptionInstructions instructions = new EncryptionInstructions(EncryptionMaterials.EmptyMaterialsDescription, envelopeKey, encryptedEnvelopeKey, iv); PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequest(completeMultiPartUploadRequest, instructions); this.EncryptionClient.S3ClientForInstructionFile.PutObject(instructionFileRequest); } //Clear Context data since encryption is completed this.EncryptionClient.CurrentMultiPartUploadKeys.Clear(); } }