private void Initialize() { rijndael = new RijndaelEngine(); aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE]; int rawLength = 2 * password.Length; byte[] rawPassword = new byte[rawLength + 8]; byte[] passwordBytes = Encoding.UTF8.GetBytes(password); for (int i = 0; i < password.Length; i++) { rawPassword[i * 2] = passwordBytes[i]; rawPassword[i * 2 + 1] = 0; } for (int i = 0; i < salt.Length; i++) { rawPassword[i + rawLength] = salt[i]; } const int noOfRounds = (1 << 18); IList <byte> bytes = new List <byte>(); byte[] digest; //TODO slow code below, find ways to optimize for (int i = 0; i < noOfRounds; i++) { bytes.AddRange(rawPassword); bytes.AddRange(new[] { (byte)i, (byte)(i >> 8), (byte)(i >> CRYPTO_BLOCK_SIZE) }); if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0) { digest = ComputeHash(bytes.ToArray()); aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19]; } } digest = ComputeHash(bytes.ToArray()); //slow code ends byte[] aesKey = new byte[CRYPTO_BLOCK_SIZE]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { aesKey[i * 4 + j] = (byte) (((digest[i * 4] * 0x1000000) & 0xff000000 | (uint)((digest[i * 4 + 1] * 0x10000) & 0xff0000) | (uint)((digest[i * 4 + 2] * 0x100) & 0xff00) | (uint)(digest[i * 4 + 3] & 0xff)) >> (j * 8)); } } rijndael.Init(false, new KeyParameter(aesKey)); }
private void Initialize() { _rijndael = new RijndaelEngine(); _aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE]; int rawLength = 2 * _password.Length; byte[] rawPassword = new byte[rawLength + 8]; byte[] passwordBytes = Encoding.UTF8.GetBytes(_password); for (int i = 0; i < _password.Length; i++) { rawPassword[i * 2] = passwordBytes[i]; rawPassword[i * 2 + 1] = 0; } for (int i = 0; i < _salt.Length; i++) { rawPassword[i + rawLength] = _salt[i]; } const int noOfRounds = (1 << 18); const int iblock = 3; byte[] digest; byte[] data = new byte[(rawPassword.Length + iblock) * noOfRounds]; //TODO slow code below, find ways to optimize for (int i = 0; i < noOfRounds; i++) { rawPassword.CopyTo(data, i * (rawPassword.Length + iblock)); data[i * (rawPassword.Length + iblock) + rawPassword.Length + 0] = (byte)i; data[i * (rawPassword.Length + iblock) + rawPassword.Length + 1] = (byte)(i >> 8); data[i * (rawPassword.Length + iblock) + rawPassword.Length + 2] = (byte)(i >> CRYPTO_BLOCK_SIZE); if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0) { digest = SHA1.Create().ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock)); _aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19]; } } digest = SHA1.Create().ComputeHash(data); //slow code ends byte[] aesKey = new byte[CRYPTO_BLOCK_SIZE]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { aesKey[i * 4 + j] = (byte) (((digest[i * 4] * 0x1000000) & 0xff000000 | (uint)((digest[i * 4 + 1] * 0x10000) & 0xff0000) | (uint)((digest[i * 4 + 2] * 0x100) & 0xff00) | (uint)(digest[i * 4 + 3] & 0xff)) >> (j * 8)); } } _rijndael.Init(false, new KeyParameter(aesKey)); }
/// <summary> /// Encrypted the data. /// </summary> /// <param name="data">The data to encrypted.</param> /// <param name="passphrase">The passphrase key used to mask the data.</param> /// <param name="blocksize">The blocksize in bits, must be 128, 192, or 256.</param> /// <returns>The encrypted data; else null.</returns> /// <remarks>The passphrase must be between 0 and 32 bytes in length.</remarks> public byte[] Encrypt(byte[] data, string passphrase, int blocksize = 256) { // Create the key length. byte[] key = GeneratePasswordBytes(passphrase); if (!VerifyKeySize(key)) { return(null); } // Create the key parameters. Key.Crypto.Parameters.KeyParameter keyParameter = new KeyParameter(key); // Initialise the cryptography engine. Key.Crypto.Engines.RijndaelEngine rijndael = new RijndaelEngine(blocksize); rijndael.Init(true, keyParameter); int dataLength = data.Length; int blockSize = rijndael.GetBlockSize(); int modBlockSize = dataLength % blockSize; int blockCount = dataLength / blockSize; // If there is a remained then add en extra block count. if ((modBlockSize) > 0) { // Add one extra block. blockCount++; } // Encrypted data store. byte[] encryptedData = new byte[blockCount * blockSize]; byte[] decryptedData = new byte[blockCount * blockSize]; // Copy the decrypted data. for (int j = 0; j < dataLength; j++) { // Assign the data. decryptedData[j] = data[j]; } // For each block size in the the data. for (int i = 0; i < blockCount; i++) { // Encrypt the block. rijndael.ProcessBlock(decryptedData, (i * blockSize), encryptedData, (i * blockSize)); } // Return the encrypted data. return(encryptedData); }