Browse Source

Add BouncyCastle AEAD

pull/2865/head
celeron533 4 years ago
parent
commit
77c6cc4e08
4 changed files with 123 additions and 0 deletions
  1. +74
    -0
      shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs
  2. +1
    -0
      shadowsocks-csharp/packages.config
  3. +4
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj
  4. +44
    -0
      test/CryptographyTest.cs

+ 74
- 0
shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs View File

@@ -0,0 +1,74 @@
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Shadowsocks.Encryption.AEAD
{
public class AEADBouncyCastleEncryptor : AEADEncryptor//, IDisposable
{
public AEADBouncyCastleEncryptor(string method, string password)
: base(method, password)
{
}
static int CIPHER_AES=1;
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)},
{"aes-192-gcm", new EncryptorInfo("AES-192-GCM", 24, 24, 12, 16, CIPHER_AES)},
{"aes-256-gcm", new EncryptorInfo("AES-256-GCM", 32, 32, 12, 16, CIPHER_AES)},
};
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _decNonce);
cipher.Init(false, parameters);
plaintext = new byte[cipher.GetOutputSize((int)clen)];
var len = cipher.ProcessBytes(ciphertext, 0, (int)clen, plaintext, 0);
cipher.DoFinal(plaintext, len);
plen = (uint)(plaintext.Length);
}
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _encNonce);
cipher.Init(true, parameters);
ciphertext = new byte[cipher.GetOutputSize((int)plen)];
var len = cipher.ProcessBytes(plaintext, 0, (int)plen, ciphertext, 0);
cipher.DoFinal(ciphertext, len);
clen = (uint)(ciphertext.Length);
}
public override void Dispose()
{
//throw new NotImplementedException();
}
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
{
base.InitCipher(salt, isEncrypt, isUdp);
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt,
_Masterkey, _sessionKey);
}
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
}
}

+ 1
- 0
shadowsocks-csharp/packages.config View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.8.5" targetFramework="net472" />
<package id="Caseless.Fody" version="1.8.3" targetFramework="net472" />
<package id="Costura.Fody" version="3.3.3" targetFramework="net472" />
<package id="Fody" version="4.2.1" targetFramework="net472" developmentDependency="true" />


+ 4
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -68,6 +68,9 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto, Version=1.8.5.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
<HintPath>..\packages\BouncyCastle.1.8.5\lib\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="Caseless, Version=1.8.3.0, Culture=neutral, PublicKeyToken=409b3227471b0f0d, processorArchitecture=MSIL">
<HintPath>..\packages\Caseless.Fody.1.8.3\lib\net452\Caseless.dll</HintPath>
</Reference>
@@ -114,6 +117,7 @@
<Compile Include="Controller\LoggerExtension.cs" />
<Compile Include="Controller\Service\PACDaemon.cs" />
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
<Compile Include="Encryption\AEAD\AEADBouncyCastleEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADOpenSSLEncryptor.cs" />


+ 44
- 0
test/CryptographyTest.cs View File

@@ -230,6 +230,50 @@ namespace Shadowsocks.Test
}
}
[TestMethod]
public void TestBouncyCastleEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleBouncyCastleEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleBouncyCastleEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleBouncyCastleEncryptionThread()
{
try
{
for (int i = 0; i < 10; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!");
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
decryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!");
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestOpenSSLAEADEncryption()
{


Loading…
Cancel
Save