private byte[] SimpleDecryptWithPassword(byte[] encryptedMessage,
                                                 string password,
                                                 int nonSecretPayloadLength = 0)
        {
            //User Error Checks
            if (string.IsNullOrWhiteSpace(password) || password.Length < MinPasswordLength)
            {
                throw new ArgumentException($"Must have a password of at least {MinPasswordLength} characters!",
                                            nameof(password));
            }

            if (encryptedMessage == null || encryptedMessage.Length == 0)
            {
                throw new ArgumentException(@"Encrypted Message Required!", nameof(encryptedMessage));
            }

            //Grab Salt from Payload
            var salt = new byte[SaltBitSize / 8];

            Array.Copy(encryptedMessage, nonSecretPayloadLength, salt, 0, salt.Length);

            //Generate Key
            var keyDerivationFunction = new Pkcs5S2KeyGenerator(KeyBitSize, KeyDerivationIterations);
            var key = keyDerivationFunction.DeriveKey(password, salt);

            return(SimpleDecrypt(encryptedMessage, key, salt.Length + nonSecretPayloadLength));
        }
        private byte[] SimpleEncryptWithPassword(byte[] secretMessage, string password, byte[] nonSecretPayload = null)
        {
            nonSecretPayload = nonSecretPayload ?? new byte[] { };

            //User Error Checks
            if (string.IsNullOrWhiteSpace(password) || password.Length < MinPasswordLength)
            {
                throw new ArgumentException($"Must have a password of at least {MinPasswordLength} characters!",
                                            nameof(password));
            }

            if (secretMessage == null || secretMessage.Length == 0)
            {
                throw new ArgumentException(@"Secret Message Required!", nameof(secretMessage));
            }

            //Use Random Salt to minimize pre-generated weak password attacks.
            var salt = GenerateSalt();

            //Generate Key
            var keyDerivationFunction = new Pkcs5S2KeyGenerator(KeyBitSize, KeyDerivationIterations);
            var key = keyDerivationFunction.DeriveKey(password, salt);

            //Create Full Non Secret Payload
            var payload = new byte[salt.Length + nonSecretPayload.Length];

            Array.Copy(nonSecretPayload, payload, nonSecretPayload.Length);
            Array.Copy(salt, 0, payload, nonSecretPayload.Length, salt.Length);

            return(SimpleEncrypt(secretMessage, key, payload));
        }
        public void KeyLengthIsKeyBitSizeDividedBy8(int keyBitSize)
        {
            var keyDerivationFunction = new Pkcs5S2KeyGenerator(keyBitSize);
            var key = keyDerivationFunction.DeriveKey("", new byte[0]);

            Assert.That(key.Length, Is.EqualTo(keyBitSize / 8));
        }
        public void DifferingSaltsProduceDifferingKeys()
        {
            var keyDerivationFunction = new Pkcs5S2KeyGenerator();
            var key1 = keyDerivationFunction.DeriveKey("", new byte[0]);
            var key2 = keyDerivationFunction.DeriveKey("", new byte[] { 1 });

            Assert.That(key1, Is.Not.EquivalentTo(key2));
        }
        public void IdenticalParametersProduceIdenticalKeys()
        {
            var keyDerivationFunction = new Pkcs5S2KeyGenerator();
            var key1 = keyDerivationFunction.DeriveKey("", new byte[0]);
            var key2 = keyDerivationFunction.DeriveKey("", new byte[0]);

            Assert.That(key1, Is.EquivalentTo(key2));
        }
        public void DifferingKeysizeProduceDifferingKeys()
        {
            var keyDerivationFunction1 = new Pkcs5S2KeyGenerator();
            var keyDerivationFunction2 = new Pkcs5S2KeyGenerator(512);
            var key1 = keyDerivationFunction1.DeriveKey("", new byte[0]);
            var key2 = keyDerivationFunction2.DeriveKey("", new byte[0]);

            Assert.That(key1, Is.Not.EquivalentTo(key2));
        }