/// <summary>
        /// Default constructor for Symmetric key algorithm
        /// </summary>
        /// <param name="algorithm">Algorithm to use</param>
        /// <param name="keySizeInBits">Key size in bits, e.g. 256</param>
        /// <param name="settings">Settings for chosen algorithm</param>
        public SymmetricKeyAlgorithm(SymmetricEncryptionAlgorithm algorithm, int keySizeInBits, object settings)
        {
            this.algorithm = algorithm.ToString();

            if (algorithm == SymmetricEncryptionAlgorithm.AES_CTR)
            {
                if (!Array.Exists(AES_CTR.allowedKeyLengths, allowed => allowed * 8 == keySizeInBits))
                {
                    throw new ArgumentException($"{keySizeInBits} is not valid AES-CTR key size!");
                }

                this.settingsAES_CTR = (SettingsAES_CTR)settings;
            }
            else if (algorithm == SymmetricEncryptionAlgorithm.ChaCha20)
            {
                if (ChaCha20.allowedKeyLength * 8 != keySizeInBits)
                {
                    throw new ArgumentException($"{keySizeInBits} is not valid ChaCha20 key size!");
                }

                this.settingsChaCha20 = (SettingsChaCha20)settings;
            }
            else
            {
                throw new NotImplementedException($"{algorithm} constructor not implemented yet!");
            }

            this.keySizeInBits = keySizeInBits;
        }
        public void SetPassword(SymmetricEncryptionAlgorithm cryptoAlgo, int keySize, string password)
        {
            int keySizeBytes = keySize / 8;
            _kdf = PBKDF2.CreateHMACSHA256(password, keySizeBytes, PBKDF2_ITERATION_COUNT);
            byte[] key = _kdf.GetBytes(keySizeBytes);

            _containerKey = new SymmetricCryptoKey(cryptoAlgo, key);
            _hmac = new HMACSHA256(key);
        }
        public SymmetricCryptoKey(SymmetricEncryptionAlgorithm cryptoAlgo, int keySize, PaddingMode padding = PaddingMode.ISO10126)
        {
            _symAlgo         = SymmetricAlgorithm.Create(cryptoAlgo.ToString());
            _symAlgo.KeySize = keySize;
            _symAlgo.Padding = padding;
            _symAlgo.Mode    = CipherMode.CBC;
            _symAlgo.GenerateKey();
            _symAlgo.GenerateIV();

            _cryptoAlgo = cryptoAlgo;
        }
Example #4
0
        /// <summary>
        /// Encrypts the specified plaintext
        /// </summary>
        public string Encrypt(string plainText, byte[] key, byte[] iv, SymmetricEncryptionAlgorithm algorithm, PaddingMode?paddingMode = null)
        {
            var hash = Encrypt(
                Encoding.ASCII.GetBytes(plainText),
                key,
                iv,
                algorithm,
                paddingMode);

            return(Convert.ToBase64String(hash));
        }
Example #5
0
        /// <summary>
        /// Decrypts the specified hash.
        /// </summary>
        public string Decrypt(string hash, byte[] key, byte[] iv, SymmetricEncryptionAlgorithm algorithm, PaddingMode?paddingMode = null)
        {
            var plainText = Decrypt(
                Convert.FromBase64String(hash),
                key,
                iv,
                algorithm,
                paddingMode);

            return(Encoding.ASCII.GetString(plainText));
        }
Example #6
0
        /// <summary>
        /// Returns a new symmetric algorithm instance to be used during the
        /// encryption/decryption operations. The algorithm to create is chosen
        /// using the algorithm field.
        /// </summary>
        private SymmetricAlgorithm GetNewSymmetricAlgorithm(byte[] key, byte[] iv, SymmetricEncryptionAlgorithm algorithm, PaddingMode?paddingMode)
        {
            SymmetricAlgorithm symmetricAlgorithm;

            switch (algorithm)
            {
            case SymmetricEncryptionAlgorithm.Des:
                symmetricAlgorithm = new DESCryptoServiceProvider();

                byte[] desKey = new byte[8];
                byte[] desIV  = new byte[8];

                Array.Copy(key, 0, desKey, 0, 8);
                Array.Copy(iv, 0, desIV, 0, 8);

                symmetricAlgorithm.Key = desKey;
                symmetricAlgorithm.IV  = desIV;
                break;

            case SymmetricEncryptionAlgorithm.TripleDes:
                symmetricAlgorithm = new TripleDESCryptoServiceProvider();

                symmetricAlgorithm.Key = key;
                symmetricAlgorithm.IV  = iv;

                break;

            case SymmetricEncryptionAlgorithm.Rijndael:
                symmetricAlgorithm = new RijndaelManaged();

                symmetricAlgorithm.Key = key;
                symmetricAlgorithm.IV  = iv;

                break;

            default:
                throw new ArgumentOutOfRangeException("algorithm");
            }

            if (paddingMode.HasValue)
            {
                symmetricAlgorithm.Padding = paddingMode.Value;
            }

            return(symmetricAlgorithm);
        }
Example #7
0
        /// <summary>
        /// Encrypts the specified plaintext
        /// </summary>
        public byte[] Encrypt(byte[] plainText, byte[] key, byte[] iv, SymmetricEncryptionAlgorithm algorithm, PaddingMode?paddingMode = null)
        {
            using (SymmetricAlgorithm symmetricAlgorithm = this.GetNewSymmetricAlgorithm(key, iv, algorithm, paddingMode))
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (ICryptoTransform encryptor = symmetricAlgorithm.CreateEncryptor())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(plainText, 0, plainText.Length);
                            cryptoStream.FlushFinalBlock();
                        }
                    }

                    return(ms.ToArray());
                }
            }
        }
        public SymmetricCryptoKey(SymmetricEncryptionAlgorithm cryptoAlgo, byte[] key, byte[] IV = null, PaddingMode padding = PaddingMode.ISO10126)
        {
            _symAlgo         = SymmetricAlgorithm.Create(cryptoAlgo.ToString());
            _symAlgo.KeySize = key.Length * 8;
            _symAlgo.Padding = padding;
            _symAlgo.Mode    = CipherMode.CBC;
            _symAlgo.Key     = key;

            if (IV == null)
            {
                _symAlgo.GenerateIV();
            }
            else
            {
                _symAlgo.IV = IV;
            }

            _cryptoAlgo = cryptoAlgo;
        }
        public SymmetricCryptoKey(Stream s)
        {
            BinaryReader bR = new BinaryReader(s);

            if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "SK")
            {
                throw new CryptoException("Invalid SymmetricCryptoKey format.");
            }

            byte version = bR.ReadByte();

            switch (version) //version
            {
            case 1:
            case 2:
                //algorithm
                _cryptoAlgo = (SymmetricEncryptionAlgorithm)bR.ReadByte();
                _symAlgo    = SymmetricAlgorithm.Create(_cryptoAlgo.ToString());

                //key
                _symAlgo.Key = bR.ReadBytes(bR.ReadByte());

                //IV
                _symAlgo.IV = bR.ReadBytes(bR.ReadByte());

                //padding
                if (version == 1)
                {
                    _symAlgo.Padding = PaddingMode.ISO10126;
                }
                else
                {
                    _symAlgo.Padding = (PaddingMode)bR.ReadByte();
                }

                _symAlgo.Mode = CipherMode.CBC;
                break;

            default:
                throw new CryptoException("SymmetricCryptoKey format version not supported.");
            }
        }
Example #10
0
        /// <summary>
        /// Decrypts the specified hash.
        /// </summary>
        public byte[] Decrypt(byte[] hash, byte[] key, byte[] iv, SymmetricEncryptionAlgorithm algorithm, PaddingMode?paddingMode = null)
        {
            using (SymmetricAlgorithm symmetricAlgorithm = this.GetNewSymmetricAlgorithm(key, iv, algorithm, paddingMode))
            {
                using (ICryptoTransform decryptor = symmetricAlgorithm.CreateDecryptor())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(new MemoryStream(hash), decryptor, CryptoStreamMode.Read))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            byte[] buffer = new byte[BufferSize];
                            int    readBytes;

                            while ((readBytes = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                ms.Write(buffer, 0, buffer.Length);
                            }

                            return(ms.ToArray());
                        }
                    }
                }
            }
        }
 public CryptoContainer(SymmetricEncryptionAlgorithm cryptoAlgo, int keySize, string password)
 {
     SetPassword(cryptoAlgo, keySize, password);
 }
        private void ReadFrom(Stream s, string password)
        {
            byte[] format = new byte[2];
            s.Read(format, 0, 2);

            if (Encoding.ASCII.GetString(format) != "CC")
            {
                throw new InvalidCryptoContainerException("Invalid CryptoContainer format.");
            }

            switch (s.ReadByte()) //version
            {
            case 0:
                ReadPlainTextFrom(s);
                break;

            case 1:     //depricated version
            {
                if (password == null)
                {
                    throw new InvalidCryptoContainerException("Password required.");
                }

                //CryptoAlgo
                SymmetricEncryptionAlgorithm cryptoAlgo = (SymmetricEncryptionAlgorithm)s.ReadByte();

                //KeySizeBytes
                int keySizeBytes = s.ReadByte();

                byte[] IV = new byte[s.ReadByte()];
                s.Read(IV, 0, IV.Length);

                byte[] key;

                switch (keySizeBytes)
                {
                case 16:
                    key = HashAlgorithm.Create("MD5").ComputeHash(Encoding.UTF8.GetBytes(password));
                    break;

                case 32:
                    key = HashAlgorithm.Create("SHA256").ComputeHash(Encoding.UTF8.GetBytes(password));
                    break;

                default:
                    throw new CryptoException("CryptoContainer key size not supported.");
                }

                _containerKey = new SymmetricCryptoKey(cryptoAlgo, key, IV);
                ReadPlainTextFrom(_containerKey.GetCryptoStreamReader(s));

                //auto upgrade to version 2 with PBKDF2-HMAC-SHA256 when calling WriteTo
                _kdf          = PBKDF2.CreateHMACSHA256(password, keySizeBytes, PBKDF2_ITERATION_COUNT);
                key           = _kdf.GetBytes(keySizeBytes);
                _containerKey = new SymmetricCryptoKey(cryptoAlgo, key, IV);
                _hmac         = new HMACSHA256(key);
            }
            break;

            case 2:     //using PBKDF2-HMAC-SHA256
            {
                if (password == null)
                {
                    throw new InvalidCryptoContainerException("Password required.");
                }

                //CryptoAlgo
                SymmetricEncryptionAlgorithm cryptoAlgo = (SymmetricEncryptionAlgorithm)s.ReadByte();

                //KeySizeBytes
                int keySizeBytes = s.ReadByte();

                byte[] IV = new byte[s.ReadByte()];
                s.Read(IV, 0, IV.Length);

                byte[] salt = new byte[s.ReadByte()];
                s.Read(salt, 0, salt.Length);

                byte[] HMAC = new byte[s.ReadByte()];
                s.Read(HMAC, 0, HMAC.Length);

                _kdf = PBKDF2.CreateHMACSHA256(password, salt, PBKDF2_ITERATION_COUNT);
                byte[] key = _kdf.GetBytes(keySizeBytes);

                //authenticate data
                _hmac = new HMACSHA256(key);
                long   startPosition = s.Position;
                byte[] computedHMAC  = _hmac.ComputeHash(s);
                s.Position = startPosition;

                //verify hmac
                for (int i = 0; i < HMAC.Length; i++)
                {
                    if (HMAC[i] != computedHMAC[i])
                    {
                        throw new CryptoException("Invalid password or data tampered.");
                    }
                }

                //decrypt data
                _containerKey = new SymmetricCryptoKey(cryptoAlgo, key, IV);
                ReadPlainTextFrom(_containerKey.GetCryptoStreamReader(s));
            }
            break;

            case -1:
                throw new EndOfStreamException();

            default:
                throw new InvalidCryptoContainerException("CryptoContainer format version not supported.");
            }
        }
Example #13
0
        /// <summary>
        /// Add contact to Common secret container
        /// </summary>
        /// <param name="password">Plaintext password</param>
        /// <param name="contact">Contact to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) AddContactSecret(string password, Contact contact, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            (bool checkResult, string possibleError) = MandatoryChecks(contact, "Contact", keyIdentifier, password);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            byte[] derivedPassword = this.FindKeyDerivationFunctionEntryWithKeyIdentifier(keyIdentifier).GeneratePasswordBytes(password);

            this.contactSecrets.Add(new ContactSecret(contact, keyIdentifier, ska, derivedPassword));

            return(success : true, possibleError : "");
        }
Example #14
0
        /// <summary>
        /// Add file entry to Common secret container
        /// </summary>
        /// <param name="derivedPassword">Derived password</param>
        /// <param name="fileEntry">File entry to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) AddFileEntrySecret(byte[] derivedPassword, FileEntry fileEntry, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            (bool checkResult, string possibleError) = MandatoryChecks(fileEntry, "FileEntry", keyIdentifier, derivedPassword);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            this.fileSecrets.Add(new FileEntrySecret(fileEntry, keyIdentifier, ska, derivedPassword));

            return(success : true, possibleError : "");
        }
Example #15
0
        /// <summary>
        /// Add payment card to Common secret container
        /// </summary>
        /// <param name="derivedPassword">Derived password</param>
        /// <param name="paymentCard">Payment card to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) AddPaymentCardSecret(byte[] derivedPassword, PaymentCard paymentCard, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            (bool checkResult, string possibleError) = MandatoryChecks(paymentCard, "PaymentCard", keyIdentifier, derivedPassword);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            this.paymentCardSecrets.Add(new PaymentCardSecret(paymentCard, keyIdentifier, ska, derivedPassword));

            return(success : true, possibleError : "");
        }
Example #16
0
        /// <summary>
        /// Replace existing contact in Common secret container with another one (basically for editing purposes)
        /// </summary>
        /// <param name="zeroBasedIndex">Zero based index of contact secret that will be replaced</param>
        /// <param name="password">Plaintext password</param>
        /// <param name="contact">Contact to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) ReplaceContactSecret(int zeroBasedIndex, string password, Contact contact, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            if (zeroBasedIndex < 0 || zeroBasedIndex >= this.contactSecrets.Count)
            {
                return(false, $"Index {zeroBasedIndex} is out of bounds [0, {this.contactSecrets.Count})");
            }

            (bool checkResult, string possibleError) = MandatoryChecks(contact, "Contact", keyIdentifier, password);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            byte[] derivedPassword = this.FindKeyDerivationFunctionEntryWithKeyIdentifier(keyIdentifier).GeneratePasswordBytes(password);

            this.contactSecrets[zeroBasedIndex] = new ContactSecret(contact, keyIdentifier, ska, derivedPassword);

            return(success : true, possibleError : "");
        }
Example #17
0
        /// <summary>
        /// Replace existing payment card in Common secret container with another one (basically for editing purposes)
        /// </summary>
        /// <param name="zeroBasedIndex">Zero based index of payment card secret that will be replaced</param>
        /// <param name="derivedPassword">Derived password</param>
        /// <param name="paymentCard">Payment card to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) ReplacePaymentCardSecret(int zeroBasedIndex, byte[] derivedPassword, PaymentCard paymentCard, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            if (zeroBasedIndex < 0 || zeroBasedIndex >= this.paymentCardSecrets.Count)
            {
                return(false, $"Index {zeroBasedIndex} is out of bounds [0, {this.paymentCardSecrets.Count})");
            }

            (bool checkResult, string possibleError) = MandatoryChecks(paymentCard, "PaymentCard", keyIdentifier, derivedPassword);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            this.paymentCardSecrets[zeroBasedIndex] = new PaymentCardSecret(paymentCard, keyIdentifier, ska, derivedPassword);

            return(success : true, possibleError : "");
        }
 /// <summary>
 /// Generate new SymmetricKeyAlgorithm, you should use this instead of constructor
 /// </summary>
 /// <param name="symmetricEncryptionAlgorithm">Wanted Symmetric encryption algorithm</param>
 /// <returns>SymmetricKeyAlgorithm</returns>
 public static SymmetricKeyAlgorithm GenerateNew(SymmetricEncryptionAlgorithm symmetricEncryptionAlgorithm)
 {
     return(new SymmetricKeyAlgorithm(symmetricEncryptionAlgorithm, 256, (symmetricEncryptionAlgorithm == SymmetricEncryptionAlgorithm.AES_CTR) ? (object)SettingsAES_CTR.CreateWithCryptographicRandomNumbers() : (object)SettingsChaCha20.CreateWithCryptographicRandomNumbers()));
 }
Example #19
0
        /// <summary>
        /// Add login information secret to Common secret container
        /// </summary>
        /// <param name="derivedPassword">Derived password</param>
        /// <param name="loginInformation">Loginiformation to add</param>
        /// <param name="keyIdentifier">Key identifier</param>
        /// <param name="algorithm">Symmetric Encryption Algorithm to use</param>
        /// <returns>Tuple that tells if add was success, and possible error</returns>
        public (bool success, string possibleError) AddLoginInformationSecret(byte[] derivedPassword, LoginInformation loginInformation, string keyIdentifier, SymmetricEncryptionAlgorithm algorithm = SymmetricEncryptionAlgorithm.AES_CTR)
        {
            (bool checkResult, string possibleError) = MandatoryChecks(loginInformation, "LoginInformation", keyIdentifier, derivedPassword);
            if (!checkResult)
            {
                return(checkResult, possibleError);
            }

            SymmetricKeyAlgorithm ska = SymmetricKeyAlgorithm.GenerateNew(algorithm);

            this.loginInformationSecrets.Add(new LoginInformationSecret(loginInformation, keyIdentifier, ska, derivedPassword));

            return(success : true, possibleError : "");
        }