public void TestEmptyMemoryStream() { byte[] input = SecureRandomizer.GetRandomBytes(0); byte[] encrypted; using (var inputStream = new MemoryStream(input)) { using (var outputStream = new MemoryStream()) { _symmetric.EncryptStream(inputStream, outputStream, _key); encrypted = outputStream.ToArray(); } } Assert.IsTrue(encrypted.Length >= 32, "encrypted.Length"); byte[] decrypted; using (var inputStream = new MemoryStream(encrypted)) { using (var outputStream = new MemoryStream()) { _symmetric.DecryptStream(inputStream, outputStream, _key); decrypted = outputStream.ToArray(); } } Assert.AreEqual(0, decrypted.Length, "decrypted.Length"); }
public void TestMemoryStream() { byte[] input = SecureRandomizer.GetRandomBytes(15000); byte[] encrypted; using (var inputStream = new MemoryStream(input)) { using (var outputStream = new MemoryStream()) { _symmetric.EncryptStream(inputStream, outputStream, _key); encrypted = outputStream.ToArray(); } } Assert.IsTrue(encrypted.Length > 15000, "encrypted.Length"); byte[] decrypted; using (var inputStream = new MemoryStream(encrypted)) { using (var outputStream = new MemoryStream()) { _symmetric.DecryptStream(inputStream, outputStream, _key); decrypted = outputStream.ToArray(); } } Assert.IsTrue(input.SequenceEqual(decrypted), "input does not match decrypted"); }
public void TestThreadSafety() { var hashset = new HashSet <string>(); ThreadStart action = () => { for (int i = 0; i < 50000; ++i) { byte[] bytes = SecureRandomizer.GetRandomBytes(32); lock (hashset) { hashset.Add(Convert.ToBase64String(bytes)); } } }; var threads = new Thread[10]; for (int i = 0; i < threads.Length; ++i) { var thread = new Thread(action); threads[i] = thread; thread.Start(); } foreach (var t in threads) { while (t.IsAlive) { } } Assert.AreEqual(500000, hashset.Count, "Number of unique arrays"); }
public void TestNoMoreThan16OfTheSameByte() { var bytes = new byte[32]; for (int i = 0; i < 500000; ++i) { bytes = SecureRandomizer.GetRandomBytes(bytes.Length); var countByValue = new Dictionary <byte, int>(); foreach (byte b in bytes) { if (!countByValue.ContainsKey(b)) { countByValue[b] = 1; } else { ++countByValue[b]; } } foreach (var kvp in countByValue) { if (kvp.Value >= 16) { Assert.Fail("Value {0} appeared 16 or more times", kvp.Key); } } } }
public void TestAllPositionsContainsAllBytes() { var byteValuesByPosition = new HashSet <byte> [32]; for (int i = 0; i < 32; ++i) { byteValuesByPosition[i] = new HashSet <byte>(); } var bytes = new byte[32]; for (int i = 0; i < 500000; ++i) { bytes = SecureRandomizer.GetRandomBytes(bytes.Length); for (int j = 0; j < 32; ++j) { byteValuesByPosition[j].Add(bytes[j]); } } for (int i = 0; i < 32; ++i) { Assert.AreEqual(256, byteValuesByPosition[i].Count, "Position {0} does not contain all 256 possible values", i); } }
public void TestBytesLarge() { byte[] input = SecureRandomizer.GetRandomBytes(250000); byte[] encrypted = _symmetric.EncryptBytes(input, _key); Assert.IsTrue(encrypted.Length > 250000, "encrypted.Length"); byte[] decrypted = _symmetric.DecryptBytes(encrypted, _key); Assert.IsTrue(input.SequenceEqual(decrypted), "input does not match decrypted"); }
public void TestBytesMedium() { byte[] input = SecureRandomizer.GetRandomBytes(3200); byte[] encrypted = _symmetric.EncryptBytes(input, _passphrase); Assert.IsTrue(encrypted.Length > 3200, "encrypted.Length"); byte[] decrypted = _symmetric.DecryptBytes(encrypted, _passphrase); Assert.IsTrue(input.SequenceEqual(decrypted), "input does not match decrypted"); }
public void TestBytesSmall() { byte[] input = SecureRandomizer.GetRandomBytes(100); byte[] encrypted = _symmetric.EncryptBytes(input, _key); Assert.IsTrue(encrypted.Length > 100, "encrypted.Length"); byte[] decrypted = _symmetric.DecryptBytes(encrypted, _key); Assert.IsTrue(input.SequenceEqual(decrypted), string.Format("{0} | {1}", Convert.ToBase64String(input), Convert.ToBase64String(decrypted))); }
public void TestUnicodeString() { string input = Convert.ToBase64String(SecureRandomizer.GetRandomBytes(100)) + "\u01e2\u01f0\u020e\u0229"; string encrypted = _symmetric.EncryptString(input, _key).AsBase64(); Assert.IsTrue(encrypted.Length > 100, "encrypted.Length"); string decrypted = _symmetric.DecryptBase64(encrypted, _key).AsString(); Assert.AreEqual(input, decrypted, string.Format("{0} | {1}", input, decrypted)); }
public void TestSameInputProducesDifferentOutput() { var inputBytes = SecureRandomizer.GetRandomBytes(1024); var encryptedAsBase64 = new HashSet <string>(); for (int i = 0; i < 20; ++i) { encryptedAsBase64.Add(Convert.ToBase64String(_symmetric.EncryptBytes(inputBytes, _key))); } Assert.AreEqual(20, encryptedAsBase64.Count, "Should be 100 distinct values"); }
public void TestFileStream() { string originalFileName = GetTempFileName(); using (var tempFileStream = File.Create(originalFileName)) { for (int i = 0; i < 100; ++i) { tempFileStream.Write(SecureRandomizer.GetRandomBytes(1024), 0, 1024); } } string encryptedFileName = GetTempFileName(); using (var inputStream = File.Open(originalFileName, FileMode.Open, FileAccess.Read, FileShare.None)) { using (var outputStream = File.Create(encryptedFileName)) { _symmetric.EncryptStream(inputStream, outputStream, _key); } } string decryptedFileName = GetTempFileName(); using (var inputStream = File.Open(encryptedFileName, FileMode.Open, FileAccess.Read, FileShare.None)) { using (var outputStream = File.Create(decryptedFileName)) { _symmetric.DecryptStream(inputStream, outputStream, _key); } } var originalFile = new FileInfo(originalFileName); var encryptedFile = new FileInfo(encryptedFileName); var decryptedFile = new FileInfo(decryptedFileName); Assert.IsTrue(encryptedFile.Length > originalFile.Length, "Encrypted file should be larger than original."); Assert.AreEqual(originalFile.Length, decryptedFile.Length, "Original file should be the same size as original."); var buffer1 = new byte[8096]; var buffer2 = new byte[8096]; using (var originalStream = File.Open(originalFileName, FileMode.Open, FileAccess.Read, FileShare.None)) { using (var decryptedStream = File.Open(decryptedFileName, FileMode.Open, FileAccess.Read, FileShare.None)) { while ((originalStream.Read(buffer1, 0, buffer1.Length) > 0)) { decryptedStream.Read(buffer2, 0, buffer2.Length); Assert.IsTrue(buffer1.SequenceEqual(buffer2), "Files do not match."); } } } }
public void TestUnevenArraySize() { var hashset = new HashSet <string>(); for (int i = 0; i < 10000; ++i) { hashset.Add(Convert.ToBase64String(SecureRandomizer.GetRandomBytes(1234))); } Assert.AreEqual(10000, hashset.Count, "Number of unique arrays"); }
public void TestTooLargeArrayStillWorks() { var hashset = new HashSet <string>(); for (int i = 0; i < 20; ++i) { hashset.Add(Convert.ToBase64String(SecureRandomizer.GetRandomBytes(100000))); } Assert.AreEqual(20, hashset.Count, "Number of unique arrays"); }
/// <summary> /// Encrypts a message using 256-bit AES CBC encryption with HMACSHA256. /// </summary> /// <param name="input">The plaintext input.</param> /// <param name="cryptoKey">The 32-byte crypto key.</param> /// <param name="authKey">The 32-byte auth key.</param> /// <returns>The encrypted message. The first 16 bytes are the IV, followed by /// the ciphertext, then the last 32 bytes are the HMAC tag.</returns> public override EncryptionResults EncryptBytes(byte[] input, byte[] cryptoKey, byte[] authKey) { if (input == null) { return(new EncryptionResults(null)); } ValidateKeys(cryptoKey, authKey); byte[] iv = SecureRandomizer.GetRandomBytes(IV_SIZE_BYTES); byte[] cipherText; using (var algo = new AesCryptoServiceProvider()) { algo.Mode = CipherMode.CBC; using (var encryptor = algo.CreateEncryptor(cryptoKey, iv)) { using (var inputStream = new MemoryStream(input)) { using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { using (var binaryWriter = new BinaryWriter(cryptoStream)) { var buffer = new byte[Defaults.BUFFER_SIZE]; int count; while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0) { binaryWriter.Write(buffer, 0, count); } } } cipherText = memoryStream.ToArray(); } } } } using (var hashAlgo = new HMACSHA256(authKey)) { using (var memoryStream = new MemoryStream()) { using (var binaryWriter = new BinaryWriter(memoryStream)) { binaryWriter.Write(iv); binaryWriter.Write(cipherText); binaryWriter.Flush(); var tag = hashAlgo.ComputeHash(memoryStream.ToArray()); binaryWriter.Write(tag); } return(new EncryptionResults(memoryStream.ToArray())); } } }
public void TestAllArraysUnique() { var hashset = new HashSet <string>(); var bytes = new byte[32]; for (int i = 0; i < 500000; ++i) { bytes = SecureRandomizer.GetRandomBytes(bytes.Length); hashset.Add(Convert.ToBase64String(bytes)); } Assert.AreEqual(500000, hashset.Count, "Number of unique arrays"); }
public void TestSpeed() { var sw = new Stopwatch(); sw.Start(); var bytes = new byte[32]; for (int i = 0; i < 100000; ++i) { bytes = SecureRandomizer.GetRandomBytes(bytes.Length); } Assert.IsTrue(sw.ElapsedMilliseconds < 2000, "Should have taken less than two seconds"); }
public void TestNotEmptyArray() { var bytes = new byte[32]; for (int i = 0; i < 500000; ++i) { bytes = SecureRandomizer.GetRandomBytes(bytes.Length); bool anyNotZero = false; foreach (var b in bytes) { anyNotZero |= (b != 0); } Assert.IsTrue(anyNotZero, "Array is full of zeros"); } }
public void TestUnicodeString(Symmetric_AES.KeySize keySize) { var key = Symmetric_AES.GenerateRandomKey(keySize); string input = Convert.ToBase64String(SecureRandomizer.GetRandomBytes(100)) + "\u01e2\u01f0\u020e\u0229"; byte[] encrypted; string decrypted; using (var algorithm = new Symmetric_AES_CBC()) { encrypted = algorithm.EncryptString(input, key); } using (var algorithm = new Symmetric_AES_CBC()) { Assert.IsTrue(encrypted.Length > 100, "encrypted.Length"); decrypted = algorithm.DecryptBytes(encrypted, key).AsString(); } Assert.AreEqual(input, decrypted, string.Format("{0} | {1}", input, decrypted)); }
public void TestUnicodeString() { string passphrase = Guid.NewGuid().ToString("N"); string input = Convert.ToBase64String(SecureRandomizer.GetRandomBytes(100)) + "\u01e2\u01f0\u020e\u0229"; byte[] encrypted; string decrypted; using (var algorithm = new Symmetric_AES_CBC_Passphrase()) { encrypted = algorithm.EncryptString(input, passphrase); } using (var algorithm = new Symmetric_AES_CBC_Passphrase()) { Assert.IsTrue(encrypted.Length > 100, "encrypted.Length"); decrypted = algorithm.DecryptBytes(encrypted, passphrase).AsString(); } Assert.AreEqual(input, decrypted, string.Format("{0} | {1}", input, decrypted)); }
public void TestUnicodeString() { byte[] cryptoKey, authKey; SymmetricAuthenticated_AES_HMACSHA256.GenerateKeys(out cryptoKey, out authKey); string input = Convert.ToBase64String(SecureRandomizer.GetRandomBytes(100)) + "\u01e2\u01f0\u020e\u0229"; byte[] encrypted; string decrypted; using (var algorithm = new SymmetricAuthenticated_AES_HMACSHA256()) { encrypted = algorithm.EncryptString(input, cryptoKey, authKey); } using (var algorithm = new SymmetricAuthenticated_AES_HMACSHA256()) { Assert.IsTrue(encrypted.Length > 100, "encrypted.Length"); decrypted = algorithm.DecryptBytes(encrypted, cryptoKey, authKey).AsString(); } Assert.AreEqual(input, decrypted, string.Format("{0} | {1}", input, decrypted)); }
/// <summary> /// Encrypts a stream using a key derived from the passphrase. /// </summary> /// <param name="inputStream">The stream to encrypt.</param> /// <param name="outputStream">The encrypted stream.</param> /// <param name="passphrase">The passphrase from which the encryption key is derived.</param> public override void EncryptStream(Stream inputStream, Stream outputStream, string passphrase) { if (inputStream == null || outputStream == null) { throw new ArgumentNullException(); } byte[] salt; byte[] key = PBKDF2.ComputeHash(passphrase, out salt, saltNumBytes: SALT_SIZE_BYTES, passwordNumBytes: KEY_SIZE_BYTES); byte[] iv = null; int ivLength = GetIVSizeBytes(); if (ivLength != 0) { iv = SecureRandomizer.GetRandomBytes(ivLength); outputStream.Write(iv, 0, iv.Length); } outputStream.Write(salt, 0, salt.Length); using (var algo = new AesCryptoServiceProvider()) { algo.Mode = GetCipherMode(); using (var encryptor = algo.CreateEncryptor(key, iv)) { using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) { using (var binaryWriter = new BinaryWriter(cryptoStream)) { var buffer = new byte[Defaults.BUFFER_SIZE]; int count; while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0) { binaryWriter.Write(buffer, 0, count); } } } } } }
/// <summary> /// Encrypts a stream using a given key. /// </summary> /// <param name="inputStream">The stream to encrypt.</param> /// <param name="outputStream">The encrypted stream.</param> /// <param name="key">The key to use for encryption.</param> public override void EncryptStream(Stream inputStream, Stream outputStream, byte[] key) { ValidateKey(key); if (inputStream == null || outputStream == null) { throw new ArgumentNullException(); } byte[] iv = null; int ivLength = GetIVSizeBytes(); if (ivLength != 0) { iv = SecureRandomizer.GetRandomBytes(ivLength); outputStream.Write(iv, 0, iv.Length); } using (var algo = new AesCryptoServiceProvider()) { algo.Mode = GetCipherMode(); using (var encryptor = algo.CreateEncryptor(key, iv)) { using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) { using (var binaryWriter = new BinaryWriter(cryptoStream)) { var buffer = new byte[Defaults.BUFFER_SIZE]; int count; while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0) { binaryWriter.Write(buffer, 0, count); } } } } } }
public void TestThreadSafetyParallel() { var hashset = new HashSet <string>(); Action <int> action = idx => { for (int i = 0; i < 50000; ++i) { byte[] bytes = SecureRandomizer.GetRandomBytes(32); lock (hashset) { hashset.Add(Convert.ToBase64String(bytes)); } } }; var parallelLoopResult = Parallel.For(0, 10, action); while (!parallelLoopResult.IsCompleted) { } Assert.AreEqual(500000, hashset.Count, "Number of unique arrays"); }
/// <summary> /// Generates a random key. /// </summary> /// <param name="keySize">The key size to use. Default is 32.</param> /// <returns>A random byte array which can be used as a key for AES encryption.</returns> public static byte[] GenerateRandomKey(KeySize keySize = KeySize.KeySize256Bit) { return(SecureRandomizer.GetRandomBytes((int)keySize)); }
/// <summary> /// Generates two random 32-byte arrays, for use with this class's encryption methods. /// </summary> /// <param name="cryptoKey">The 32-byte crypto key.</param> /// <param name="authKey">The 32-byte auth key.</param> public static void GenerateKeys(out byte[] cryptoKey, out byte[] authKey) { cryptoKey = SecureRandomizer.GetRandomBytes(KEY_SIZE_BYTES); authKey = SecureRandomizer.GetRandomBytes(KEY_SIZE_BYTES); }
public void SetUp() { _symmetric = new Symmetric_AES_CBC(); _key = SecureRandomizer.GetRandomBytes(32); }