@@ -0,0 +1,158 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Security.Cryptography; | |||||
using System.Text; | |||||
namespace Shadowsocks.Encrypt | |||||
{ | |||||
public abstract class IVEncryptor | |||||
: EncryptorBase | |||||
{ | |||||
protected static byte[] tempbuf = new byte[32768]; | |||||
protected Dictionary<string, int[]> ciphers; | |||||
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>(); | |||||
protected byte[] _encryptIV; | |||||
protected byte[] _decryptIV; | |||||
protected bool _decryptIVReceived; | |||||
protected bool _encryptIVSent; | |||||
protected int _encryptIVOffset = 0; | |||||
protected int _decryptIVOffset = 0; | |||||
protected string _method; | |||||
protected int _cipher; | |||||
protected int[] _cipherInfo; | |||||
protected byte[] _key; | |||||
protected int keyLen; | |||||
protected int ivLen; | |||||
public IVEncryptor(string method, string password) | |||||
: base(method, password) | |||||
{ | |||||
InitKey(method, password); | |||||
} | |||||
protected abstract Dictionary<string, int[]> getCiphers(); | |||||
protected void InitKey(string method, string password) | |||||
{ | |||||
method = method.ToLower(); | |||||
_method = method; | |||||
string k = method + ":" + password; | |||||
ciphers = getCiphers(); | |||||
_cipherInfo = ciphers[_method]; | |||||
_cipher = _cipherInfo[2]; | |||||
if (_cipher == 0) | |||||
{ | |||||
throw new Exception("method not found"); | |||||
} | |||||
keyLen = ciphers[_method][0]; | |||||
ivLen = ciphers[_method][1]; | |||||
if (CachedKeys.ContainsKey(k)) | |||||
{ | |||||
_key = CachedKeys[k]; | |||||
} | |||||
else | |||||
{ | |||||
byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||||
_key = new byte[32]; | |||||
byte[] iv = new byte[16]; | |||||
bytesToKey(passbuf, _key); | |||||
CachedKeys[k] = _key; | |||||
} | |||||
} | |||||
protected void bytesToKey(byte[] password, byte[] key) | |||||
{ | |||||
byte[] result = new byte[password.Length + 16]; | |||||
int i = 0; | |||||
byte[] md5sum = null; | |||||
while (i < key.Length) | |||||
{ | |||||
MD5 md5 = MD5.Create(); | |||||
if (i == 0) | |||||
{ | |||||
md5sum = md5.ComputeHash(password); | |||||
} | |||||
else | |||||
{ | |||||
md5sum.CopyTo(result, 0); | |||||
password.CopyTo(result, md5sum.Length); | |||||
md5sum = md5.ComputeHash(result); | |||||
} | |||||
md5sum.CopyTo(key, i); | |||||
i += md5sum.Length; | |||||
} | |||||
} | |||||
protected static void randBytes(byte[] buf, int length) | |||||
{ | |||||
byte[] temp = new byte[length]; | |||||
new Random().NextBytes(temp); | |||||
temp.CopyTo(buf, 0); | |||||
} | |||||
protected virtual void initCipher(byte[] iv, bool isCipher) | |||||
{ | |||||
if (ivLen > 0) | |||||
{ | |||||
if (isCipher) | |||||
{ | |||||
_encryptIV = new byte[ivLen]; | |||||
Array.Copy(iv, _encryptIV, ivLen); | |||||
} | |||||
else | |||||
{ | |||||
_decryptIV = new byte[ivLen]; | |||||
Array.Copy(iv, _decryptIV, ivLen); | |||||
} | |||||
} | |||||
} | |||||
protected abstract void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf); | |||||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||||
{ | |||||
if (!_encryptIVSent) | |||||
{ | |||||
_encryptIVSent = true; | |||||
randBytes(outbuf, ivLen); | |||||
initCipher(outbuf, true); | |||||
outlength = length + ivLen; | |||||
lock (tempbuf) | |||||
{ | |||||
cipherUpdate(true, length, buf, tempbuf); | |||||
outlength = length + ivLen; | |||||
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, length); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
outlength = length; | |||||
cipherUpdate(true, length, buf, outbuf); | |||||
} | |||||
} | |||||
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||||
{ | |||||
if (!_decryptIVReceived) | |||||
{ | |||||
_decryptIVReceived = true; | |||||
initCipher(buf, false); | |||||
outlength = length - ivLen; | |||||
lock (tempbuf) | |||||
{ | |||||
// C# could be multi-threaded | |||||
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); | |||||
cipherUpdate(false, length - ivLen, tempbuf, outbuf); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
outlength = length; | |||||
cipherUpdate(false, length, buf, outbuf); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -8,32 +8,13 @@ using System.Threading; | |||||
namespace Shadowsocks.Encrypt | namespace Shadowsocks.Encrypt | ||||
{ | { | ||||
public class PolarSSLEncryptor | public class PolarSSLEncryptor | ||||
: EncryptorBase, IDisposable | |||||
: IVEncryptor, IDisposable | |||||
{ | { | ||||
const int CIPHER_AES = 1; | const int CIPHER_AES = 1; | ||||
const int CIPHER_RC4 = 2; | const int CIPHER_RC4 = 2; | ||||
static Dictionary<string, int[]> ciphers = new Dictionary<string, int[]> { | |||||
{"aes-128-cfb", new int[]{16, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"aes-192-cfb", new int[]{24, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"aes-256-cfb", new int[]{32, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"rc4", new int[]{16, 0, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}}, | |||||
{"rc4-md5", new int[]{16, 16, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}}, | |||||
}; | |||||
private static readonly Dictionary<string, byte[]> CachedKeys = new Dictionary<string, byte[]>(); | |||||
private int _cipher; | |||||
private int[] _cipherInfo; | |||||
private byte[] _key; | |||||
private IntPtr _encryptCtx = IntPtr.Zero; | private IntPtr _encryptCtx = IntPtr.Zero; | ||||
private IntPtr _decryptCtx = IntPtr.Zero; | private IntPtr _decryptCtx = IntPtr.Zero; | ||||
private byte[] _encryptIV; | |||||
private byte[] _decryptIV; | |||||
private int _encryptIVOffset = 0; | |||||
private int _decryptIVOffset = 0; | |||||
private string _method; | |||||
private int keyLen; | |||||
private int ivLen; | |||||
public PolarSSLEncryptor(string method, string password) | public PolarSSLEncryptor(string method, string password) | ||||
: base(method, password) | : base(method, password) | ||||
@@ -41,66 +22,31 @@ namespace Shadowsocks.Encrypt | |||||
InitKey(method, password); | InitKey(method, password); | ||||
} | } | ||||
private static void randBytes(byte[] buf, int length) | |||||
protected override Dictionary<string, int[]> getCiphers() | |||||
{ | { | ||||
byte[] temp = new byte[length]; | |||||
new Random().NextBytes(temp); | |||||
temp.CopyTo(buf, 0); | |||||
return new Dictionary<string, int[]> { | |||||
{"aes-128-cfb", new int[]{16, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"aes-192-cfb", new int[]{24, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"aes-256-cfb", new int[]{32, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}}, | |||||
{"rc4", new int[]{16, 0, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}}, | |||||
{"rc4-md5", new int[]{16, 16, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}}, | |||||
}; | |||||
} | } | ||||
private void bytesToKey(byte[] password, byte[] key) | |||||
protected override void initCipher(byte[] iv, bool isCipher) | |||||
{ | { | ||||
byte[] result = new byte[password.Length + 16]; | |||||
int i = 0; | |||||
byte[] md5sum = null; | |||||
while (i < key.Length) | |||||
{ | |||||
MD5 md5 = MD5.Create(); | |||||
if (i == 0) | |||||
{ | |||||
md5sum = md5.ComputeHash(password); | |||||
} | |||||
else | |||||
{ | |||||
md5sum.CopyTo(result, 0); | |||||
password.CopyTo(result, md5sum.Length); | |||||
md5sum = md5.ComputeHash(result); | |||||
} | |||||
md5sum.CopyTo(key, i); | |||||
i += md5sum.Length; | |||||
} | |||||
} | |||||
base.initCipher(iv, isCipher); | |||||
private void InitKey(string method, string password) | |||||
{ | |||||
method = method.ToLower(); | |||||
_method = method; | |||||
string k = method + ":" + password; | |||||
_cipherInfo = ciphers[_method]; | |||||
_cipher = _cipherInfo[2]; | |||||
if (_cipher == 0) | |||||
{ | |||||
throw new Exception("method not found"); | |||||
} | |||||
keyLen = ciphers[_method][0]; | |||||
ivLen = ciphers[_method][1]; | |||||
if (CachedKeys.ContainsKey(k)) | |||||
IntPtr ctx; | |||||
ctx = Marshal.AllocHGlobal(_cipherInfo[3]); | |||||
if (isCipher) | |||||
{ | { | ||||
_key = CachedKeys[k]; | |||||
_encryptCtx = ctx; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||||
_key = new byte[32]; | |||||
byte[] iv = new byte[16]; | |||||
bytesToKey(passbuf, _key); | |||||
CachedKeys[k] = _key; | |||||
_decryptCtx = ctx; | |||||
} | } | ||||
} | |||||
private void InitCipher(ref IntPtr ctx, byte[] iv, bool isCipher) | |||||
{ | |||||
ctx = Marshal.AllocHGlobal(_cipherInfo[3]); | |||||
byte[] realkey; | byte[] realkey; | ||||
if (_method == "rc4-md5") | if (_method == "rc4-md5") | ||||
{ | { | ||||
@@ -120,16 +66,6 @@ namespace Shadowsocks.Encrypt | |||||
// PolarSSL takes key length by bit | // PolarSSL takes key length by bit | ||||
// since we'll use CFB mode, here we both do enc, not dec | // since we'll use CFB mode, here we both do enc, not dec | ||||
PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8); | PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8); | ||||
if (isCipher) | |||||
{ | |||||
_encryptIV = new byte[ivLen]; | |||||
Array.Copy(iv, _encryptIV, ivLen); | |||||
} | |||||
else | |||||
{ | |||||
_decryptIV = new byte[ivLen]; | |||||
Array.Copy(iv, _decryptIV, ivLen); | |||||
} | |||||
} | } | ||||
else if (_cipher == CIPHER_RC4) | else if (_cipher == CIPHER_RC4) | ||||
{ | { | ||||
@@ -139,98 +75,41 @@ namespace Shadowsocks.Encrypt | |||||
} | } | ||||
} | } | ||||
static byte[] tempbuf = new byte[32768]; | |||||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||||
protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf) | |||||
{ | { | ||||
if (_encryptCtx == IntPtr.Zero) | |||||
// C# could be multi-threaded | |||||
if (_disposed) | |||||
{ | { | ||||
randBytes(outbuf, ivLen); | |||||
InitCipher(ref _encryptCtx, outbuf, true); | |||||
outlength = length + ivLen; | |||||
lock (tempbuf) | |||||
{ | |||||
// C# could be multi-threaded | |||||
if (_disposed) | |||||
{ | |||||
throw new ObjectDisposedException(this.ToString()); | |||||
} | |||||
switch (_cipher) | |||||
{ | |||||
case CIPHER_AES: | |||||
PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); | |||||
break; | |||||
case CIPHER_RC4: | |||||
PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf); | |||||
break; | |||||
} | |||||
outlength = length + ivLen; | |||||
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, length); | |||||
} | |||||
throw new ObjectDisposedException(this.ToString()); | |||||
} | |||||
byte[] iv; | |||||
int ivOffset; | |||||
if (isCipher) | |||||
{ | |||||
iv = _encryptIV; | |||||
ivOffset = _encryptIVOffset; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
outlength = length; | |||||
if (_disposed) | |||||
{ | |||||
throw new ObjectDisposedException(this.ToString()); | |||||
} | |||||
switch (_cipher) | |||||
{ | |||||
case CIPHER_AES: | |||||
PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf); | |||||
break; | |||||
case CIPHER_RC4: | |||||
PolarSSL.arc4_crypt(_encryptCtx, length, buf, outbuf); | |||||
break; | |||||
} | |||||
iv = _decryptIV; | |||||
ivOffset = _decryptIVOffset; | |||||
} | } | ||||
} | |||||
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||||
{ | |||||
if (_decryptCtx == IntPtr.Zero) | |||||
switch (_cipher) | |||||
{ | { | ||||
InitCipher(ref _decryptCtx, buf, false); | |||||
outlength = length - ivLen; | |||||
lock (tempbuf) | |||||
{ | |||||
// C# could be multi-threaded | |||||
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); | |||||
if (_disposed) | |||||
case CIPHER_AES: | |||||
PolarSSL.aes_crypt_cfb128(_encryptCtx, isCipher ? PolarSSL.AES_ENCRYPT : PolarSSL.AES_DECRYPT, length, ref ivOffset, iv, buf, outbuf); | |||||
if (isCipher) | |||||
{ | { | ||||
throw new ObjectDisposedException(this.ToString()); | |||||
_encryptIVOffset = ivOffset; | |||||
} | } | ||||
switch (_cipher) | |||||
else | |||||
{ | { | ||||
case CIPHER_AES: | |||||
PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); | |||||
break; | |||||
case CIPHER_RC4: | |||||
PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf); | |||||
break; | |||||
_decryptIVOffset = ivOffset; | |||||
} | } | ||||
} | |||||
} | |||||
else | |||||
{ | |||||
outlength = length; | |||||
if (_disposed) | |||||
{ | |||||
throw new ObjectDisposedException(this.ToString()); | |||||
} | |||||
switch (_cipher) | |||||
{ | |||||
case CIPHER_AES: | |||||
PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf); | |||||
break; | |||||
case CIPHER_RC4: | |||||
PolarSSL.arc4_crypt(_decryptCtx, length, buf, outbuf); | |||||
break; | |||||
} | |||||
break; | |||||
case CIPHER_RC4: | |||||
PolarSSL.arc4_crypt(_encryptCtx, length, buf, outbuf); | |||||
break; | |||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,39 @@ | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
namespace Shadowsocks.Encrypt | |||||
{ | |||||
public class Sodium | |||||
{ | |||||
const string DLLNAME = "libsodium"; | |||||
static Sodium() | |||||
{ | |||||
string tempPath = Path.GetTempPath(); | |||||
string dllPath = tempPath + "/libsodium.dll"; | |||||
try | |||||
{ | |||||
FileManager.UncompressFile(dllPath, Resources.libsodium_dll); | |||||
} | |||||
catch (IOException e) | |||||
{ | |||||
Console.WriteLine(e.ToString()); | |||||
} | |||||
LoadLibrary(dllPath); | |||||
} | |||||
[DllImport("Kernel32.dll")] | |||||
private static extern IntPtr LoadLibrary(string path); | |||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | |||||
public extern static void crypto_stream_salsa20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k); | |||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | |||||
public extern static void crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k); | |||||
} | |||||
} |
@@ -0,0 +1,63 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Shadowsocks.Encrypt | |||||
{ | |||||
public class SodiumEncryptor | |||||
: IVEncryptor, IDisposable | |||||
{ | |||||
const int CIPHER_SALSA20 = 1; | |||||
const int CIPHER_CHACHA20 = 2; | |||||
protected uint _encryptBytesRemaining; | |||||
protected uint _decryptBytesRemaining; | |||||
protected ulong _encryptIC; | |||||
protected ulong _decryptIC; | |||||
public SodiumEncryptor(string method, string password) | |||||
: base(method, password) | |||||
{ | |||||
InitKey(method, password); | |||||
} | |||||
protected override Dictionary<string, int[]> getCiphers() | |||||
{ | |||||
return new Dictionary<string, int[]> { | |||||
{"salsa20", new int[]{32, 8, CIPHER_SALSA20, PolarSSL.AES_CTX_SIZE}}, | |||||
{"chacha20", new int[]{32, 8, CIPHER_CHACHA20, PolarSSL.AES_CTX_SIZE}}, | |||||
}; ; | |||||
} | |||||
protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf) | |||||
{ | |||||
uint bytesRemaining; | |||||
ulong ic; | |||||
if (isCipher) | |||||
{ | |||||
bytesRemaining = _encryptBytesRemaining; | |||||
ic = _encryptIC; | |||||
} | |||||
else | |||||
{ | |||||
bytesRemaining = _decryptBytesRemaining; | |||||
ic = _decryptIC; | |||||
} | |||||
if (isCipher) | |||||
{ | |||||
_encryptBytesRemaining = bytesRemaining; | |||||
_encryptIC = ic; | |||||
} | |||||
else | |||||
{ | |||||
_decryptBytesRemaining = bytesRemaining; | |||||
_decryptIC = ic; | |||||
} | |||||
} | |||||
public override void Dispose() | |||||
{ | |||||
} | |||||
} | |||||
} |
@@ -60,6 +60,16 @@ namespace Shadowsocks.Properties { | |||||
} | } | ||||
} | } | ||||
/// <summary> | |||||
/// Looks up a localized resource of type System.Byte[]. | |||||
/// </summary> | |||||
internal static byte[] libsodium_dll { | |||||
get { | |||||
object obj = ResourceManager.GetObject("libsodium_dll", resourceCulture); | |||||
return ((byte[])(obj)); | |||||
} | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Looks up a localized resource of type System.Byte[]. | /// Looks up a localized resource of type System.Byte[]. | ||||
/// </summary> | /// </summary> | ||||
@@ -118,6 +118,9 @@ | |||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
</resheader> | </resheader> | ||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> | <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> | ||||
<data name="libsodium_dll" type="System.Resources.ResXFileRef, System.Windows.Forms"> | |||||
<value>..\data\libsodium.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||||
</data> | |||||
<data name="polarssl_dll" type="System.Resources.ResXFileRef, System.Windows.Forms"> | <data name="polarssl_dll" type="System.Resources.ResXFileRef, System.Windows.Forms"> | ||||
<value>..\Data\polarssl.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | <value>..\Data\polarssl.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
</data> | </data> | ||||
@@ -77,8 +77,11 @@ | |||||
<Compile Include="Controller\UpdateChecker.cs" /> | <Compile Include="Controller\UpdateChecker.cs" /> | ||||
<Compile Include="Encrypt\EncryptorBase.cs" /> | <Compile Include="Encrypt\EncryptorBase.cs" /> | ||||
<Compile Include="Encrypt\EncryptorFactory.cs" /> | <Compile Include="Encrypt\EncryptorFactory.cs" /> | ||||
<Compile Include="Encrypt\IVEncryptor.cs" /> | |||||
<Compile Include="Encrypt\PolarSSL.cs" /> | <Compile Include="Encrypt\PolarSSL.cs" /> | ||||
<Compile Include="Encrypt\PolarSSLEncryptor.cs" /> | <Compile Include="Encrypt\PolarSSLEncryptor.cs" /> | ||||
<Compile Include="Encrypt\Sodium.cs" /> | |||||
<Compile Include="Encrypt\SodiumEncryptor.cs" /> | |||||
<Compile Include="Encrypt\TableEncryptor.cs" /> | <Compile Include="Encrypt\TableEncryptor.cs" /> | ||||
<Compile Include="Encrypt\IEncryptor.cs" /> | <Compile Include="Encrypt\IEncryptor.cs" /> | ||||
<Compile Include="Controller\PACServer.cs" /> | <Compile Include="Controller\PACServer.cs" /> | ||||
@@ -125,6 +128,7 @@ | |||||
<None Include="app.manifest"> | <None Include="app.manifest"> | ||||
<SubType>Designer</SubType> | <SubType>Designer</SubType> | ||||
</None> | </None> | ||||
<None Include="Data\libsodium.dll.gz" /> | |||||
<None Include="Data\polarssl.dll.gz" /> | <None Include="Data\polarssl.dll.gz" /> | ||||
<None Include="Data\polipo.exe.gz" /> | <None Include="Data\polipo.exe.gz" /> | ||||
<None Include="Properties\Settings.settings"> | <None Include="Properties\Settings.settings"> | ||||