/// <summary> /// For Unit testing: Decrypt a stream using the supplied password with changing (small) buffer sizes /// </summary> /// <param name="password">The password to decrypt with</param> /// <param name="input">The input stream</param> /// <param name="output">The output stream</param> private static void UnitStreamDecrypt(string password, Stream input, Stream output, int bufferSizeSelect, int useThreads) { var r = new Random(); var partBufs = Math.Min(bufferSizeSelect, 1024); var buffers = new byte[partBufs][]; for (int bs = 1; bs < partBufs; bs++) { buffers[bs] = new byte[bs]; } buffers[0] = new byte[bufferSizeSelect]; int a; var c = new SharpAESCrypt(password, input, OperationMode.Decrypt, true); c.MaxCryptoThreads = useThreads; do { var bufLen = r.Next(bufferSizeSelect) + 1; var useBuf = bufLen < partBufs ? buffers[bufLen] : buffers[0]; a = c.Read(useBuf, 0, bufLen); output.Write(useBuf, 0, a); } while (a != 0); }
private static Stream Process(Stream stream, string encryptionKey, SharpAESCrypt.OperationMode mode) { var buffer = new MemoryStream(); switch (mode) { case SharpAESCrypt.OperationMode.Encrypt: SharpAESCrypt.SharpAESCrypt.Encrypt(encryptionKey, stream, buffer); break; case SharpAESCrypt.OperationMode.Decrypt: SharpAESCrypt.SharpAESCrypt.Decrypt(encryptionKey, stream, buffer); break; } stream.Close(); stream = buffer; stream.Seek(0, SeekOrigin.Begin); return stream; }
private Zone LoadZoneFromFile([NotNull] string zoneFileName) { Assert.ArgumentNotNullOrWhiteSpace(zoneFileName, "zoneFileName"); if (File.Exists(Path.Combine(GetZonesFolder(), zoneFileName))) { using (var inStream = File.OpenRead(Path.Combine(GetZonesFolder(), zoneFileName))) { var aesStream = new SharpAESCrypt("A5Ub5T7j5cYg40v", inStream, OperationMode.Decrypt); using (var streamReader = new StreamReader(aesStream, Encoding.GetEncoding(20866))) { return((Zone)_zoneSerializer.Deserialize(streamReader)); } } } return(null); }
/// <summary> /// Helper function to perform a single test. /// </summary> /// <param name="message">A message printed to the console</param> /// <param name="input">The stream to test with</param> private static bool Unittest(string message, MemoryStream input, int useRndBufSize, bool useNonSeekable, int useThreads) { Console.Write(message); const string PASSWORD_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#¤%&/()=?`*'^¨-_.:,;<>|"; const int MIN_LEN = 1; const int MAX_LEN = 25; try { var rnd = new Random(); var pwdchars = new char[rnd.Next(MIN_LEN, MAX_LEN)]; for (int i = 0; i < pwdchars.Length; i++) { pwdchars[i] = PASSWORD_CHARS[rnd.Next(0, PASSWORD_CHARS.Length)]; } input.Position = 0; using (var enc = new MemoryStream()) using (var dec = new MemoryStream()) using (var nenc = useNonSeekable ? (Stream) new NonSeekableStream(enc) : (Stream)enc) using (var ndec = useNonSeekable ? (Stream) new NonSeekableStream(dec) : (Stream)dec) { SharpAESCrypt.Encrypt(new string(pwdchars), input, nenc, maxThreads: useThreads); // 1st pass: test with wrong password if version > 0 enc.Position = 0; try { if (SharpAESCrypt.DefaultFileVersion > 0) { SharpAESCrypt.Decrypt("!WRONG_PASSWORD!", nenc, dec, maxThreads: useThreads); throw new InvalidOperationException("Wrong password not detected."); } } catch (SharpAESCrypt.WrongPasswordException) { } // 2nd Pass: data ok enc.Position = 0; if (useRndBufSize <= 0) { SharpAESCrypt.Decrypt(new string(pwdchars), nenc, dec, maxThreads: useThreads); } else { UnitStreamDecrypt(new string(pwdchars), nenc, dec, useRndBufSize, useThreads); } dec.Position = 0; input.Position = 0; if (dec.Length != input.Length) { throw new Exception(string.Format("Length differ {0} vs {1}", dec.Length, input.Length)); } for (int i = 0; i < dec.Length; i++) { if (dec.ReadByte() != input.ReadByte()) { throw new Exception(string.Format("Streams differ at byte {0}", i)); } } // 3rd pass: Change hash at end of file, and expect HashMismatch int changeHashAt = rnd.Next(SharpAESCrypt.HASH_SIZE); enc.Position = enc.Length - changeHashAt - 1; int b = enc.ReadByte(); enc.Position = enc.Length - changeHashAt - 1; enc.WriteByte((byte)(~b & 0xff)); enc.Position = 0; try { if (useRndBufSize <= 0) { SharpAESCrypt.Decrypt(new string(pwdchars), nenc, dec, maxThreads: useThreads); } else { UnitStreamDecrypt(new string(pwdchars), nenc, dec, useRndBufSize, useThreads); } throw new InvalidDataException("Mismatching HMAC not detected."); } catch (SharpAESCrypt.HashMismatchException) { } } } catch (Exception ex) { Console.WriteLine("FAILED: " + ex.Message); return(false); } Console.WriteLine("OK!"); return(true); }
public void TestTruncatedDataDecryption() { var rnd = new Random(); var failed = 0; int initialThreadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count; int maxByteCount = 1 << 21; // must be larger than maximum test size below. //Test each supported version with variable buffer lengths for (byte v = 0; v <= SharpAESCrypt.MAX_FILE_VERSION; v++) { SharpAESCrypt.DefaultFileVersion = v; using (MemoryStream ms = new MemoryStream()) { byte[] tmp = new byte[maxByteCount]; rnd.NextBytes(tmp); string pwd = new string(Enumerable.Repeat('a', 10).Select(c => (char)(c + rnd.Next(26))).ToArray()); SharpAESCrypt.Encrypt(pwd, new MemoryStream(tmp), ms, 1); int approxHeaderSize = ((int)ms.Length) - tmp.Length - SharpAESCrypt.HASH_SIZE; // Test at boundaries and around the block/keysize margins int[] bounds = new int[] { 0, 1 << 6, 1 << 8, 1 << 10, 1 << 12, 1 << 14, 1 << 16, 1 << 20 }; Array.Reverse(bounds); foreach (int bound in bounds) { int low = Math.Max(-approxHeaderSize, bound - 6 * SharpAESCrypt.BLOCK_SIZE - 1); int high = Math.Min((int)ms.Length, bound + (6 * SharpAESCrypt.BLOCK_SIZE + 1)); for (int i = approxHeaderSize + high; i >= approxHeaderSize + low; i--) { ms.SetLength(i); // truncate input stream! for (int useThreads = 1; useThreads <= 4; useThreads++) { ms.Position = 0; // Run the test in separate thread to detect races / deadlocks Task <bool> runTest = Task <bool> .Run(() => { Console.Write("Testing version {0} with truncated stream length = {1}, using {2} Thread(s) and variable buffer sizes => ", v, ms.Length, useThreads); try { UnitStreamDecrypt(pwd, ms, new MemoryStream(tmp), 256, useThreads); Console.WriteLine("FAILED: Truncated stream accepted."); return(false); } catch { Console.WriteLine("OK!"); return(true); } }); runTest.Wait(TimeSpan.FromSeconds(300)); // we give a single test a timeout of 5 minutes. This should well be enough! if (!runTest.IsCompleted) { Console.WriteLine("FAILED: A test timed out. There must be a race."); throw new Exception("A test timed out. There must be a race."); } else if (!runTest.Result) { failed++; } // Check for number of threads: a systematic rise would signal that the sync does not work! // We have to allow a lot of threads for the test framework, but it should not go far above 30 normally. int currentThreadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count; if (currentThreadCount > initialThreadCount + 50) // too many threads. This shouldn't be! { Console.WriteLine("FAILED: Allowed thread count threshold reached."); throw new Exception("Allowed thread count threshold reached. Thread synchronization might not work. Also: check test framework!"); } } } } } } if (failed != 0) { throw new Exception(string.Format("Failed with {0} tests", failed)); } }
/// <summary> /// Encrypts a stream using the supplied password /// </summary> /// <param name="password">The password to decrypt with</param> /// <param name="input">The stream with unencrypted data</param> /// <param name="output">The encrypted output stream</param> public static void Encrypt(string password, Stream input, Stream output) { int a; byte[] buffer = new byte[1024 * 4]; SharpAESCrypt c = new SharpAESCrypt(password, output, OperationMode.Encrypt); while ((a = input.Read(buffer, 0, buffer.Length)) != 0) c.Write(buffer, 0, a); c.FlushFinalBlock(); }
/// <summary> /// Decrypts a stream using the supplied password /// </summary> /// <param name="password">The password to encrypt with</param> /// <param name="input">The stream with encrypted data</param> /// <param name="output">The unencrypted output stream</param> public static void Decrypt(string password, Stream input, Stream output) { int a; byte[] buffer = new byte[1024 * 4]; SharpAESCrypt c = new SharpAESCrypt(password, input, OperationMode.Decrypt); while ((a = c.Read(buffer, 0, buffer.Length)) != 0) output.Write(buffer, 0, a); }