Пример #1
0
        /// <inheritdoc/>
        public byte[] Decrypt(byte[] packedCipher, SecureString password)
        {
            if (packedCipher == null)
            {
                throw new ArgumentNullException("packedCipher");
            }

            CryptoHeader header;

            byte[] cipher;
            CryptoHeaderPacker.UnpackHeaderAndCipher(packedCipher, PackageName, out header, out cipher);

            ISymmetricEncryptionAlgorithm decryptor = new SymmetricEncryptionAlgorithmFactory().CreateAlgorithm(header.AlgorithmName);
            IKeyDerivationFunction        kdf       = new KeyDerivationFactory().CreateKdf(header.KdfName);

            try
            {
                int    cost    = int.Parse(header.Cost);
                byte[] key     = kdf.DeriveKeyFromPassword(password, decryptor.ExpectedKeySize, header.Salt, cost);
                byte[] message = decryptor.Decrypt(cipher, key, header.Nonce);

                if (string.Equals(CompressionGzip, header.Compression, StringComparison.InvariantCultureIgnoreCase))
                {
                    message = CompressUtils.Decompress(message);
                }

                return(message);
            }
            catch (Exception ex)
            {
                throw new CryptoDecryptionException("Could not decrypt cipher, probably because the key is wrong.", ex);
            }
        }
Пример #2
0
        /// <summary>
        /// Decrypts a cipher, which was encrypted with <see cref="Encrypt(byte[],string,KeyDerivationCostType,ICryptoRandomSource,string,string)"/>.
        /// </summary>
        /// <param name="packedCipher">The cipher containing a header with the
        /// necessary parameters for decryption.</param>
        /// <param name="password">The password which was used for encryption.</param>
        /// <returns>The plain text message.</returns>
        public byte[] Decrypt(byte[] packedCipher, string password)
        {
            if (packedCipher == null)
            {
                throw new ArgumentNullException("packedCipher");
            }

            CryptoHeader header;

            byte[] cipher;
            CryptoHeaderPacker.UnpackHeaderAndCipher(packedCipher, out header, out cipher);
            if (_appName != header.AppName)
            {
                throw new CryptoExceptionInvalidCipherFormat();
            }

            ISymmetricEncryptionAlgorithm decryptor = new SymmetricEncryptionAlgorithmFactory().CreateAlgorithm(header.AlgorithmName);
            IKeyDerivationFunction        kdf       = new KeyDerivationFactory().CreateKdf(header.KdfName);

            try
            {
                int    cost    = int.Parse(header.Cost);
                byte[] key     = kdf.DeriveKeyFromPassword(password, decryptor.ExpectedKeySize, header.Salt, cost);
                byte[] message = decryptor.Decrypt(cipher, key, header.Nonce);
                return(message);
            }
            catch (Exception ex)
            {
                throw new CryptoDecryptionException("Could not decrypt cipher, probably because the key is wrong.", ex);
            }
        }
Пример #3
0
        /// <inheritdoc/>
        public byte[] Encrypt(
            byte[] message,
            SecureString password,
            KeyDerivationCostType costType,
            string encryptorName,
            string kdfName     = Pbkdf2.CryptoKdfName,
            string compression = null)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            ValidatePassword(password);
            if (_randomSource == null)
            {
                throw new ArgumentNullException(nameof(_randomSource));
            }
            if (string.IsNullOrWhiteSpace(encryptorName))
            {
                encryptorName = BouncyCastleXChaCha20.CryptoAlgorithmName;
            }
            if (string.IsNullOrWhiteSpace(kdfName))
            {
                encryptorName = Pbkdf2.CryptoKdfName;
            }
            ISymmetricEncryptionAlgorithm encryptor = new SymmetricEncryptionAlgorithmFactory().CreateAlgorithm(encryptorName);
            IKeyDerivationFunction        kdf       = new KeyDerivationFactory().CreateKdf(kdfName);

            // Prepare header
            CryptoHeader header = new CryptoHeader();

            header.PackageName   = PackageName;
            header.AlgorithmName = encryptor.Name;
            header.Nonce         = _randomSource.GetRandomBytes(encryptor.ExpectedNonceSize);
            header.KdfName       = kdf.Name;
            header.Salt          = _randomSource.GetRandomBytes(kdf.ExpectedSaltSizeBytes);
            int cost = kdf.RecommendedCost(costType);

            header.Cost        = cost.ToString();
            header.Compression = compression;

            try
            {
                if (string.Equals(CompressionGzip, header.Compression, StringComparison.InvariantCultureIgnoreCase))
                {
                    message = CompressUtils.Compress(message);
                }

                byte[] key    = kdf.DeriveKeyFromPassword(password, encryptor.ExpectedKeySize, header.Salt, cost);
                byte[] cipher = encryptor.Encrypt(message, key, header.Nonce);
                return(CryptoHeaderPacker.PackHeaderAndCypher(header, cipher));
            }
            catch (Exception ex)
            {
                throw new CryptoException("An unexpected error occured, while encrypting the message.", ex);
            }
        }
Пример #4
0
        /// <summary>
        /// Encrypts a message with a user password, and adds a header containing all information
        /// necessary for the decryption (algorithm, nonce, salt, ...).
        /// </summary>
        /// <param name="message">Plain text message to encrypt.</param>
        /// <param name="password">Password to use for encryption, minimum length is 7 characters.</param>
        /// <param name="costType">The cost type to use for encryption.</param>
        /// <param name="randomSource">A cryptographically safe random source.</param>
        /// <param name="encryptorName">The name of an encryption algorithm which shall be used to
        /// do the encryption.</param>
        /// <param name="kdfName">The name of a key derivation function, which can convert the
        /// password to a key.</param>
        /// <returns>A binary array containing the cipher.</returns>
        public byte[] Encrypt(
            byte[] message,
            string password,
            KeyDerivationCostType costType,
            ICryptoRandomSource randomSource,
            string encryptorName,
            string kdfName = Pbkdf2.CryptoKdfName)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            ValidatePassword(password);
            if (randomSource == null)
            {
                throw new ArgumentNullException("randomSource");
            }
            if (string.IsNullOrWhiteSpace(encryptorName))
            {
                encryptorName = BouncyCastleAesGcm.CryptoAlgorithmName;
            }
            if (string.IsNullOrWhiteSpace(kdfName))
            {
                encryptorName = Pbkdf2.CryptoKdfName;
            }
            ISymmetricEncryptionAlgorithm encryptor = new SymmetricEncryptionAlgorithmFactory().CreateAlgorithm(encryptorName);
            IKeyDerivationFunction        kdf       = new KeyDerivationFactory().CreateKdf(kdfName);

            // Prepare header
            CryptoHeader header = new CryptoHeader();

            header.AppName       = _appName;
            header.AlgorithmName = encryptor.Name;
            header.Nonce         = randomSource.GetRandomBytes(encryptor.ExpectedNonceSize);
            header.KdfName       = kdf.Name;
            header.Salt          = randomSource.GetRandomBytes(kdf.ExpectedSaltSizeBytes);
            int cost = kdf.RecommendedCost(costType);

            header.Cost = cost.ToString();

            try
            {
                byte[] key    = kdf.DeriveKeyFromPassword(password, encryptor.ExpectedKeySize, header.Salt, cost);
                byte[] cipher = encryptor.Encrypt(message, key, header.Nonce);
                return(CryptoHeaderPacker.PackHeaderAndCypher(header, cipher));
            }
            catch (Exception ex)
            {
                throw new CryptoException("An unexpected error occured, while encrypting the message.", ex);
            }
        }