Exemplo n.º 1
0
        /// <summary>
        /// Update the request's ObjectMetadata with the necessary information for decrypting the object.
        /// </summary>
        /// <param name="request">
        /// AmazonWebServiceRequest  encrypted using the given instruction
        /// </param>
        /// <param name="instructions">
        /// Non-null instruction used to encrypt the data in this AmazonWebServiceRequest .
        /// </param>
        /// <param name="encryptionClient">Encryption client used for put objects</param>
        internal static void UpdateMetadataWithEncryptionInstructionsV2(AmazonWebServiceRequest request,
                                                                        EncryptionInstructions instructions, AmazonS3EncryptionClientBase encryptionClient)
        {
            var keyBytesToStoreInMetadata = instructions.EncryptedEnvelopeKey;
            var base64EncodedEnvelopeKey  = Convert.ToBase64String(keyBytesToStoreInMetadata);

            var ivToStoreInMetadata = instructions.InitializationVector;
            var base64EncodedIv     = Convert.ToBase64String(ivToStoreInMetadata);

            MetadataCollection metadata = null;

            var putObjectRequest = request as PutObjectRequest;

            if (putObjectRequest != null)
            {
                metadata = putObjectRequest.Metadata;
            }

            var initiateMultipartrequest = request as InitiateMultipartUploadRequest;

            if (initiateMultipartrequest != null)
            {
                metadata = initiateMultipartrequest.Metadata;
            }

            if (metadata != null)
            {
                metadata.Add(XAmzWrapAlg, instructions.WrapAlgorithm);
                metadata.Add(XAmzTagLen, DefaultTagBitsLength.ToString());
                metadata.Add(XAmzKeyV2, base64EncodedEnvelopeKey);
                metadata.Add(XAmzCekAlg, instructions.CekAlgorithm);
                metadata.Add(XAmzIV, base64EncodedIv);
                metadata.Add(XAmzMatDesc, JsonMapper.ToJson(instructions.MaterialsDescription));
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates an instruction that will be used to encrypt an object
        /// using materials with the KMSKeyID set.
        /// </summary>
        /// <param name="kmsClient">
        /// Used to call KMS to generate a data key.
        /// </param>
        /// <param name="materials">
        /// The encryption materials to be used to encrypt and decrypt data.
        /// </param>
        /// <returns>
        /// The instruction that will be used to encrypt an object.
        /// </returns>
        internal static async System.Threading.Tasks.Task <EncryptionInstructions> GenerateInstructionsForKMSMaterialsV2Async(IAmazonKeyManagementService kmsClient,
                                                                                                                              EncryptionMaterialsV2 materials)
        {
            if (materials.KMSKeyID == null)
            {
                throw new ArgumentNullException(nameof(materials.KMSKeyID), KmsKeyIdNullMessage);
            }

            switch (materials.KmsType)
            {
            case KmsType.KmsContext:
            {
                var nonce = new byte[DefaultNonceSize];

                // Generate nonce, and get both the key and the encrypted key from KMS.
                RandomNumberGenerator.Create().GetBytes(nonce);
                var result = await kmsClient.GenerateDataKeyAsync(materials.KMSKeyID, materials.MaterialsDescription, KMSKeySpec).ConfigureAwait(false);

                var instructions = new EncryptionInstructions(materials.MaterialsDescription, result.KeyPlaintext, result.KeyCiphertext, nonce,
                                                              XAmzWrapAlgKmsContextValue, XAmzAesGcmCekAlgValue);
                return(instructions);
            }

            default:
                throw new NotSupportedException($"{materials.KmsType} is not supported for KMS Key Id {materials.KMSKeyID}");
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Build encryption instructions for UploadPartEncryptionContext
        /// </summary>
        /// <param name="context">UploadPartEncryptionContext which contains instructions used for encrypting multipart object</param>
        /// <param name="encryptionMaterials">EncryptionMaterials which contains material used for encrypting multipart object</param>
        /// <returns></returns>
        internal static EncryptionInstructions BuildEncryptionInstructionsForInstructionFileV2(UploadPartEncryptionContext context, EncryptionMaterialsBase encryptionMaterials)
        {
            var instructions = new EncryptionInstructions(encryptionMaterials.MaterialsDescription, context.EnvelopeKey, context.EncryptedEnvelopeKey, context.FirstIV,
                                                          context.WrapAlgorithm, context.CekAlgorithm);

            return(instructions);
        }
Exemplo n.º 4
0
        //wrap encrypted stream into AESDecriptionStream wrapper
        internal static Stream DecryptStream(Stream encryptedStream, EncryptionInstructions encryptionInstructions)
        {
            AESDecryptionStream aesDecryptStream;

            aesDecryptStream = new AESDecryptionStream(encryptedStream, encryptionInstructions.EnvelopeKey, encryptionInstructions.InitializationVector);
            return(aesDecryptStream);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Returns encryption instructions to encrypt content with AES/GCM/NoPadding algorithm
        /// Creates encryption key used for AES/GCM/NoPadding and encrypt it with AES/GCM
        /// Encrypted key follows nonce(12 bytes) + key cipher text(16 or 32 bytes) + tag(16 bytes) format
        /// Tag is appended by the AES/GCM cipher with encryption process
        /// </summary>
        /// <param name="materials"></param>
        /// <returns></returns>
        private static EncryptionInstructions EncryptEnvelopeKeyUsingSymmetricKeyV2(EncryptionMaterialsV2 materials)
        {
            var aes = materials.SymmetricProvider as Aes;

            if (aes == null)
            {
                throw new NotSupportedException("AES is the only supported algorithm with this method.");
            }

            switch (materials.SymmetricProviderType)
            {
            case SymmetricAlgorithmType.AesGcm:
            {
                var aesObject      = Aes.Create();
                var nonce          = aesObject.IV.Take(DefaultNonceSize).ToArray();
                var associatedText = Encoding.UTF8.GetBytes(XAmzAesGcmCekAlgValue);
                var cipher         = AesGcmUtils.CreateCipher(true, materials.SymmetricProvider.Key, DefaultTagBitsLength, nonce, associatedText);
                var envelopeKey    = cipher.DoFinal(aesObject.Key);

                var encryptedEnvelopeKey = nonce.Concat(envelopeKey).ToArray();

                var instructions = new EncryptionInstructions(materials.MaterialsDescription, aesObject.Key, encryptedEnvelopeKey, nonce,
                                                              XAmzWrapAlgAesGcmValue, XAmzAesGcmCekAlgValue);
                return(instructions);
            }

            default:
            {
                throw new NotSupportedException($"{materials.SymmetricProviderType} isn't supported with SymmetricProvider");
            }
            }
        }
Exemplo n.º 6
0
        private static EncryptionInstructions EncryptEnvelopeKeyUsingAsymmetricKeyPairV2(EncryptionMaterialsV2 materials)
        {
            var rsa = materials.AsymmetricProvider as RSA;

            if (rsa == null)
            {
                throw new NotSupportedException("RSA is the only supported algorithm with this method.");
            }

            switch (materials.AsymmetricProviderType)
            {
            case AsymmetricAlgorithmType.RsaOaepSha1:
            {
                var aesObject            = Aes.Create();
                var nonce                = aesObject.IV.Take(DefaultNonceSize).ToArray();
                var envelopeKeyToEncrypt = EnvelopeKeyForDataKey(aesObject.Key);
                var cipher               = RsaUtils.CreateRsaOaepSha1Cipher(true, rsa);
                var encryptedEnvelopeKey = cipher.DoFinal(envelopeKeyToEncrypt);

                var instructions = new EncryptionInstructions(materials.MaterialsDescription, aesObject.Key, encryptedEnvelopeKey, nonce,
                                                              XAmzWrapAlgRsaOaepSha1, XAmzAesGcmCekAlgValue);
                return(instructions);
            }

            default:
            {
                throw new NotSupportedException($"{materials.AsymmetricProviderType} isn't supported with AsymmetricProvider");
            }
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Returns an updated stream where the stream contains the encrypted object contents.
        /// The specified instruction will be used to encrypt data.
        /// </summary>
        /// <param name="toBeEncrypted">
        /// The stream whose contents are to be encrypted.
        /// </param>
        /// <param name="instructions">
        /// The instruction that will be used to encrypt the object data.
        /// </param>
        /// <returns>
        /// Encrypted stream, i.e input stream wrapped into encrypted stream
        /// </returns>
        internal static Stream EncryptRequestUsingInstruction(Stream toBeEncrypted, EncryptionInstructions instructions)
        {
            //wrap input stream into AESEncryptionPutObjectStream wrapper
            AESEncryptionPutObjectStream aesEStream;

            aesEStream = new AESEncryptionPutObjectStream(toBeEncrypted, instructions.EnvelopeKey, instructions.InitializationVector);
            return(aesEStream);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Builds an instruction object from the instruction file.
        /// </summary>
        /// <param name="response"> Instruction file GetObject response</param>
        /// <param name="materials">
        /// The non-null encryption materials to be used to encrypt and decrypt Envelope key.
        /// </param>
        /// <returns>
        /// A non-null instruction object containing encryption information.
        /// </returns>
        internal static EncryptionInstructions BuildInstructionsUsingInstructionFileV2(GetObjectResponse response, EncryptionMaterialsBase materials)
        {
            using (TextReader textReader = new StreamReader(response.ResponseStream))
            {
                var jsonData = JsonMapper.ToObject(textReader);

                if (jsonData[XAmzKeyV2] != null)
                {
                    // The envelope contains data in V2 format
                    var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, XAmzKeyV2);
                    var decryptedEnvelopeKey = DecryptNonKmsEnvelopeKeyV2(encryptedEnvelopeKey, materials);

                    var initializationVector = Base64DecodedDataValue(jsonData, XAmzIV);
                    var materialDescription  = JsonMapper.ToObject <Dictionary <string, string> >((string)jsonData[XAmzMatDesc]);

                    var cekAlgorithm  = StringValue(jsonData, XAmzCekAlg);
                    var wrapAlgorithm = StringValue(jsonData, XAmzWrapAlg);

                    var instructions = new EncryptionInstructions(materialDescription, decryptedEnvelopeKey, null,
                                                                  initializationVector, wrapAlgorithm, cekAlgorithm);

                    return(instructions);
                }
                else if (jsonData[XAmzKey] != null)
                {
                    // The envelope contains data in V1 format
                    var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, XAmzKey);
                    var decryptedEnvelopeKey = DecryptNonKMSEnvelopeKey(encryptedEnvelopeKey, materials);

                    var initializationVector = Base64DecodedDataValue(jsonData, XAmzIV);
                    var materialDescription  = JsonMapper.ToObject <Dictionary <string, string> >((string)jsonData[XAmzMatDesc]);

                    var instructions = new EncryptionInstructions(materialDescription, decryptedEnvelopeKey, null, initializationVector);

                    return(instructions);
                }
                else if (jsonData[EncryptedEnvelopeKey] != null)
                {
                    // The envelope contains data in older format
                    var encryptedEnvelopeKey = Base64DecodedDataValue(jsonData, EncryptedEnvelopeKey);
                    var decryptedEnvelopeKey = DecryptNonKMSEnvelopeKey(encryptedEnvelopeKey, materials);

                    var initializationVector = Base64DecodedDataValue(jsonData, IV);

                    return(new EncryptionInstructions(materials.MaterialsDescription, decryptedEnvelopeKey, initializationVector));
                }
                else
                {
                    throw new ArgumentException("Missing parameters required for decryption");
                }
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Update the request's ObjectMetadata with the necessary information for decrypting the object.
        /// </summary>
        /// <param name="request">
        /// AmazonWebServiceRequest encrypted using the given instruction
        /// </param>
        /// <param name="instructions">
        /// Non-null instruction used to encrypt the data in this AmazonWebServiceRequest.
        /// </param>
        /// <param name="useV2Metadata">
        /// If true use V2 metadata format, otherwise use V1.
        /// </param>
        internal static void UpdateMetadataWithEncryptionInstructions(AmazonWebServiceRequest request, EncryptionInstructions instructions, bool useV2Metadata)
        {
            byte[] keyBytesToStoreInMetadata = instructions.EncryptedEnvelopeKey;
            string base64EncodedEnvelopeKey  = Convert.ToBase64String(keyBytesToStoreInMetadata);

            byte[] IVToStoreInMetadata = instructions.InitializationVector;
            string base64EncodedIV     = Convert.ToBase64String(IVToStoreInMetadata);

            MetadataCollection metadata = null;

            var putObjectRequest = request as PutObjectRequest;

            if (putObjectRequest != null)
            {
                metadata = putObjectRequest.Metadata;
            }

            var initiateMultipartrequest = request as InitiateMultipartUploadRequest;

            if (initiateMultipartrequest != null)
            {
                metadata = initiateMultipartrequest.Metadata;
            }

            if (metadata != null)
            {
                if (useV2Metadata)
                {
                    metadata.Add(XAmzKeyV2, base64EncodedEnvelopeKey);
                    metadata.Add(XAmzWrapAlg, instructions.WrapAlgorithm);
                    metadata.Add(XAmzCekAlg, instructions.CekAlgorithm);
                }
                else
                {
                    metadata.Add(XAmzKey, base64EncodedEnvelopeKey);
                }

                metadata.Add(XAmzIV, base64EncodedIV);
                metadata.Add(XAmzMatDesc, JsonMapper.ToJson(instructions.MaterialsDescription));
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Build encryption instructions for UploadPartEncryptionContext
        /// </summary>
        /// <param name="context">UploadPartEncryptionContext which contains instructions used for encrypting multipart object</param>
        /// <param name="encryptionMaterials">EncryptionMaterials which contains material used for encrypting multipart object</param>
        /// <returns></returns>
        internal static EncryptionInstructions BuildEncryptionInstructionsForInstructionFile(UploadPartEncryptionContext context, EncryptionMaterials encryptionMaterials)
        {
            var instructions = new EncryptionInstructions(encryptionMaterials.MaterialsDescription, context.EnvelopeKey, context.EncryptedEnvelopeKey, context.FirstIV);

            return(instructions);
        }
Exemplo n.º 11
0
 /// <summary>
 /// Updates object where the object
 /// input stream contains the decrypted contents.
 /// </summary>
 /// <param name="response">
 /// The getObject response whose contents are to be decrypted.
 /// </param>
 /// <param name="instructions">
 /// The instruction that will be used to encrypt the object data.
 /// </param>
 internal static void DecryptObjectUsingInstructionsV2(GetObjectResponse response, EncryptionInstructions instructions)
 {
     response.ResponseStream = new AesGcmDecryptStream(response.ResponseStream, instructions.EnvelopeKey, instructions.InitializationVector, DefaultTagBitsLength);
 }
Exemplo n.º 12
0
        /// <summary>
        /// Returns an updated input stream where the input stream contains the encrypted object contents.
        /// The specified instruction will be used to encrypt data.
        /// </summary>
        /// <param name="toBeEncrypted">
        /// The stream whose contents are to be encrypted.
        /// </param>
        /// <param name="instructions">
        /// The instruction that will be used to encrypt the object data.
        /// </param>
        /// <returns>
        /// Encrypted stream, i.e input stream wrapped into encrypted stream
        /// </returns>
        internal static Stream EncryptUploadPartRequestUsingInstructionsV2(Stream toBeEncrypted, EncryptionInstructions instructions)
        {
            //wrap input stream into AesGcmEncryptCachingStream wrapper
            Stream aesGcmEncryptStream = new AesGcmEncryptCachingStream(toBeEncrypted, instructions.EnvelopeKey, instructions.InitializationVector, DefaultTagBitsLength);

            return(aesGcmEncryptStream);
        }
Exemplo n.º 13
0
        internal static PutObjectRequest CreateInstructionFileRequestV2(AmazonWebServiceRequest request, EncryptionInstructions instructions)
        {
            var keyBytesToStoreInInstructionFile = instructions.EncryptedEnvelopeKey;
            var base64EncodedEnvelopeKey         = Convert.ToBase64String(keyBytesToStoreInInstructionFile);

            var ivToStoreInInstructionFile = instructions.InitializationVector;
            var base64EncodedIv            = Convert.ToBase64String(ivToStoreInInstructionFile);

            var jsonData = new JsonData
            {
                [XAmzTagLen]  = DefaultTagBitsLength.ToString(),
                [XAmzKeyV2]   = base64EncodedEnvelopeKey,
                [XAmzCekAlg]  = instructions.CekAlgorithm,
                [XAmzWrapAlg] = instructions.WrapAlgorithm,
                [XAmzIV]      = base64EncodedIv,
                [XAmzMatDesc] = JsonMapper.ToJson(instructions.MaterialsDescription)
            };

            var contentBody = jsonData.ToJson();

            var putObjectRequest = request as PutObjectRequest;

            if (putObjectRequest != null)
            {
                return(GetInstructionFileRequest(putObjectRequest.BucketName, putObjectRequest.Key, EncryptionInstructionFileV2Suffix, contentBody));
            }

            var completeMultiPartRequest = request as CompleteMultipartUploadRequest;

            if (completeMultiPartRequest != null)
            {
                return(GetInstructionFileRequest(completeMultiPartRequest.BucketName, completeMultiPartRequest.Key, EncryptionInstructionFileV2Suffix, contentBody));
            }

            return(null);
        }
Exemplo n.º 14
0
        internal static PutObjectRequest CreateInstructionFileRequest(AmazonWebServiceRequest request, EncryptionInstructions instructions)
        {
            byte[] keyBytesToStoreInInstructionFile = instructions.EncryptedEnvelopeKey;
            string base64EncodedEnvelopeKey         = Convert.ToBase64String(keyBytesToStoreInInstructionFile);

            byte[] IVToStoreInInstructionFile = instructions.InitializationVector;
            string base64EncodedIV            = Convert.ToBase64String(IVToStoreInInstructionFile);

            JsonData jsonData = new JsonData();

            jsonData["EncryptedEnvelopeKey"] = base64EncodedEnvelopeKey;
            jsonData["IV"] = base64EncodedIV;

            var contentBody = jsonData.ToJson();

            var putObjectRequest = request as PutObjectRequest;

            if (putObjectRequest != null)
            {
                return(GetInstructionFileRequest(putObjectRequest.BucketName, putObjectRequest.Key, EncryptionInstructionFileSuffix, contentBody));
            }

            var completeMultiPartRequest = request as CompleteMultipartUploadRequest;

            if (completeMultiPartRequest != null)
            {
                return(GetInstructionFileRequest(completeMultiPartRequest.BucketName, completeMultiPartRequest.Key, EncryptionInstructionFileSuffix, contentBody));
            }

            return(null);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Returns an updated stream where the stream contains the encrypted object contents.
        /// The specified instruction will be used to encrypt data.
        /// </summary>
        /// <param name="toBeEncrypted">
        /// The stream whose contents are to be encrypted.
        /// </param>
        /// <param name="instructions">
        /// The instruction that will be used to encrypt the object data.
        /// </param>
        /// <returns>
        /// Encrypted stream, i.e input stream wrapped into encrypted stream
        /// </returns>
        internal static Stream EncryptRequestUsingInstructionV2(Stream toBeEncrypted, EncryptionInstructions instructions)
        {
            Stream gcmEncryptStream = new AesGcmEncryptStream(toBeEncrypted, instructions.EnvelopeKey, instructions.InitializationVector, DefaultTagBitsLength);

            return(gcmEncryptStream);
        }
Exemplo n.º 16
0
 /// <summary>
 /// Updates object where the object
 /// input stream contains the decrypted contents.
 /// </summary>
 /// <param name="response">
 /// The getObject response whose contents are to be decrypted.
 /// </param>
 /// <param name="instructions">
 /// The instruction that will be used to encrypt the object data.
 /// </param>
 internal static void DecryptObjectUsingInstructions(GetObjectResponse response, EncryptionInstructions instructions)
 {
     response.ResponseStream = DecryptStream(response.ResponseStream, instructions);
 }
Exemplo n.º 17
0
        /// <summary>
        /// Returns an updated stream where the stream contains the encrypted object contents.
        /// The specified instruction will be used to encrypt data.
        /// </summary>
        /// <param name="toBeEncrypted">
        /// The stream whose contents are to be encrypted.
        /// </param>
        /// <param name="instructions">
        /// The instruction that will be used to encrypt the object data.
        /// </param>
        /// <param name="shouldUseCachingStream">
        /// Flag indicating if the caching stream should be used or not.
        /// </param>
        /// <returns>
        /// Encrypted stream, i.e input stream wrapped into encrypted stream
        /// </returns>
        internal static Stream EncryptRequestUsingInstructionV2(Stream toBeEncrypted, EncryptionInstructions instructions, bool shouldUseCachingStream)
        {
            Stream gcmEncryptStream = (shouldUseCachingStream ?
                                       new AesGcmEncryptCachingStream(toBeEncrypted, instructions.EnvelopeKey, instructions.InitializationVector, DefaultTagBitsLength)
                                        : new AesGcmEncryptStream(toBeEncrypted, instructions.EnvelopeKey, instructions.InitializationVector, DefaultTagBitsLength)
                                       );

            return(gcmEncryptStream);
        }