Browse Source

Add bc chacha20-ietf

Drop NaCl
pull/3006/head
Bruce Wayne 3 years ago
parent
commit
6368535237
No known key found for this signature in database GPG Key ID: 6D396097F05051BF
4 changed files with 61 additions and 79 deletions
  1. +2
    -2
      Shadowsocks.Net/Crypto/CryptoFactory.cs
  2. +59
    -0
      Shadowsocks.Net/Crypto/Stream/StreamChachaBouncyCastleCrypto.cs
  3. +0
    -76
      Shadowsocks.Net/Crypto/Stream/StreamChachaNaClCrypto.cs
  4. +0
    -1
      Shadowsocks.Net/Shadowsocks.Net.csproj

+ 2
- 2
Shadowsocks.Net/Crypto/CryptoFactory.cs View File

@@ -42,12 +42,12 @@ namespace Shadowsocks.Net.Crypto
_registeredEncryptors.Add(method.Key, typeof(StreamAesCfbBouncyCastleCrypto));
}
}
foreach (var method in StreamChachaNaClCrypto.SupportedCiphers())
foreach (var method in StreamChachaBouncyCastleCrypto.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(StreamChachaNaClCrypto));
_registeredEncryptors.Add(method.Key, typeof(StreamChachaBouncyCastleCrypto));
}
}



+ 59
- 0
Shadowsocks.Net/Crypto/Stream/StreamChachaBouncyCastleCrypto.cs View File

@@ -0,0 +1,59 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;

namespace Shadowsocks.Net.Crypto.Stream
{
public class StreamChachaBouncyCastleCrypto : StreamCrypto
{
private readonly BufferedCipherBase _encryptor;

public StreamChachaBouncyCastleCrypto(string method, string password) : base(method, password)
{
_encryptor = new BufferedStreamCipher(new ChaCha7539Engine());
}

protected override void InitCipher(byte[] iv, bool isEncrypt)
{
base.InitCipher(iv, isEncrypt);
_encryptor.Init(isEncrypt, new ParametersWithIV(new KeyParameter(key), iv));
}

protected override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
return CipherUpdate(plain, cipher);
}

protected override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
return CipherUpdate(cipher, plain);
}

protected virtual int CipherUpdate(ReadOnlySpan<byte> input, Span<byte> output)
{
var i = input.ToArray();
var o = new byte[_encryptor.GetOutputSize(i.Length)];
var res = _encryptor.ProcessBytes(i, 0, i.Length, o, 0);
o.CopyTo(output);
return res;
}

#region Cipher Info
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
{ "chacha20-ietf", new CipherInfo("chacha20-ietf", 32, 12, CipherFamily.Chacha20) },
};
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers;
}

protected override Dictionary<string, CipherInfo> GetCiphers()
{
return _ciphers;
}
#endregion
}
}

+ 0
- 76
Shadowsocks.Net/Crypto/Stream/StreamChachaNaClCrypto.cs View File

@@ -1,76 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using NaCl.Core;

namespace Shadowsocks.Net.Crypto.Stream
{
public class StreamChachaNaClCrypto : StreamCrypto
{
const int BlockSize = 64;

// tcp is stream, which can split into chunks at unexpected position...
// so we need some special handling, as we can't read all data before encrypt

// we did it in AEADEncryptor.cs for AEAD, it can operate at block level
// but we need do it ourselves in stream cipher.

// when new data arrive, put it on correct offset
// and update it, ignore other data, get it in correct offset...
readonly byte[] chachaBuf = new byte[MaxInputSize + BlockSize];
// the 'correct offset', always in 0~BlockSize range, so input data always fit into buffer
int remain = 0;
// increase counter manually...
int ic = 0;
public StreamChachaNaClCrypto(string method, string password) : base(method, password)
{
}

protected override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
return CipherUpdate(cipher, plain, false);
}

protected override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
return CipherUpdate(plain, cipher, true);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc)
{
// about performance problem:
// as a part of hacking for streaming, we need manually increase IC
// so we need new Chacha20
// and to get correct position, copy paste array everytime is required
// NaCl.Core has no int Encrypt(ReadOnlySpan<byte>,Span<byte>)...

int len = i.Length;
int pad = remain;
i.CopyTo(chachaBuf.AsSpan(pad));
var chacha = new ChaCha20(key, ic);
var p = enc ? chacha.Encrypt(chachaBuf, iv) : chacha.Decrypt(chachaBuf, iv);
p.AsSpan(pad, len).CopyTo(o);
pad += len;
ic += pad / BlockSize;
remain = pad % BlockSize;
return len;
}

#region Cipher Info
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
{ "chacha20-ietf", new CipherInfo("chacha20-ietf", 32, 12, CipherFamily.Chacha20) },
};
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers;
}

protected override Dictionary<string, CipherInfo> GetCiphers()
{
return _ciphers;
}
#endregion
}
}

+ 0
- 1
Shadowsocks.Net/Shadowsocks.Net.csproj View File

@@ -6,7 +6,6 @@

<ItemGroup>
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.6" />
<PackageReference Include="NaCl.Core" Version="2.0.0" />
<PackageReference Include="Splat" Version="9.6.1" />
</ItemGroup>



Loading…
Cancel
Save