|
|
@@ -1,12 +1,12 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
using System.Text; |
|
|
|
|
|
|
|
namespace shadowsocks_csharp.Encrypt |
|
|
|
{ |
|
|
|
public class OpensslEncryptor |
|
|
|
: EncryptorBase, IDisposable |
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
namespace shadowsocks_csharp.Encrypt
|
|
|
|
{
|
|
|
|
public class OpensslEncryptor
|
|
|
|
: EncryptorBase, IDisposable
|
|
|
|
{
|
|
|
|
static Dictionary<string, int[]> ciphers = new Dictionary<string, int[]> {
|
|
|
|
{"aes-128-cfb", new int[]{16, 16}},
|
|
|
@@ -14,66 +14,66 @@ namespace shadowsocks_csharp.Encrypt |
|
|
|
{"aes-256-cfb", new int[]{32, 16}},
|
|
|
|
{"bf-cfb", new int[]{16, 8}},
|
|
|
|
{"rc4", new int[]{16, 0}},
|
|
|
|
{"rc4-md5", new int[]{16, 16}}, |
|
|
|
{"rc4-md5", new int[]{16, 16}},
|
|
|
|
};
|
|
|
|
|
|
|
|
static OpensslEncryptor()
|
|
|
|
{
|
|
|
|
OpenSSL.OpenSSL_add_all_ciphers();
|
|
|
|
} |
|
|
|
|
|
|
|
public OpensslEncryptor(string method, string password) |
|
|
|
: base(method, password) |
|
|
|
{ |
|
|
|
InitKey(method, password); |
|
|
|
}
|
|
|
|
|
|
|
|
public OpensslEncryptor(string method, string password)
|
|
|
|
: base(method, password)
|
|
|
|
{
|
|
|
|
InitKey(method, password);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static byte[] tempbuf = new byte[32768];
|
|
|
|
|
|
|
|
static byte[] tempbuf = new byte[32768]; |
|
|
|
|
|
|
|
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) |
|
|
|
{ |
|
|
|
if (_encryptCtx == IntPtr.Zero) |
|
|
|
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
|
|
|
{
|
|
|
|
if (_encryptCtx == IntPtr.Zero)
|
|
|
|
{
|
|
|
|
OpenSSL.RAND_bytes(outbuf, ivLen);
|
|
|
|
InitCipher(ref _encryptCtx, outbuf, true);
|
|
|
|
outlength = length + ivLen;
|
|
|
|
OpenSSL.EVP_CipherUpdate(_encryptCtx, tempbuf, out outlength, buf, length);
|
|
|
|
outlength = length + ivLen;
|
|
|
|
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength); |
|
|
|
} |
|
|
|
else |
|
|
|
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outlength = length;
|
|
|
|
OpenSSL.EVP_CipherUpdate(_encryptCtx, outbuf, out outlength, buf, length); |
|
|
|
} |
|
|
|
OpenSSL.EVP_CipherUpdate(_encryptCtx, outbuf, out outlength, buf, length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) |
|
|
|
{ |
|
|
|
if (_decryptCtx == IntPtr.Zero) |
|
|
|
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
|
|
|
{
|
|
|
|
if (_decryptCtx == IntPtr.Zero)
|
|
|
|
{
|
|
|
|
InitCipher(ref _decryptCtx, buf, false);
|
|
|
|
outlength = length - ivLen;
|
|
|
|
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen);
|
|
|
|
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, tempbuf, length - ivLen); |
|
|
|
} |
|
|
|
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, tempbuf, length - ivLen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outlength = length;
|
|
|
|
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, buf, length); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>(); |
|
|
|
private byte[] _key; |
|
|
|
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, buf, length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>();
|
|
|
|
private byte[] _key;
|
|
|
|
private IntPtr _encryptCtx;
|
|
|
|
private IntPtr _decryptCtx;
|
|
|
|
private IntPtr _cipher;
|
|
|
|
private string _method;
|
|
|
|
private int keyLen;
|
|
|
|
private int ivLen; |
|
|
|
|
|
|
|
private int ivLen;
|
|
|
|
|
|
|
|
private void InitKey(string method, string password)
|
|
|
|
{
|
|
|
|
method = method.ToLower();
|
|
|
@@ -101,12 +101,12 @@ namespace shadowsocks_csharp.Encrypt |
|
|
|
byte[] iv = new byte[16];
|
|
|
|
OpenSSL.EVP_BytesToKey(_cipher, OpenSSL.EVP_md5(), IntPtr.Zero, passbuf, passbuf.Length, 1, _key, iv);
|
|
|
|
CachedKeys[k] = _key;
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void InitCipher(ref IntPtr ctx, byte[] iv, bool isCipher) |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void InitCipher(ref IntPtr ctx, byte[] iv, bool isCipher)
|
|
|
|
{
|
|
|
|
ctx = OpenSSL.EVP_CIPHER_CTX_new(); |
|
|
|
ctx = OpenSSL.EVP_CIPHER_CTX_new();
|
|
|
|
int enc = isCipher ? 1 : 0;
|
|
|
|
byte[] realkey;
|
|
|
|
IntPtr r = IntPtr.Zero;
|
|
|
@@ -123,48 +123,48 @@ namespace shadowsocks_csharp.Encrypt |
|
|
|
{
|
|
|
|
realkey = _key;
|
|
|
|
}
|
|
|
|
OpenSSL.EVP_CipherInit_ex(ctx, _cipher, IntPtr.Zero, realkey, iv, enc); |
|
|
|
} |
|
|
|
|
|
|
|
#region IDisposable |
|
|
|
private bool _disposed; |
|
|
|
|
|
|
|
public override void Dispose() |
|
|
|
{ |
|
|
|
Dispose(true); |
|
|
|
GC.SuppressFinalize(this); |
|
|
|
} |
|
|
|
|
|
|
|
~OpensslEncryptor() |
|
|
|
{ |
|
|
|
Dispose(false); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing) |
|
|
|
{ |
|
|
|
if (!_disposed) |
|
|
|
{ |
|
|
|
if (disposing) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (_encryptCtx.ToInt64() != 0) |
|
|
|
OpenSSL.EVP_CipherInit_ex(ctx, _cipher, IntPtr.Zero, realkey, iv, enc);
|
|
|
|
}
|
|
|
|
|
|
|
|
#region IDisposable
|
|
|
|
private bool _disposed;
|
|
|
|
|
|
|
|
public override void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
~OpensslEncryptor()
|
|
|
|
{
|
|
|
|
Dispose(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (!_disposed)
|
|
|
|
{
|
|
|
|
if (disposing)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_encryptCtx.ToInt64() != 0)
|
|
|
|
{
|
|
|
|
OpenSSL.EVP_CIPHER_CTX_cleanup(_encryptCtx);
|
|
|
|
OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx); |
|
|
|
_encryptCtx = IntPtr.Zero; |
|
|
|
OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx);
|
|
|
|
_encryptCtx = IntPtr.Zero;
|
|
|
|
}
|
|
|
|
if (_decryptCtx.ToInt64() != 0) |
|
|
|
if (_decryptCtx.ToInt64() != 0)
|
|
|
|
{
|
|
|
|
OpenSSL.EVP_CIPHER_CTX_cleanup(_decryptCtx);
|
|
|
|
OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx); |
|
|
|
_decryptCtx = IntPtr.Zero; |
|
|
|
} |
|
|
|
|
|
|
|
_disposed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
#endregion |
|
|
|
} |
|
|
|
} |
|
|
|
OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx);
|
|
|
|
_decryptCtx = IntPtr.Zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
_disposed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|