/// <inheritdoc/> protected override void GenerateEncryptedUploadPartRequest(UploadPartRequest request) { string uploadID = request.UploadId; var contextForEncryption = this.EncryptionClient.CurrentMultiPartUploadKeys[uploadID]; var envelopeKey = contextForEncryption.EnvelopeKey; var IV = contextForEncryption.NextIV; var instructions = new EncryptionInstructions(EncryptionMaterials.MaterialsDescription, envelopeKey, IV); if (request.IsLastPart == false) { if (contextForEncryption.IsFinalPart) { 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 be in correct sequence. Request part number {request.PartNumber} must be >= to {contextForEncryption.PartNumber}"); } UpdateRequestInputStream(request, contextForEncryption, instructions); contextForEncryption.PartNumber = request.PartNumber; } else { UpdateRequestInputStream(request, contextForEncryption, instructions); contextForEncryption.IsFinalPart = true; } ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)request).RequestState.Add(AmazonS3EncryptionClient.S3CryptoStream, request.InputStream); }
/// <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); }
/// <summary> /// Updates object where the object input stream contains the decrypted contents. /// </summary> /// <param name="instructionFileResponse"> /// The getObject response of InstructionFile. /// </param> /// <param name="response"> /// The getObject response whose contents are to be decrypted. /// </param> private void DecryptObjectUsingInstructionFile(GetObjectResponse response, GetObjectResponse instructionFileResponse) { // Create an instruction object from the instruction file response EncryptionInstructions instructions = EncryptionUtils.BuildInstructionsUsingInstructionFile(instructionFileResponse, this.EncryptionClient.EncryptionMaterials); // Decrypt the object with the instructions EncryptionUtils.DecryptObjectUsingInstructions(response, instructions); }
/// <summary> /// Updates object where the object input stream contains the decrypted contents. /// </summary> /// <param name="objectResponse"> /// The getObject response whose contents are to be decrypted. /// </param> private void DecryptObjectUsingMetadata(GetObjectResponse objectResponse) { // Create an instruction object from the object metadata EncryptionInstructions instructions = EncryptionUtils.BuildInstructionsFromObjectMetadata(objectResponse, this.EncryptionClient.EncryptionMaterials); // Decrypt the object with the instruction EncryptionUtils.DecryptObjectUsingInstructions(objectResponse, instructions); }
/// <summary> /// Encrypts the S3 object being uploaded. /// </summary> /// <param name="executionContext"></param> protected async System.Threading.Tasks.Task PreInvokeAsync(IExecutionContext executionContext) { EncryptionInstructions instructions = null; if (NeedToGenerateKMSInstructions(executionContext)) { instructions = await EncryptionUtils.GenerateInstructionsForKMSMaterialsAsync( EncryptionClient.KMSClient, EncryptionClient.EncryptionMaterials).ConfigureAwait(false); } PreInvokeSynchronous(executionContext, instructions); }
/// <summary> /// Encrypts the S3 object being uploaded. /// </summary> /// <param name="executionContext"></param> protected void PreInvoke(IExecutionContext executionContext) { EncryptionInstructions instructions = null; if (NeedToGenerateKMSInstructions(executionContext)) { instructions = EncryptionUtils.GenerateInstructionsForKMSMaterials( EncryptionClient.KMSClient, EncryptionClient.EncryptionMaterials); } PreInvokeSynchronous(executionContext, instructions); }
/// <summary> /// Updates the request where the metadata contains encryption information /// and the input stream contains the encrypted object contents. /// </summary> /// <param name="putObjectRequest"> /// The request whose contents are to be encrypted. /// </param> private void GenerateEncryptedObjectRequestUsingMetadata(PutObjectRequest putObjectRequest) { // Create instruction EncryptionInstructions instructions = EncryptionUtils.GenerateInstructions(this.EncryptionClient.EncryptionMaterials); EncryptionUtils.AddUnencryptedContentLengthToMetadata(putObjectRequest); // Encrypt the object data with the instruction putObjectRequest.InputStream = EncryptionUtils.EncryptRequestUsingInstruction(putObjectRequest.InputStream, instructions); // Update the metadata EncryptionUtils.UpdateMetadataWithEncryptionInstructions(putObjectRequest, instructions); }
private void EncryptObject(EncryptionInstructions instructions, PutObjectRequest putObjectRequest) { ValidateConfigAndMaterials(); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { GenerateEncryptedObjectRequestUsingMetadata(putObjectRequest, instructions); } else { var instructionFileRequest = GenerateEncryptedObjectRequestUsingInstructionFile(putObjectRequest, instructions); EncryptionClient.S3ClientForInstructionFile.PutObject(instructionFileRequest); } }
private async System.Threading.Tasks.Task EncryptObjectAsync(EncryptionInstructions instructions, PutObjectRequest putObjectRequest) { ValidateConfigAndMaterials(); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { GenerateEncryptedObjectRequestUsingMetadata(putObjectRequest, instructions); } else { var instructionFileRequest = GenerateEncryptedObjectRequestUsingInstructionFile(putObjectRequest, instructions); await EncryptionClient.S3ClientForInstructionFile.PutObjectAsync(instructionFileRequest) .ConfigureAwait(false); } }
/// <summary> /// Updates the request where the instruction file contains encryption information /// and the input stream contains the encrypted object contents. /// </summary> /// <param name="putObjectRequest"></param> private void GenerateEncryptedObjectRequestUsingInstructionFile(PutObjectRequest putObjectRequest) { // Create instruction EncryptionInstructions instructions = EncryptionUtils.GenerateInstructions(this.EncryptionClient.EncryptionMaterials); EncryptionUtils.AddUnencryptedContentLengthToMetadata(putObjectRequest); // Encrypt the object data with the instruction putObjectRequest.InputStream = EncryptionUtils.EncryptRequestUsingInstruction(putObjectRequest.InputStream, instructions); // Create request for uploading instruction file PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequest(putObjectRequest, instructions); this.EncryptionClient.S3ClientForInstructionFile.PutObject(instructionFileRequest); }
/// <inheritdoc/> protected override EncryptionInstructions GenerateInstructions(IExecutionContext executionContext) { EncryptionInstructions instructions = null; if (NeedToGenerateKMSInstructions(executionContext)) { instructions = EncryptionUtils.GenerateInstructionsForKMSMaterials(EncryptionClient.KMSClient, EncryptionMaterials); } if (instructions == null && NeedToGenerateInstructions(executionContext)) { instructions = EncryptionUtils.GenerateInstructionsForNonKMSMaterials(EncryptionMaterials); } return(instructions); }
/// <summary> /// Updates object where the object input stream contains the decrypted contents. /// </summary> /// <param name="getObjectResponse">The getObject response whose contents are to be decrypted.</param> /// <param name="decryptedEnvelopeKeyKMS">The decrypted envelope key to be use if KMS key wrapping is being used. Or null if non-KMS key wrapping is being used.</param> protected void DecryptObjectUsingMetadata(GetObjectResponse getObjectResponse, byte[] decryptedEnvelopeKeyKMS) { // Create an instruction object from the object metadata EncryptionInstructions instructions = EncryptionUtils.BuildInstructionsFromObjectMetadata(getObjectResponse, EncryptionClient.EncryptionMaterials, decryptedEnvelopeKeyKMS); if (decryptedEnvelopeKeyKMS != null) { if (getObjectResponse.Metadata[EncryptionUtils.XAmzCekAlg] != null && instructions.MaterialsDescription.ContainsKey(EncryptionUtils.XAmzEncryptionContextCekAlg)) { if (EncryptionUtils.XAmzAesGcmCekAlgValue.Equals(getObjectResponse.Metadata[EncryptionUtils.XAmzCekAlg]) && EncryptionUtils.XAmzAesGcmCekAlgValue.Equals(instructions.MaterialsDescription[EncryptionUtils.XAmzEncryptionContextCekAlg])) { // Decrypt the object with V2 instruction EncryptionUtils.DecryptObjectUsingInstructionsV2(getObjectResponse, instructions); } else { throw new AmazonCryptoException($"The content encryption algorithm used at encryption time does not match the algorithm stored for decryption time." + " The object may be altered or corrupted."); } } else if (EncryptionUtils.XAmzAesCbcPaddingCekAlgValue.Equals(instructions.CekAlgorithm)) { ThrowIfLegacyReadIsDisabled(); // Decrypt the object with V1 instruction EncryptionUtils.DecryptObjectUsingInstructions(getObjectResponse, instructions); } else { throw new AmazonCryptoException($"The content encryption algorithm used at encryption time does not match the algorithm stored for decryption time." + " The object may be altered or corrupted."); } } else if (EncryptionUtils.XAmzAesGcmCekAlgValue.Equals(getObjectResponse.Metadata[EncryptionUtils.XAmzCekAlg])) { // Decrypt the object with V2 instruction EncryptionUtils.DecryptObjectUsingInstructionsV2(getObjectResponse, instructions); } // It is safe to assume, this is either non KMS encryption with V1 client or AES CBC // We don't need to check cek algorithm to be AES CBC, because non KMS encryption with V1 client doesn't set it else { ThrowIfLegacyReadIsDisabled(); EncryptionUtils.DecryptObjectUsingInstructions(getObjectResponse, instructions); } }
private void PreInvokeSynchronous(IExecutionContext executionContext, EncryptionInstructions instructions) { var request = executionContext.RequestContext.OriginalRequest; var putObjectRequest = request as PutObjectRequest; var initiateMultiPartUploadRequest = request as InitiateMultipartUploadRequest; var uploadPartRequest = request as UploadPartRequest; var useKMSKeyWrapping = this.EncryptionClient.EncryptionMaterials.KMSKeyID != null; if (instructions == null && NeedToGenerateInstructions(executionContext)) { instructions = EncryptionUtils.GenerateInstructionsForNonKMSMaterials( EncryptionClient.EncryptionMaterials); } if (putObjectRequest != null) { ValidateConfigAndMaterials(); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { GenerateEncryptedObjectRequestUsingMetadata(putObjectRequest, instructions); } else { GenerateEncryptedObjectRequestUsingInstructionFile(putObjectRequest, instructions); } } if (initiateMultiPartUploadRequest != null) { ValidateConfigAndMaterials(); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { EncryptionUtils.UpdateMetadataWithEncryptionInstructions( initiateMultiPartUploadRequest, instructions, useKMSKeyWrapping); } initiateMultiPartUploadRequest.StorageMode = EncryptionClient.S3CryptoConfig.StorageMode; initiateMultiPartUploadRequest.EncryptedEnvelopeKey = instructions.EncryptedEnvelopeKey; initiateMultiPartUploadRequest.EnvelopeKey = instructions.EnvelopeKey; initiateMultiPartUploadRequest.IV = instructions.InitializationVector; } if (uploadPartRequest != null) { GenerateEncryptedUploadPartRequest(uploadPartRequest); } }
/// <inheritdoc/> protected override async System.Threading.Tasks.Task <EncryptionInstructions> GenerateInstructionsAsync(IExecutionContext executionContext) { EncryptionInstructions instructions = null; if (NeedToGenerateKMSInstructions(executionContext)) { instructions = await EncryptionUtils.GenerateInstructionsForKMSMaterialsAsync( EncryptionClient.KMSClient, EncryptionMaterials).ConfigureAwait(false); } if (instructions == null && NeedToGenerateInstructions(executionContext)) { instructions = EncryptionUtils.GenerateInstructionsForNonKMSMaterials(EncryptionMaterials); } return(instructions); }
/// <summary> /// Encrypts the S3 object being uploaded. /// </summary> /// <param name="executionContext">The execution context, it contains the request and response context.</param> protected async System.Threading.Tasks.Task PreInvokeAsync(IExecutionContext executionContext) { ThrowIfRangeGet(executionContext); EncryptionInstructions instructions = await GenerateInstructionsAsync(executionContext).ConfigureAwait(false); var request = executionContext.RequestContext.OriginalRequest; var putObjectRequest = request as PutObjectRequest; if (putObjectRequest != null) { await EncryptObjectAsync(instructions, putObjectRequest).ConfigureAwait(false); } PreInvokeSynchronous(executionContext, instructions); }
internal void PreInvokeSynchronous(IExecutionContext executionContext, EncryptionInstructions instructions) { var request = executionContext.RequestContext.OriginalRequest; var useKMSKeyWrapping = this.EncryptionClient.EncryptionMaterials.KMSKeyID != null; var initiateMultiPartUploadRequest = request as InitiateMultipartUploadRequest; if (initiateMultiPartUploadRequest != null) { GenerateInitiateMultiPartUploadRequest(instructions, initiateMultiPartUploadRequest, useKMSKeyWrapping); } var uploadPartRequest = request as UploadPartRequest; if (uploadPartRequest != null) { GenerateEncryptedUploadPartRequest(uploadPartRequest); } }
/// <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> /// Encrypts the S3 object being uploaded. /// </summary> /// <param name="executionContext"></param> protected void PreInvoke(IExecutionContext executionContext) { var request = executionContext.RequestContext.OriginalRequest; var putObjectRequest = request as PutObjectRequest; if (putObjectRequest != null) { if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.InstructionFile) { GenerateEncryptedObjectRequestUsingInstructionFile(putObjectRequest); } else { GenerateEncryptedObjectRequestUsingMetadata(putObjectRequest); } } var initiateMultiPartRequest = request as InitiateMultipartUploadRequest; if (initiateMultiPartRequest != null) { EncryptionInstructions instructions = EncryptionUtils.GenerateInstructions(this.EncryptionClient.EncryptionMaterials); if (EncryptionClient.S3CryptoConfig.StorageMode == CryptoStorageMode.ObjectMetadata) { EncryptionUtils.UpdateMetadataWithEncryptionInstructions(initiateMultiPartRequest, instructions); } initiateMultiPartRequest.EnvelopeKey = instructions.EnvelopeKey; initiateMultiPartRequest.IV = instructions.InitializationVector; } var uploadPartRequest = request as UploadPartRequest; if (uploadPartRequest != null) { GenerateEncryptedUploadPartRequest(uploadPartRequest); } }
/// <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(EncryptionMaterials.EmptyMaterialsDescription, 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; } request.RequestState.Add(AmazonS3EncryptionClient.S3CryptoStream, request.InputStream); }
/// <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(); } }
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 PutObjectRequest GenerateEncryptedObjectRequestUsingInstructionFile(PutObjectRequest putObjectRequest, EncryptionInstructions instructions) { EncryptionUtils.AddUnencryptedContentLengthToMetadata(putObjectRequest); // Encrypt the object data with the instruction putObjectRequest.InputStream = EncryptionUtils.EncryptRequestUsingInstruction(putObjectRequest.InputStream, instructions); // Create request for uploading instruction file PutObjectRequest instructionFileRequest = EncryptionUtils.CreateInstructionFileRequest(putObjectRequest, instructions); return(instructionFileRequest); }
/// <inheritdoc/> protected override void GenerateEncryptedObjectRequestUsingMetadata(PutObjectRequest putObjectRequest, EncryptionInstructions instructions) { EncryptionUtils.AddUnencryptedContentLengthToMetadata(putObjectRequest); // Encrypt the object data with the instruction putObjectRequest.InputStream = EncryptionUtils.EncryptRequestUsingInstruction(putObjectRequest.InputStream, instructions); // Update the metadata EncryptionUtils.UpdateMetadataWithEncryptionInstructions(putObjectRequest, instructions, EncryptionMaterials.KMSKeyID != null); }
/// <summary> /// Update InitiateMultipartUploadRequest request with given encryption instructions /// </summary> /// <param name="instructions">EncryptionInstructions which used for encrypting the UploadPartRequest request</param> /// <param name="initiateMultiPartUploadRequest">InitiateMultipartUploadRequest whose encryption context needs to updated</param> /// <param name="useKmsKeyWrapping">If true, KMS mode of encryption is used</param> protected abstract void GenerateInitiateMultiPartUploadRequest(EncryptionInstructions instructions, InitiateMultipartUploadRequest initiateMultiPartUploadRequest, bool useKmsKeyWrapping);
/// <summary> /// Updates the request where the instruction file contains encryption information /// and the input stream contains the encrypted object contents. /// </summary> /// <param name="putObjectRequest">The request whose contents are to be encrypted.</param> /// <param name="instructions">EncryptionInstructions instructions used for creating encrypt stream</param> protected abstract PutObjectRequest GenerateEncryptedObjectRequestUsingInstructionFile(PutObjectRequest putObjectRequest, EncryptionInstructions instructions);
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(); } }
/// <summary> /// Updates the request where the metadata contains encryption information /// and the input stream contains the encrypted object contents. /// </summary> /// <param name="putObjectRequest">The request whose contents are to be encrypted.</param> /// <param name="instructions">EncryptionInstructions instructions used for creating encrypt stream</param> protected abstract void GenerateEncryptedObjectRequestUsingMetadata(PutObjectRequest putObjectRequest, EncryptionInstructions instructions);
/// <inheritdoc/> protected override void GenerateEncryptedObjectRequestUsingMetadata(PutObjectRequest putObjectRequest, EncryptionInstructions instructions) { EncryptionUtils.AddUnencryptedContentLengthToMetadata(putObjectRequest); // Encrypt the object data with the instruction putObjectRequest.InputStream = EncryptionUtils.EncryptRequestUsingInstructionV2(putObjectRequest.InputStream, instructions, putObjectRequest.CalculateContentMD5Header); // Update the metadata EncryptionUtils.UpdateMetadataWithEncryptionInstructionsV2(putObjectRequest, instructions, EncryptionClient); }