/// <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.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); S3ClientForInstructionFile.PutObject(instructionFileRequest); }
/// <summary> /// Performs decryption of data by getting encryption information /// from object metadata or instruction file. /// </summary> /// <param name="response">AmazonWebServiceResponse on which decryption is performed</param> /// <param name="request">IRequest</param> /// <param name="webResponseData">IWebResponseData</param> 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(); } }