private CascadingSymmetricKey(SecureSymmetricKeyDerivationMode derivationMode, params SymmetricAlgorithmSpecification[] algorithms)
            : base(ConcurrencyControlMode.SingleThreadLock)
        {
            Depth = algorithms.Length;
            Keys  = new SecureSymmetricKey[Depth];

            for (var i = 0; i < Depth; i++)
            {
                Keys[i] = SecureSymmetricKey.New(algorithms[i], derivationMode);
            }
        }
        private SecureSymmetricKey(SymmetricAlgorithmSpecification algorithm, SecureSymmetricKeyDerivationMode derivationMode, PinnedBuffer keySource)
            : base(ConcurrencyControlMode.SingleThreadLock)
        {
            Algorithm          = algorithm.RejectIf().IsEqualToValue(SymmetricAlgorithmSpecification.Unspecified, nameof(algorithm));
            DerivationMode     = derivationMode.RejectIf().IsEqualToValue(SecureSymmetricKeyDerivationMode.Unspecified, nameof(derivationMode));
            KeySource          = new SecureBuffer(KeySourceLengthInBytes);
            LazyPbkdf2Provider = new Lazy <Rfc2898DeriveBytes>(InitializePbkdf2Algorithm, LazyThreadSafetyMode.ExecutionAndPublication);

            // Gather information about the derived key.
            var keyBitLength = algorithm.ToKeyBitLength();

            DerivedKeyLength = (keyBitLength / 8);
            BlockWordCount   = (keyBitLength / 32);
            BlockCount       = (KeySourceWordCount / BlockWordCount);

            // Copy in the key source bits.
            KeySource.Access(buffer => Array.Copy(keySource, buffer, buffer.Length));
        }
 /// <summary>
 /// Generates a new <see cref="CascadingSymmetricKey" />.
 /// </summary>
 /// <param name="derivationMode">
 /// The mode used to derive the generated keys.
 /// </param>
 /// <param name="firstLayerAlgorithm">
 /// The algorithm for the first (inner-most) layer of encryption.
 /// </param>
 /// <param name="secondLayerAlgorithm">
 /// The algorithm for the second layer of encryption.
 /// </param>
 /// <param name="thirdLayerAlgorithm">
 /// The algorithm for the third layer of encryption.
 /// </param>
 /// <param name="fourthLayerAlgorithm">
 /// The algorithm for the fourth (outer-most) layer of encryption.
 /// </param>
 /// <returns>
 /// A new <see cref="CascadingSymmetricKey" />.
 /// </returns>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="derivationMode" /> is equal to <see cref="SecureSymmetricKeyDerivationMode.Unspecified" /> -or- one or
 /// more algorithm layers are equal to <see cref="SymmetricAlgorithmSpecification.Unspecified" />.
 /// </exception>
 public static CascadingSymmetricKey New(SecureSymmetricKeyDerivationMode derivationMode, SymmetricAlgorithmSpecification firstLayerAlgorithm, SymmetricAlgorithmSpecification secondLayerAlgorithm, SymmetricAlgorithmSpecification thirdLayerAlgorithm, SymmetricAlgorithmSpecification fourthLayerAlgorithm) => new CascadingSymmetricKey(derivationMode, firstLayerAlgorithm, secondLayerAlgorithm, thirdLayerAlgorithm, fourthLayerAlgorithm);
Example #4
0
        private static void Encrypt_ShouldBeReversible_UsingSecureSymmetricKey(SymmetricAlgorithmSpecification algorithm, SecureSymmetricKeyDerivationMode derivationMode)
        {
            using (var randomnessProvider = RandomNumberGenerator.Create())
            {
                // Arrange.
                var binarySerializer = new BinaryPassThroughSerializer();
                var target           = new SymmetricProcessor <Byte[]>(randomnessProvider, binarySerializer);
                var plaintextObject  = new Byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

                using (var key = SecureSymmetricKey.New(algorithm, derivationMode))
                {
                    // Act.
                    var ciphertextResult = target.Encrypt(plaintextObject, key);

                    // Assert.
                    ciphertextResult.Should().NotBeNullOrEmpty();
                    ciphertextResult.Count(value => value == 0x00).Should().NotBe(ciphertextResult.Length);

                    // Act.
                    var plaintextResult = target.Decrypt(ciphertextResult, key);

                    // Assert.
                    plaintextResult.Should().NotBeNullOrEmpty();
                    plaintextResult.Length.Should().Be(plaintextObject.Length);
                    plaintextResult.Count(value => value == 0x00).Should().NotBe(plaintextResult.Length);

                    for (var i = 0; i < plaintextResult.Length; i++)
                    {
                        // Assert.
                        plaintextResult[i].Should().Be(plaintextObject[i]);
                    }
                }
            }
        }
Example #5
0
 private static void Encrypt_ShouldBeReversible_UsingCascadingSymmetricKey_WithTwoLayers(SecureSymmetricKeyDerivationMode derivationMode, SymmetricAlgorithmSpecification firstLayerAlgorithm, SymmetricAlgorithmSpecification secondLayerAlgorithm)
 {
     using (var key = CascadingSymmetricKey.New(derivationMode, firstLayerAlgorithm, secondLayerAlgorithm))
     {
         Encrypt_ShouldBeReversible_UsingCascadingSymmetricKey(key);
     }
 }
 /// <summary>
 /// Generates a new <see cref="SecureSymmetricKey" />.
 /// </summary>
 /// <param name="algorithm">
 /// The symmetric-key algorithm that the generated key is derived to interoperate with. The default value is
 /// <see cref="SymmetricAlgorithmSpecification.Aes256Cbc" />.
 /// </param>
 /// <param name="derivationMode">
 /// The mode used to derive the generated key. The default value is
 /// <see cref="SecureSymmetricKeyDerivationMode.XorLayeringWithSubstitution" />.
 /// </param>
 /// <param name="keySource">
 /// A buffer comprising 384 bytes (3,072 bits) from which the private key is derived.
 /// </param>
 /// <returns>
 /// A new <see cref="SecureSymmetricKey" />.
 /// </returns>
 /// <exception cref="ArgumentException">
 /// <paramref name="keySource" /> is not 384 bytes in length.
 /// </exception>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="algorithm" /> is equal to <see cref="SymmetricAlgorithmSpecification.Unspecified" /> -or-
 /// <paramref name="derivationMode" /> is equal to <see cref="SecureSymmetricKeyDerivationMode.Unspecified" />.
 /// </exception>
 public static SecureSymmetricKey New(SymmetricAlgorithmSpecification algorithm, SecureSymmetricKeyDerivationMode derivationMode, PinnedBuffer keySource)
 {
     keySource.RejectIf(argument => argument.Length != KeySourceLengthInBytes, nameof(keySource), $"The key source is not {KeySourceLengthInBytes} bytes in length.");
     return(new SecureSymmetricKey(algorithm, derivationMode, keySource));
 }
 /// <summary>
 /// Generates a new <see cref="SecureSymmetricKey" />.
 /// </summary>
 /// <param name="algorithm">
 /// The symmetric-key algorithm that the generated key is derived to interoperate with. The default value is
 /// <see cref="SymmetricAlgorithmSpecification.Aes256Cbc" />.
 /// </param>
 /// <param name="derivationMode">
 /// The mode used to derive the generated key. The default value is
 /// <see cref="SecureSymmetricKeyDerivationMode.XorLayeringWithSubstitution" />.
 /// </param>
 /// <returns>
 /// A new <see cref="SecureSymmetricKey" />.
 /// </returns>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="algorithm" /> is equal to <see cref="SymmetricAlgorithmSpecification.Unspecified" /> or
 /// <paramref name="derivationMode" /> is equal to <see cref="SecureSymmetricKeyDerivationMode.Unspecified" />.
 /// </exception>
 public static SecureSymmetricKey New(SymmetricAlgorithmSpecification algorithm, SecureSymmetricKeyDerivationMode derivationMode)
 {
     using (var keySource = new PinnedBuffer(KeySourceLengthInBytes, true))
     {
         RandomnessProvider.GetBytes(keySource);
         return(New(algorithm, derivationMode, keySource));
     }
 }