#region copyright // ------------------------------------------------------ // Copyright (C) Dmitriy Yukhanov [https://codestage.net] // ------------------------------------------------------ #endregion namespace CodeStage.AntiCheat.Utils { using System; using System.IO; using System.Security.Cryptography; internal static class CryptoUtils { private const int BufferSize = 81920; private const byte Iterations = 10; private const byte AesSaltLengthBytes = 16; private const byte AesKeyLengthBytes = 16; private const byte Rc2SaltLengthBytes = 8; private const byte Rc2KeyLengthBytes = 7; public static void EncryptAes(Stream input, Stream output, byte[] password) { EncryptInternal(input, output, password, AesKeyLengthBytes); } public static void DecryptAes(Stream input, Stream output, byte[] password) { DecryptInternal(input, output, password, AesKeyLengthBytes, AesSaltLengthBytes); } public static void EncryptRc2(Stream input, Stream output, byte[] password) { EncryptInternal(input, output, password, Rc2KeyLengthBytes); } public static void DecryptRc2(Stream input, Stream output, byte[] password) { DecryptInternal(input, output, password, Rc2KeyLengthBytes, Rc2SaltLengthBytes); } private static void EncryptInternal(Stream input, Stream output, byte[] password, byte keyLength) where T : SymmetricAlgorithm, new() { using (var crypto = new T()) { crypto.GenerateIV(); var salt = crypto.IV; using (var key = new Rfc2898DeriveBytes(password, salt, Iterations)) { crypto.Key = key.GetBytes(keyLength); } output.Write(salt, 0, salt.Length); using (var encryptor = crypto.CreateEncryptor()) { using (var cryptoStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) { input.CopyTo(cryptoStream, BufferSize); } } } } private static void DecryptInternal(Stream input, Stream output, byte[] password, byte keyLength, byte saltLength) where T : SymmetricAlgorithm, new() { try { using (var crypto = new T()) { var salt = new byte[saltLength]; input.Read(salt, 0, saltLength); crypto.IV = salt; using (var key = new Rfc2898DeriveBytes(password, salt, Iterations)) { crypto.Key = key.GetBytes(keyLength); } using(var decryptor = crypto.CreateDecryptor()) { using (var cryptoStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) { cryptoStream.CopyTo(output, BufferSize); } } } } catch (Exception e) { throw new CryptographicException("Something went wrong while trying to decrypt data!", e); } } } }