public override byte[] Encrypt(byte[] input, CryptoKey key)
        {
            byte[]           nonce            = GenerateNonce();
            IAeadBlockCipher cipher           = GetNewAeadBlockCipherInstance();
            AeadParameters   cipherParameters = GetParameters(key, nonce);

            try
            {
                cipher.Init(true, cipherParameters);
                int    outputLen = cipher.GetOutputSize(input.Length);
                byte[] output    = new byte[outputLen + nonce.Length];
                int    position  = cipher.ProcessBytes(input, 0, input.Length, output, 0);

                try
                {
                    cipher.DoFinal(output, position);
                }
                catch (Exception e)
                {
                    throw new AppEncryptionException("unexpected error during encrypt cipher finalization", e);
                }

                AppendNonce(output, nonce);
                return(output);
            }
            finally
            {
                ManagedBufferUtils.WipeByteArray(cipherParameters.Key.GetKey());
            }
        }
        public override byte[] EncryptKey(CryptoKey key)
        {
            using (MetricsUtil.MetricsInstance.Measure.Timer.Time(EncryptkeyTimerOptions))
            {
                Json kmsKeyEnvelope = new Json();

                // We generate a KMS datakey (plaintext and encrypted) and encrypt its plaintext key against remaining regions.
                // This allows us to be able to decrypt from any of the regions locally later.
                GenerateDataKeyResult dataKey = GenerateDataKey(RegionToArnAndClientDictionary, out string dateKeyKeyId);
                byte[] dataKeyPlainText       = dataKey.KeyPlaintext;
                try
                {
                    byte[] encryptedKey = crypto.EncryptKey(key, crypto.GenerateKeyFromBytes(dataKeyPlainText));
                    kmsKeyEnvelope.Put(EncryptedKey, encryptedKey);

                    ConcurrentBag <JObject> kmsRegionKeyJsonBag = new ConcurrentBag <JObject>();
                    Parallel.ForEach(RegionToArnAndClientDictionary.Cast <object>(), regionToArnClientObject =>
                    {
                        DictionaryEntry regionToArnAndClient = (DictionaryEntry)regionToArnClientObject;
                        AwsKmsArnClient arnClient            = (AwsKmsArnClient)regionToArnAndClient.Value;
                        string region = (string)regionToArnAndClient.Key;
                        if (!arnClient.Arn.Equals(dateKeyKeyId))
                        {
                            // If the ARN is different than the datakey's, call encrypt since it's another region
                            EncryptKeyAndBuildResult(
                                arnClient.AwsKmsClient,
                                region,
                                arnClient.Arn,
                                dataKeyPlainText).IfSome(encryptedKeyResult => kmsRegionKeyJsonBag.Add(encryptedKeyResult));
                        }
                        else
                        {
                            // This is the datakey, so build kmsKey json for it
                            kmsRegionKeyJsonBag.Add((JObject)Option <JObject> .Some(BuildKmsRegionKeyJson(
                                                                                        region,
                                                                                        dateKeyKeyId,
                                                                                        dataKey.KeyCiphertext)));
                        }
                    });

                    // TODO Consider adding minimum or quorum check on number of entries
                    kmsKeyEnvelope.Put(KmsKeksKey, kmsRegionKeyJsonBag.ToList());
                }
                catch (Exception e)
                {
                    Logger.LogError(e, "Unexpected execution exception while encrypting KMS data key");
                    throw new AppEncryptionException("unexpected execution error during encrypt", e);
                }
                finally
                {
                    ManagedBufferUtils.WipeByteArray(dataKeyPlainText);
                }

                return(kmsKeyEnvelope.ToUtf8());
            }
        }
Beispiel #3
0
 public virtual CryptoKey DecryptKey(
     byte[] encryptedKey, DateTimeOffset encryptedKeyCreated, CryptoKey keyEncryptionKey, bool revoked)
 {
     byte[] decryptedKey = Decrypt(encryptedKey, keyEncryptionKey);
     try
     {
         return(GenerateKeyFromBytes(decryptedKey, encryptedKeyCreated, revoked));
     }
     finally
     {
         ManagedBufferUtils.WipeByteArray(decryptedKey);
     }
 }
        internal virtual CryptoKey DecryptKmsEncryptedKey(
            IAmazonKeyManagementService awsKmsClient,
            byte[] cipherText,
            DateTimeOffset keyCreated,
            byte[] kmsKeyEncryptionKey,
            bool revoked)
        {
            byte[] plaintextBackingBytes = awsKmsClient.Decrypt(kmsKeyEncryptionKey, null);

            try
            {
                return(crypto.DecryptKey(cipherText, keyCreated, crypto.GenerateKeyFromBytes(plaintextBackingBytes), revoked));
            }
            finally
            {
                ManagedBufferUtils.WipeByteArray(plaintextBackingBytes);
            }
        }
Beispiel #5
0
        public override byte[] Decrypt(byte[] input, CryptoKey key)
        {
            byte[]           nonce            = GetAppendedNonce(input);
            IAeadBlockCipher cipher           = GetNewAeadBlockCipherInstance();
            AeadParameters   cipherParameters = GetParameters(key, nonce);

            try
            {
                cipher.Init(false, cipherParameters);
                int    cipherTextLength = input.Length - nonce.Length;
                int    outputLen        = cipher.GetOutputSize(cipherTextLength);
                byte[] output           = new byte[outputLen];
                int    position         = cipher.ProcessBytes(input, 0, cipherTextLength, output, 0);

                try
                {
                    position += cipher.DoFinal(output, position);
                }
                catch (Exception e)
                {
                    throw new AppEncryptionException("unexpected error during decrypt cipher finalization", e);
                }

                if (position != outputLen)
                {
                    if (Debug.On)
#pragma warning disable 162
                    {
                        Logger.LogError("position {position} not equal to outputLength {outputLen}", position, outputLen);
                    }
#pragma warning restore 162

                    throw new AppEncryptionException("unexpected error during decrypt cipher finalization");
                }

                return(output);
            }
            finally
            {
                ManagedBufferUtils.WipeByteArray(cipherParameters.Key.GetKey());
            }
        }
Beispiel #6
0
        /// <summary>
        /// Generates a random <see cref="CryptoKey"/> using the given time as the created time.
        /// </summary>
        ///
        /// <param name="created"> The time to associate the generated <see cref="CryptoKey"/> with.</param>
        /// <returns>A generated random <see cref="CryptoKey"/>.</returns>
        /// <exception cref="ArgumentException">Throws an exception if key length is invalid.</exception>
        protected internal virtual CryptoKey GenerateRandomCryptoKey(DateTimeOffset created)
        {
            int keyLengthBits = GetKeySizeBits();

            if (keyLengthBits % BitsPerByte != 0)
            {
                throw new ArgumentException("Invalid key length: " + keyLengthBits);
            }

            byte[] keyBytes = new byte[keyLengthBits / BitsPerByte];
            CryptoRandom.GetBytes(keyBytes);
            try
            {
                return(GenerateKeyFromBytes(keyBytes, created));
            }
            finally
            {
                ManagedBufferUtils.WipeByteArray(keyBytes);
            }
        }