예제 #1
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);
            }
        }
예제 #2
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);
            }
        }
예제 #3
0
        /// <summary>
        /// Generates a random string of a given length, using the random source of
        /// the operating system.The string contains only safe characters of this
        /// alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
        /// </summary>
        /// <param name="length">Number of characters the string should have.</param>
        /// <param name="randomSource">Random generator.</param>
        /// <returns>New randomly generated string.</returns>
        public static string GenerateRandomBase62String(int length, ICryptoRandomSource randomSource)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            StringBuilder result          = new StringBuilder();
            int           remainingLength = length;

            do
            {
                // We take advantage of the fast base64 encoding
                int    binaryLength = (int)((remainingLength * 3.0 / 4.0) + 1.0);
                byte[] randomBytes  = randomSource.GetRandomBytes(binaryLength);
                string base64String = Convert.ToBase64String(randomBytes);

                // Remove invalid characters
                result.Append(base64String);
                result.Replace("+", string.Empty);
                result.Replace("/", string.Empty);
                result.Replace("=", string.Empty);

                // If too many characters have been removed, we repeat the procedure
                remainingLength = length - result.Length;
            }while (remainingLength > 0);

            result.Length = length;
            return(result.ToString());
        }
예제 #4
0
        public void MeasureTime()
        {
            IKeyDerivationFunction kdf          = new Pbkdf2();
            ICryptoRandomSource    randomSource = CommonMocksAndStubs.CryptoRandomService();
            SecureString           password     = CryptoUtils.StringToSecureString("candidate");

            byte[] salt       = randomSource.GetRandomBytes(kdf.ExpectedSaltSizeBytes);
            int    iterations = 10000;

            Stopwatch watch = new Stopwatch();

            watch.Start();
            kdf.DeriveKeyFromPassword(password, 32, salt, iterations);
            watch.Stop();
            Console.WriteLine("Pbkdf2 time for {0} iterations: {1}ms", iterations, watch.ElapsedMilliseconds);
        }