/// <summary>
        /// Unmarshaller the response from the service to the response class.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override AmazonWebServiceResponse Unmarshall(JsonUnmarshallerContext context)
        {
            GenerateDataKeyResponse response = new GenerateDataKeyResponse();

            context.Read();
            int targetDepth = context.CurrentDepth;

            while (context.ReadAtDepth(targetDepth))
            {
                if (context.TestExpression("CiphertextBlob", targetDepth))
                {
                    var unmarshaller = MemoryStreamUnmarshaller.Instance;
                    response.CiphertextBlob = unmarshaller.Unmarshall(context);
                    continue;
                }
                if (context.TestExpression("KeyId", targetDepth))
                {
                    var unmarshaller = StringUnmarshaller.Instance;
                    response.KeyId = unmarshaller.Unmarshall(context);
                    continue;
                }
                if (context.TestExpression("Plaintext", targetDepth))
                {
                    var unmarshaller = MemoryStreamUnmarshaller.Instance;
                    response.Plaintext = unmarshaller.Unmarshall(context);
                    continue;
                }
            }

            return(response);
        }
Example #2
0
        public void GenerateKey(int keyBits, out byte[] key, out byte[] encryptedKey, IDictionary <string, string> context)
        {
            DataKeySpec keySpec;

            if (keyBits == 128)
            {
                keySpec = DataKeySpec.AES_128;
            }
            else if (keyBits == 256)
            {
                keySpec = DataKeySpec.AES_256;
            }
            else
            {
                throw new ArgumentException("only 128 and 256 bit keys are supported", "keyBits");
            }
            var request = new GenerateDataKeyRequest
            {
                KeyId             = _keyId,
                KeySpec           = keySpec,
                EncryptionContext = AsDictionary(context)
            };
            GenerateDataKeyResponse response = _client.GenerateDataKey(request);

            key          = response.Plaintext.ToArray();
            encryptedKey = response.CiphertextBlob.ToArray();
        }
Example #3
0
        public void ServiceReturnsFailCode()
        {
            _result = new GenerateDataKeyResponse
            {
                HttpStatusCode = HttpStatusCode.InternalServerError
            };

            KmsService.GenerateDataKeyAsync(Arg.Any <GenerateDataKeyRequest>()).Returns(_result);
        }
        public void ServiceReturnsFailCode()
        {
            _result = new GenerateDataKeyResponse
            {
                HttpStatusCode = HttpStatusCode.ServiceUnavailable
            };

            KmsService.GenerateDataKeyAsync(Arg.Any <GenerateDataKeyRequest>()).Returns(_result);
        }
Example #5
0
        public static GenerateDataKeyResponse Unmarshall(UnmarshallerContext context)
        {
            GenerateDataKeyResponse generateDataKeyResponse = new GenerateDataKeyResponse();

            generateDataKeyResponse.HttpResponse   = context.HttpResponse;
            generateDataKeyResponse.CiphertextBlob = context.StringValue("GenerateDataKey.CiphertextBlob");
            generateDataKeyResponse.KeyId          = context.StringValue("GenerateDataKey.KeyId");
            generateDataKeyResponse.Plaintext      = context.StringValue("GenerateDataKey.Plaintext");
            generateDataKeyResponse.RequestId      = context.StringValue("GenerateDataKey.RequestId");

            return(generateDataKeyResponse);
        }
        private GenerateDataKeyResponse SanitizedResponse(GenerateDataKeyResponse response)
        {
            if (response == null)
            {
                return(response);
            }

            response.CiphertextBlob   = null;
            response.Plaintext        = null;
            response.ResponseMetadata = null;
            return(response);
        }
        private SecureString GetDataKeyFromKms(string application, string tenantId, string keyIdentifier)
        {
            using (var scope = new ProfileContext($"Generating new crypto key using kms for {application} {tenantId}"))
            {
                GenerateDataKeyRequest  request  = null;
                GenerateDataKeyResponse response = null;
                bool isSuccess = false;
                try
                {
                    var client = _kmsClientFactory.GetGlobalClient();
                    request = GetGenerateDataKeyRequest(application, tenantId, keyIdentifier);
                    var waitHandle = new ManualResetEvent(false);

                    Task.Factory.StartNew(async() =>
                    {
                        try
                        {
                            response = await client.GenerateDataKeyAsync(request);
                        }
                        catch (Exception ex)
                        {
                            Platform.Common.ExceptionPolicy.HandleException(ex, Constants.LogOnlyPolicy);
                            throw Errors.ServerSide.KMSCommunicationError();
                        }
                        finally
                        {
                            waitHandle.Set();
                        }
                    });
                    waitHandle.WaitOne();
                    if (response == null || response.HttpStatusCode != HttpStatusCode.OK)
                    {
                        throw Errors.ServerSide.KMSCommunicationError();
                    }

                    //CiperTextBlob is Base64-encoded binary data
                    _cryptoKeyStore.Add(application, tenantId, keyIdentifier, response.CiphertextBlob.ToArray());
                    isSuccess = true;
                    //PlaintText is Base64-encoded binary data
                    return(ConvertStreamToSecureString(response.Plaintext));
                }
                finally
                {
                    LogRQRS(request, SanitizedResponse(response), application, tenantId, "aws_kms_provider", "generate_datakey", isSuccess);
                }
            }
        }
Example #8
0
        public static async Task <byte[]> EncryptData(string toEncrypt, AccountCredentials credentials, string region, CancellationToken token = default)
        {
            try
            {
                var jsonMemStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(toEncrypt ?? ""));
                var cmk           = credentials.cmk;
                var kmsClient     = new AmazonKeyManagementServiceClient(credentials.AWSCredentials, RegionEndpoint.GetBySystemName(region));
                kmsClient.ExceptionEvent += KmsClient_ExceptionEvent;

                var dataKeyRequest = new GenerateDataKeyRequest()
                {
                    KeyId   = cmk, //"alias/console-test1846939174-user1846939660"
                    KeySpec = DataKeySpec.AES_128
                };


                GenerateDataKeyResponse dataKeyResponse = kmsClient.GenerateDataKey(dataKeyRequest);

                var plaintextKey = await StreamToByteArray(dataKeyResponse.Plaintext);

                var encryptedKey = await StreamToByteArray(dataKeyResponse.CiphertextBlob);

                var key = encryptedKey;

                var encryptedResponse = await kmsClient.EncryptAsync(new EncryptRequest()
                {
                    KeyId     = cmk,
                    Plaintext = jsonMemStream,
                }, token);

                var dataBytes = await GetByteDataPackage(encryptedResponse, key);

                //var dataBytes = Encoding.ASCII.GetBytes(dataPack);
                return(dataBytes);
            }
            catch (Exception exc)  //took just over 15 seconds
            {
            }
            return(null);
        }
Example #9
0
        private async Task <(MemoryStream dataKey, string encryptedDataKey)> GenerateEncryptionKey(string keyAlias)
        {
            GenerateDataKeyResponse generateKeyResponse = null;

            try
            {
                generateKeyResponse = await mAmazonKeyManagementService.GenerateDataKeyAsync(new GenerateDataKeyRequest { KeyId = keyAlias, KeySpec = "AES_256" });
            }
            catch (NotFoundException)
            {
                await GenerateMasterKey(keyAlias);

                generateKeyResponse = await mAmazonKeyManagementService.GenerateDataKeyAsync(new GenerateDataKeyRequest { KeyId = keyAlias, KeySpec = "AES_256" });
            }

            if (generateKeyResponse.HttpStatusCode != HttpStatusCode.OK)
            {
                throw new Exception($"Couldn't generate encryption key for {keyAlias}");
            }

            return(generateKeyResponse.Plaintext, ConvertMemoryStreamToBase64String(generateKeyResponse.CiphertextBlob));
        }
Example #10
0
        public async Task EnvelopeAsync(byte[] unencryptedBytes, int symmetricKeySizeBits, int symmetricInitializationVectorSizeBits, Stream encryptedOutputStream, CancellationToken cancellationToken)
        {
            try
            {
                AmazonS3Credentials kmsCredentials = await GetCredentialsAsync();

                if (symmetricKeySizeBits != 256)
                {
                    throw new ArgumentOutOfRangeException(nameof(symmetricKeySizeBits), "Invalid value " + symmetricKeySizeBits + ". Only 256-bit keys are supported.");
                }

                if (symmetricInitializationVectorSizeBits != 128)
                {
                    throw new ArgumentOutOfRangeException(nameof(symmetricInitializationVectorSizeBits), "Invalid value " + symmetricInitializationVectorSizeBits + ". Only 128-bit initialization vectors are supported.");
                }

                AmazonKeyManagementServiceClient kmsClient = new AmazonKeyManagementServiceClient(kmsCredentials.AccessKeyId, kmsCredentials.SecretAccessKey, kmsCredentials.SessionToken, kmsCredentials.RegionEndpoint);

                // generate a symmetric data key
                GenerateDataKeyResponse dataKeyResponse = await kmsClient.GenerateDataKeyAsync(new GenerateDataKeyRequest
                {
                    KeyId   = kmsCredentials.CustomerMasterKey,
                    KeySpec = DataKeySpec.AES_256
                }, cancellationToken);

                // write encrypted payload

                // write encrypted data key length and bytes
                byte[] encryptedDataKeyBytes       = dataKeyResponse.CiphertextBlob.ToArray();
                byte[] encryptedDataKeyBytesLength = BitConverter.GetBytes(encryptedDataKeyBytes.Length);
                encryptedOutputStream.Write(encryptedDataKeyBytesLength, 0, encryptedDataKeyBytesLength.Length);
                encryptedOutputStream.Write(encryptedDataKeyBytes, 0, encryptedDataKeyBytes.Length);

                // write encrypted random initialization vector length and bytes
                Random random = new Random();
                byte[] initializationVectorBytes = new byte[16];
                random.NextBytes(initializationVectorBytes);

                byte[] encryptedInitializationVectorBytes = (await kmsClient.EncryptAsync(new EncryptRequest
                {
                    KeyId = kmsCredentials.CustomerMasterKey,
                    Plaintext = new MemoryStream(initializationVectorBytes)
                }, cancellationToken)).CiphertextBlob.ToArray();

                byte[] encryptedInitializationVectorBytesLength = BitConverter.GetBytes(encryptedInitializationVectorBytes.Length);
                encryptedOutputStream.Write(encryptedInitializationVectorBytesLength, 0, encryptedInitializationVectorBytesLength.Length);
                encryptedOutputStream.Write(encryptedInitializationVectorBytes, 0, encryptedInitializationVectorBytes.Length);

                // write symmetrically encrypted bytes
                byte[] dataKeyBytes = dataKeyResponse.Plaintext.ToArray();
                SymmetricEncryption symmetricEncryption = new SymmetricEncryption(dataKeyBytes, initializationVectorBytes);
                byte[] encryptedBytes = symmetricEncryption.Encrypt(unencryptedBytes);
                encryptedOutputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
            }
            // the following catch statements attempt to filter out expected exceptions (e.g., due to naturally lacking internet connections)
            // from those that are fixable errors within the app. expected exceptions are logged but not reported to the app center, whereas
            // all others are reported to the app center. our approach is to whitelist excepted exceptions as we see them appear in the app
            // center, in order to ensure that we don't miss any fixable errors.
            catch (HttpRequestException ex)
            {
                bool logged = false;

                if (ex.InnerException is WebException)
                {
                    WebException webException = ex.InnerException as WebException;

                    if (IGNORED_WEB_EXCEPTION_STATUSES.Contains(webException.Status))
                    {
                        LogKmsEnvelopeException(ex);
                        logged = true;
                    }
                }

                if (!logged)
                {
                    ReportKmsEnvelopeException(ex);
                }

                throw ex;
            }
            catch (WebException webException)
            {
                if (IGNORED_WEB_EXCEPTION_STATUSES.Contains(webException.Status))
                {
                    LogKmsEnvelopeException(webException);
                }
                else
                {
                    ReportKmsEnvelopeException(webException);
                }

                throw webException;
            }
            catch (OperationCanceledException ex)
            {
                LogKmsEnvelopeException(ex);

                throw ex;
            }
            catch (Exception ex)
            {
                ReportKmsEnvelopeException(ex);

                throw ex;
            }
        }