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 |