208 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			208 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | #if !DISABLE_ENCRYPTION | |||
|  | using System.IO; | |||
|  | using System.Security.Cryptography; | |||
|  | #if NETFX_CORE | |||
|  | using Windows.Security.Cryptography; | |||
|  | using Windows.Security.Cryptography.Core; | |||
|  | using Windows.Storage.Streams; | |||
|  | using System.Runtime.InteropServices.WindowsRuntime; | |||
|  | #endif | |||
|  | 
 | |||
|  | namespace ES3Internal | |||
|  | { | |||
|  | 	public static class ES3Hash | |||
|  | 	{ | |||
|  | #if NETFX_CORE | |||
|  | 		public static string SHA1Hash(string input) | |||
|  | 		{ | |||
|  | 			return System.Text.Encoding.UTF8.GetString(UnityEngine.Windows.Crypto.ComputeSHA1Hash(System.Text.Encoding.UTF8.GetBytes(input))); | |||
|  | 		} | |||
|  | #else | |||
|  | 		public static string SHA1Hash(string input) | |||
|  | 		{ | |||
|  | 			using (SHA1Managed sha1 = new SHA1Managed()) | |||
|  | 				return System.Text.Encoding.UTF8.GetString(sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input))); | |||
|  | 		} | |||
|  | #endif | |||
|  | 	} | |||
|  | 
 | |||
|  |     public abstract class EncryptionAlgorithm | |||
|  |     { | |||
|  |         public abstract byte[] Encrypt(byte[] bytes, string password, int bufferSize); | |||
|  |         public abstract byte[] Decrypt(byte[] bytes, string password, int bufferSize); | |||
|  |         public abstract void Encrypt(Stream input, Stream output, string password, int bufferSize); | |||
|  |         public abstract void Decrypt(Stream input, Stream output, string password, int bufferSize); | |||
|  | 
 | |||
|  |         protected static void CopyStream(Stream input, Stream output, int bufferSize) | |||
|  |         { | |||
|  |             byte[] buffer = new byte[bufferSize]; | |||
|  |             int read; | |||
|  |             while ((read = input.Read(buffer, 0, bufferSize)) > 0) | |||
|  |                 output.Write(buffer, 0, read); | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     public class AESEncryptionAlgorithm : EncryptionAlgorithm | |||
|  |     { | |||
|  |         private const int ivSize = 16; | |||
|  |         private const int keySize = 16; | |||
|  |         private const int pwIterations = 100; | |||
|  | 
 | |||
|  |         public override byte[] Encrypt(byte[] bytes, string password, int bufferSize) | |||
|  |         { | |||
|  |             using (var input = new MemoryStream(bytes)) | |||
|  |             { | |||
|  |                 using (var output = new MemoryStream()) | |||
|  |                 { | |||
|  |                     Encrypt(input, output, password, bufferSize); | |||
|  |                     return output.ToArray(); | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         public override byte[] Decrypt(byte[] bytes, string password, int bufferSize) | |||
|  |         { | |||
|  |             using (var input = new MemoryStream(bytes)) | |||
|  |             { | |||
|  |                 using (var output = new MemoryStream()) | |||
|  |                 { | |||
|  |                     Decrypt(input, output, password, bufferSize); | |||
|  |                     return output.ToArray(); | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         public override void Encrypt(Stream input, Stream output, string password, int bufferSize) | |||
|  |         { | |||
|  |             input.Position = 0; | |||
|  | 
 | |||
|  | #if NETFX_CORE | |||
|  |             // Generate an IV and write it to the output. | |||
|  |             var iv = CryptographicBuffer.GenerateRandom(ivSize); | |||
|  |             output.Write(iv.ToArray(), 0, ivSize); | |||
|  | 
 | |||
|  |             var pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8); | |||
|  |             var keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1"); | |||
|  |             KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(iv, pwIterations); | |||
|  |             // Create a key based on original key and derivation parmaters | |||
|  |             CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer); | |||
|  |             IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, keySize); | |||
|  | 
 | |||
|  |             var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7); | |||
|  |             var key = provider.CreateSymmetricKey(keyMaterial); | |||
|  | 
 | |||
|  |             // Get the input stream as an IBuffer. | |||
|  |             IBuffer msg; | |||
|  |             using(var ms = new MemoryStream()) | |||
|  |             { | |||
|  |                 input.CopyTo(ms); | |||
|  |                 msg = ms.ToArray().AsBuffer(); | |||
|  |             } | |||
|  | 
 | |||
|  |             var buffEncrypt = CryptographicEngine.Encrypt(key, msg, iv); | |||
|  | 
 | |||
|  | 
 | |||
|  |             output.Write(buffEncrypt.ToArray(), 0, (int)buffEncrypt.Length); | |||
|  |             output.Dispose(); | |||
|  | #else | |||
|  |             using (var alg = Aes.Create()) | |||
|  | 			{ | |||
|  |                 alg.Mode = CipherMode.CBC; | |||
|  |                 alg.Padding = PaddingMode.PKCS7; | |||
|  |                 alg.GenerateIV(); | |||
|  |                 var key = new Rfc2898DeriveBytes(password, alg.IV, pwIterations); | |||
|  | 				alg.Key = key.GetBytes(keySize); | |||
|  | 				// Write the IV to the output stream. | |||
|  | 				output.Write(alg.IV, 0, ivSize); | |||
|  | 				using(var encryptor = alg.CreateEncryptor()) | |||
|  | 				using(var cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) | |||
|  | 					CopyStream(input, cs, bufferSize); | |||
|  | 			} | |||
|  | #endif | |||
|  |         } | |||
|  | 
 | |||
|  |         public override void Decrypt(Stream input, Stream output, string password, int bufferSize) | |||
|  |         { | |||
|  | #if NETFX_CORE | |||
|  |             var thisIV = new byte[ivSize]; | |||
|  |             input.Read(thisIV, 0, ivSize); | |||
|  |             var iv = thisIV.AsBuffer(); | |||
|  | 
 | |||
|  |             var pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8); | |||
|  | 
 | |||
|  |             var keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1"); | |||
|  |             KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(iv, pwIterations); | |||
|  |             // Create a key based on original key and derivation parameters. | |||
|  |             CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer); | |||
|  |             IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, keySize); | |||
|  |              | |||
|  |             var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7); | |||
|  |             var key = provider.CreateSymmetricKey(keyMaterial); | |||
|  | 
 | |||
|  |             // Get the input stream as an IBuffer. | |||
|  |             IBuffer msg; | |||
|  |             using(var ms = new MemoryStream()) | |||
|  |             { | |||
|  |                 input.CopyTo(ms); | |||
|  |                 msg = ms.ToArray().AsBuffer(); | |||
|  |             } | |||
|  | 
 | |||
|  |             var buffDecrypt = CryptographicEngine.Decrypt(key, msg, iv); | |||
|  | 
 | |||
|  |             output.Write(buffDecrypt.ToArray(), 0, (int)buffDecrypt.Length); | |||
|  | #else | |||
|  |             using (var alg = Aes.Create()) | |||
|  | 			{ | |||
|  |                 var thisIV = new byte[ivSize]; | |||
|  |                 input.Read(thisIV, 0, ivSize); | |||
|  |                 alg.IV = thisIV; | |||
|  | 
 | |||
|  |                 var key = new Rfc2898DeriveBytes(password, alg.IV, pwIterations); | |||
|  | 				alg.Key = key.GetBytes(keySize); | |||
|  | 
 | |||
|  | 				using(var decryptor = alg.CreateDecryptor()) | |||
|  | 				using(var cryptoStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) | |||
|  | 					CopyStream(cryptoStream, output, bufferSize); | |||
|  | 
 | |||
|  | 			} | |||
|  | #endif | |||
|  |             output.Position = 0; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     public class UnbufferedCryptoStream : MemoryStream | |||
|  |     { | |||
|  |         private readonly Stream stream; | |||
|  |         private readonly bool isReadStream; | |||
|  |         private string password; | |||
|  |         private int bufferSize; | |||
|  |         private EncryptionAlgorithm alg; | |||
|  |         private bool disposed = false; | |||
|  | 
 | |||
|  |         public UnbufferedCryptoStream(Stream stream, bool isReadStream, string password, int bufferSize, EncryptionAlgorithm alg) : base() | |||
|  |         { | |||
|  |             this.stream = stream; | |||
|  |             this.isReadStream = isReadStream; | |||
|  |             this.password = password; | |||
|  |             this.bufferSize = bufferSize; | |||
|  |             this.alg = alg; | |||
|  | 
 | |||
|  | 
 | |||
|  |             if (isReadStream) | |||
|  |                 alg.Decrypt(stream, this, password, bufferSize); | |||
|  |         } | |||
|  | 
 | |||
|  |         protected override void Dispose(bool disposing) | |||
|  |         { | |||
|  |             if (disposed) | |||
|  |                 return; | |||
|  |             disposed = true; | |||
|  | 
 | |||
|  |             if (!isReadStream) | |||
|  |                 alg.Encrypt(this, stream, password, bufferSize); | |||
|  |             stream.Dispose(); | |||
|  |             base.Dispose(disposing); | |||
|  |         } | |||
|  |     } | |||
|  | } | |||
|  | #endif |