mirror of
				https://github.com/bolucat/Archive.git
				synced 2025-10-31 20:03:10 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.IO;
 | |
| using System.Runtime.InteropServices;
 | |
| using System.Security;
 | |
| using System.Text;
 | |
| using NLog;
 | |
| using Shadowsocks.Controller;
 | |
| using Shadowsocks.Encryption.Exception;
 | |
| using Shadowsocks.Properties;
 | |
| using Shadowsocks.Util;
 | |
| 
 | |
| namespace Shadowsocks.Encryption
 | |
| {
 | |
|     // XXX: only for OpenSSL 1.1.0 and higher
 | |
|     public static class OpenSSL
 | |
|     {
 | |
|         private static Logger logger = LogManager.GetCurrentClassLogger();
 | |
| 
 | |
|         private const string DLLNAME = "libsscrypto.dll";
 | |
| 
 | |
|         public const int OPENSSL_ENCRYPT = 1;
 | |
|         public const int OPENSSL_DECRYPT = 0;
 | |
| 
 | |
|         public const int EVP_CTRL_AEAD_SET_IVLEN = 0x9;
 | |
|         public const int EVP_CTRL_AEAD_GET_TAG = 0x10;
 | |
|         public const int EVP_CTRL_AEAD_SET_TAG = 0x11;
 | |
| 
 | |
|         static OpenSSL()
 | |
|         {
 | |
|             string dllPath = Utils.GetTempPath(DLLNAME);
 | |
|             try
 | |
|             {
 | |
|                 FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
 | |
|             }
 | |
|             catch (IOException)
 | |
|             {
 | |
|             }
 | |
|             catch (System.Exception e)
 | |
|             {
 | |
|                 logger.LogUsefulException(e);
 | |
|             }
 | |
|             LoadLibrary(dllPath);
 | |
|         }
 | |
| 
 | |
|         public static IntPtr GetCipherInfo(string cipherName)
 | |
|         {
 | |
|             var name = Encoding.ASCII.GetBytes(cipherName);
 | |
|             Array.Resize(ref name, name.Length + 1);
 | |
|             return EVP_get_cipherbyname(name);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Need init cipher context after EVP_CipherFinal_ex to reuse context
 | |
|         /// </summary>
 | |
|         /// <param name="ctx"></param>
 | |
|         /// <param name="cipherType"></param>
 | |
|         /// <param name="nonce"></param>
 | |
|         public static void SetCtxNonce(IntPtr ctx, byte[] nonce, bool isEncrypt)
 | |
|         {
 | |
|             var ret = EVP_CipherInit_ex(ctx, IntPtr.Zero,
 | |
|                 IntPtr.Zero, null,
 | |
|                 nonce,
 | |
|                 isEncrypt ? OPENSSL_ENCRYPT : OPENSSL_DECRYPT);
 | |
|             if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce");
 | |
|         }
 | |
| 
 | |
|         public static void AEADGetTag(IntPtr ctx, byte[] tagbuf, int taglen)
 | |
|         {
 | |
|             IntPtr tagBufIntPtr = IntPtr.Zero;
 | |
|             try
 | |
|             {
 | |
|                 tagBufIntPtr = Marshal.AllocHGlobal(taglen);
 | |
|                 var ret = EVP_CIPHER_CTX_ctrl(ctx,
 | |
|                     EVP_CTRL_AEAD_GET_TAG, taglen, tagBufIntPtr);
 | |
|                 if (ret != 1) throw new CryptoErrorException("openssl: fail to get AEAD tag");
 | |
|                 // take tag from unmanaged memory
 | |
|                 Marshal.Copy(tagBufIntPtr, tagbuf, 0, taglen);
 | |
|             }
 | |
|             finally
 | |
|             {
 | |
|                 if (tagBufIntPtr != IntPtr.Zero)
 | |
|                 {
 | |
|                     Marshal.FreeHGlobal(tagBufIntPtr);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static void AEADSetTag(IntPtr ctx, byte[] tagbuf, int taglen)
 | |
|         {
 | |
|             IntPtr tagBufIntPtr = IntPtr.Zero;
 | |
|             try
 | |
|             {
 | |
|                 // allocate unmanaged memory for tag
 | |
|                 tagBufIntPtr = Marshal.AllocHGlobal(taglen);
 | |
| 
 | |
|                 // copy tag to unmanaged memory
 | |
|                 Marshal.Copy(tagbuf, 0, tagBufIntPtr, taglen);
 | |
| 
 | |
|                 var ret = EVP_CIPHER_CTX_ctrl(ctx,
 | |
|                     EVP_CTRL_AEAD_SET_TAG, taglen, tagBufIntPtr);
 | |
| 
 | |
|                 if (ret != 1) throw new CryptoErrorException("openssl: fail to set AEAD tag");
 | |
| 
 | |
|             }
 | |
|             finally
 | |
|             {
 | |
|                 if (tagBufIntPtr != IntPtr.Zero)
 | |
|                 {
 | |
|                     Marshal.FreeHGlobal(tagBufIntPtr);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [DllImport("Kernel32.dll")]
 | |
|         private static extern IntPtr LoadLibrary(string path);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern IntPtr EVP_CIPHER_CTX_new();
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern void EVP_CIPHER_CTX_free(IntPtr ctx);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CIPHER_CTX_reset(IntPtr ctx);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CipherInit_ex(IntPtr ctx, IntPtr type,
 | |
|             IntPtr impl, byte[] key, byte[] iv, int enc);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CipherUpdate(IntPtr ctx, byte[] outb,
 | |
|             out int outl, byte[] inb, int inl);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CipherFinal_ex(IntPtr ctx, byte[] outm, ref int outl);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CIPHER_CTX_set_padding(IntPtr x, int padding);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CIPHER_CTX_set_key_length(IntPtr x, int keylen);
 | |
| 
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern int EVP_CIPHER_CTX_ctrl(IntPtr ctx, int type, int arg, IntPtr ptr);
 | |
| 
 | |
|         /// <summary>
 | |
|         /// simulate NUL-terminated string
 | |
|         /// </summary>
 | |
|         /// <param name="name"></param>
 | |
|         /// <returns></returns>
 | |
|         [SuppressUnmanagedCodeSecurity]
 | |
|         [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
 | |
|         public static extern IntPtr EVP_get_cipherbyname(byte[] name);
 | |
|     }
 | |
| } | 
![github-action[bot]](/assets/img/avatar_default.png)