Browse Source

make compiler happy in encryption

pull/2865/head
Student Main 5 years ago
parent
commit
92137d28aa
12 changed files with 96 additions and 95 deletions
  1. +3
    -3
      shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs
  2. +32
    -39
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  3. +10
    -15
      shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs
  4. +1
    -0
      shadowsocks-csharp/Encryption/EncryptorBase.cs
  5. +5
    -5
      shadowsocks-csharp/Encryption/EncryptorFactory.cs
  6. +4
    -5
      shadowsocks-csharp/Encryption/Stream/ExtendedCfbBlockCipher.cs
  7. +8
    -6
      shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs
  8. +6
    -3
      shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs
  9. +14
    -10
      shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs
  10. +1
    -1
      shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs
  11. +8
    -4
      shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs
  12. +4
    -4
      test/CryptographyTest.cs

+ 3
- 3
shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs View File

@@ -18,7 +18,7 @@ namespace Shadowsocks.Encryption.AEAD
{"aes-256-gcm", new CipherInfo("aes-256-gcm", 32, 32, 12, 16, CipherFamily.AesGcm)},
};

protected override Dictionary<string, CipherInfo> getCiphers()
protected override Dictionary<string, CipherInfo> GetCiphers()
{
return _ciphers;
}
@@ -32,7 +32,7 @@ namespace Shadowsocks.Encryption.AEAD
public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
using AesGcm aes = new AesGcm(sessionKey);
aes.Encrypt(nonce.AsSpan(), plain, cipher.Slice(0, plain.Length), cipher.Slice(plain.Length, tagLen));
aes.Encrypt(nonce, plain, cipher.Slice(0, plain.Length), cipher.Slice(plain.Length, tagLen));
return plain.Length + tagLen;
}

@@ -42,7 +42,7 @@ namespace Shadowsocks.Encryption.AEAD
using AesGcm aes = new AesGcm(sessionKey);
ReadOnlySpan<byte> ciphertxt = cipher.Slice(0, clen);
ReadOnlySpan<byte> tag = cipher.Slice(clen);
aes.Decrypt(nonce.AsSpan(), ciphertxt, tag, plain.Slice(0, clen));
aes.Decrypt(nonce, ciphertxt, tag, plain.Slice(0, clen));
return clen;
}
}

+ 32
- 39
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -5,26 +5,25 @@ using Shadowsocks.Encryption.Stream;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
namespace Shadowsocks.Encryption.AEAD
{
public abstract class AEADEncryptor : EncryptorBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
// We are using the same saltLen and keyLen
private const string Info = "ss-subkey";
private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info);
// every connection should create its own buffer
private byte[] sharedBuffer = new byte[65536];
private readonly byte[] buffer = new byte[65536];
private int bufPtr = 0;
public const int ChunkLengthBytes = 2;
public const uint ChunkLengthMask = 0x3FFFu;
protected Dictionary<string, CipherInfo> ciphers;
protected CipherFamily cipherFamily;
protected CipherInfo CipherInfo;
protected static byte[] masterKey = Array.Empty<byte>();
@@ -46,7 +45,7 @@ namespace Shadowsocks.Encryption.AEAD
public AEADEncryptor(string method, string password)
: base(method, password)
{
CipherInfo = getCiphers()[method.ToLower()];
CipherInfo = GetCiphers()[method.ToLower()];
cipherFamily = CipherInfo.Type;
AEADCipherParameter parameter = (AEADCipherParameter)CipherInfo.CipherParameter;
keyLen = parameter.KeySize;
@@ -55,13 +54,15 @@ namespace Shadowsocks.Encryption.AEAD
nonceLen = parameter.NonceSize;
InitKey(password);
salt = new byte[saltLen];
// Initialize all-zero nonce for each connection
nonce = new byte[nonceLen];
logger.Dump($"masterkey {instanceId}", masterKey, keyLen);
logger.Dump($"nonce {instanceId}", nonce, keyLen);
}
protected abstract Dictionary<string, CipherInfo> getCiphers();
protected abstract Dictionary<string, CipherInfo> GetCiphers();
protected void InitKey(string password)
{
@@ -77,32 +78,18 @@ namespace Shadowsocks.Encryption.AEAD
Array.Resize(ref masterKey, keyLen);
}
DeriveKey(passbuf, masterKey, keyLen);
StreamEncryptor.LegacyDeriveKey(passbuf, masterKey, keyLen);
// init session key
sessionKey = new byte[keyLen];
}
public void DeriveKey(byte[] password, byte[] key, int keylen)
{
StreamEncryptor.LegacyDeriveKey(password, key, keylen);
}
public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey)
{
CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey, 0);
}
protected void IncrementNonce()
{
CryptoUtils.SodiumIncrement(nonce);
}
public virtual void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
public virtual void InitCipher(byte[] salt, bool isEncrypt)
{
this.salt = new byte[saltLen];
Array.Copy(salt, this.salt, saltLen);
DeriveSessionKey(salt, masterKey, sessionKey);
CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey, 0);
logger.Dump($"salt {instanceId}", salt, saltLen);
logger.Dump($"sessionkey {instanceId}", sessionKey, keyLen);
}
@@ -112,10 +99,11 @@ namespace Shadowsocks.Encryption.AEAD
#region TCP
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
// push data
Span<byte> tmp = sharedBuffer.AsSpan(0, plain.Length + bufPtr);
Span<byte> tmp = buffer.AsSpan(0, plain.Length + bufPtr);
plain.CopyTo(tmp.Slice(bufPtr));
int outlength = 0;
@@ -124,7 +112,7 @@ namespace Shadowsocks.Encryption.AEAD
saltReady = true;
// Generate salt
byte[] saltBytes = RNG.GetBytes(saltLen);
InitCipher(saltBytes, true, false);
InitCipher(saltBytes, true);
saltBytes.CopyTo(cipher);
outlength = saltLen;
}
@@ -162,7 +150,7 @@ namespace Shadowsocks.Encryption.AEAD
logger.Debug("enc outbuf almost full, giving up");
// write rest data to head of shared buffer
tmp.CopyTo(sharedBuffer);
tmp.CopyTo(buffer);
bufPtr = tmp.Length;
return outlength;
@@ -177,11 +165,12 @@ namespace Shadowsocks.Encryption.AEAD
}
}
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
int outlength = 0;
// drop all into buffer
Span<byte> tmp = sharedBuffer.AsSpan(0, cipher.Length + bufPtr);
Span<byte> tmp = buffer.AsSpan(0, cipher.Length + bufPtr);
cipher.CopyTo(tmp.Slice(bufPtr));
int bufSize = tmp.Length;
@@ -192,7 +181,7 @@ namespace Shadowsocks.Encryption.AEAD
if (bufSize <= saltLen)
{
// need more, write back cache
tmp.CopyTo(sharedBuffer);
tmp.CopyTo(buffer);
bufPtr = tmp.Length;
return outlength;
}
@@ -202,7 +191,7 @@ namespace Shadowsocks.Encryption.AEAD
byte[] salt = tmp.Slice(0, saltLen).ToArray();
tmp = tmp.Slice(saltLen);
InitCipher(salt, false, false);
InitCipher(salt, false);
logger.Debug("get salt len " + saltLen);
}
@@ -222,7 +211,7 @@ namespace Shadowsocks.Encryption.AEAD
{
// so we only have chunk length and its tag?
// wait more
tmp.CopyTo(sharedBuffer);
tmp.CopyTo(buffer);
bufPtr = tmp.Length;
return outlength;
}
@@ -231,7 +220,7 @@ namespace Shadowsocks.Encryption.AEAD
if (len <= 0)
{
// no chunk decrypted
tmp.CopyTo(sharedBuffer);
tmp.CopyTo(buffer);
bufPtr = tmp.Length;
return outlength;
}
@@ -243,7 +232,7 @@ namespace Shadowsocks.Encryption.AEAD
if (outlength + 100 > TCPHandler.BufferSize)
{
logger.Debug("dec outbuf almost full, giving up");
tmp.CopyTo(sharedBuffer);
tmp.CopyTo(buffer);
bufPtr = tmp.Length;
return outlength;
}
@@ -260,21 +249,24 @@ namespace Shadowsocks.Encryption.AEAD
#endregion
#region UDP
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
RNG.GetSpan(cipher.Slice(0, saltLen));
InitCipher(cipher.Slice(0, saltLen).ToArray(), true, true);
InitCipher(cipher.Slice(0, saltLen).ToArray(), true);
return saltLen + CipherEncrypt(plain, cipher.Slice(saltLen));
}
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
InitCipher(cipher.Slice(0, saltLen).ToArray(), false, true);
InitCipher(cipher.Slice(0, saltLen).ToArray(), false);
return CipherDecrypt(plain, cipher.Slice(saltLen));
}
#endregion
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private int ChunkEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
if (plain.Length > ChunkLengthMask)
@@ -285,13 +277,14 @@ namespace Shadowsocks.Encryption.AEAD
byte[] lenbuf = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)plain.Length));
int cipherLenSize = CipherEncrypt(lenbuf, cipher);
IncrementNonce();
CryptoUtils.SodiumIncrement(nonce);
int cipherDataSize = CipherEncrypt(plain, cipher.Slice(cipherLenSize));
IncrementNonce();
CryptoUtils.SodiumIncrement(nonce);
return cipherLenSize + cipherDataSize;
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private int ChunkDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
// try to dec chunk len
@@ -311,11 +304,11 @@ namespace Shadowsocks.Encryption.AEAD
logger.Debug("No data to decrypt one chunk");
return 0;
}
IncrementNonce();
CryptoUtils.SodiumIncrement(nonce);
// we have enough data to decrypt one chunk
// drop chunk len and its tag from buffer
int len = CipherDecrypt(plain, cipher.Slice(ChunkLengthBytes + tagLen, chunkLength + tagLen));
IncrementNonce();
CryptoUtils.SodiumIncrement(nonce);
return len;
}
}

+ 10
- 15
shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs View File

@@ -8,7 +8,7 @@ namespace Shadowsocks.Encryption.AEAD
public class AEADNaClEncryptor : AEADEncryptor
{

SnufflePoly1305 enc;
SnufflePoly1305? enc;
public AEADNaClEncryptor(string method, string password) : base(method, password)
{
}
@@ -20,7 +20,7 @@ namespace Shadowsocks.Encryption.AEAD
{"xchacha20-ietf-poly1305", new CipherInfo("xchacha20-ietf-poly1305",32, 32, 24, 16, CipherFamily.XChacha20Poly1305)},
};

protected override Dictionary<string, CipherInfo> getCiphers()
protected override Dictionary<string, CipherInfo> GetCiphers()
{
return _ciphers;
}
@@ -31,31 +31,26 @@ namespace Shadowsocks.Encryption.AEAD
}
#endregion

public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
public override void InitCipher(byte[] salt, bool isEncrypt)
{
base.InitCipher(salt, isEncrypt, isUdp);
switch (cipherFamily)
base.InitCipher(salt, isEncrypt);
enc = cipherFamily switch
{
default:
case CipherFamily.Chacha20Poly1305:
enc = new ChaCha20Poly1305(sessionKey);
break;
case CipherFamily.XChacha20Poly1305:
enc = new XChaCha20Poly1305(sessionKey);
break;
}
CipherFamily.XChacha20Poly1305 => new XChaCha20Poly1305(sessionKey),
_ => new ChaCha20Poly1305(sessionKey),
};
}

public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
byte[] ct = enc.Encrypt(plain, null, nonce);
byte[] ct = enc!.Encrypt(plain, null, nonce);
ct.CopyTo(cipher);
return ct.Length;
}

public override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
byte[] pt = enc.Decrypt(cipher, null, nonce);
byte[] pt = enc!.Decrypt(cipher, null, nonce);
pt.CopyTo(plain);
return pt.Length;
}


+ 1
- 0
shadowsocks-csharp/Encryption/EncryptorBase.cs View File

@@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
namespace Shadowsocks.Encryption
{


+ 5
- 5
shadowsocks-csharp/Encryption/EncryptorFactory.cs View File

@@ -11,8 +11,8 @@ namespace Shadowsocks.Encryption
{
public static string DefaultCipher = "chacha20-ietf-poly1305";
private static Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>();
private static Dictionary<string, CipherInfo> ciphers = new Dictionary<string, CipherInfo>();
private static readonly Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>();
private static readonly Dictionary<string, CipherInfo> ciphers = new Dictionary<string, CipherInfo>();
private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) };
static EncryptorFactory()
@@ -33,12 +33,12 @@ namespace Shadowsocks.Encryption
_registeredEncryptors.Add(method.Key, typeof(StreamRc4NativeEncryptor));
}
}
foreach (var method in StreamAesBouncyCastleEncryptor.SupportedCiphers())
foreach (var method in StreamAesCfbBouncyCastleEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(StreamAesBouncyCastleEncryptor));
_registeredEncryptors.Add(method.Key, typeof(StreamAesCfbBouncyCastleEncryptor));
}
}
foreach (var method in StreamChachaNaClEncryptor.SupportedCiphers())
@@ -77,7 +77,7 @@ namespace Shadowsocks.Encryption
}
method = method.ToLowerInvariant();
bool ok = _registeredEncryptors.TryGetValue(method, out Type t);
bool ok = _registeredEncryptors.TryGetValue(method, out Type? t);
if (!ok)
{
t = _registeredEncryptors[DefaultCipher];


+ 4
- 5
shadowsocks-csharp/Encryption/Stream/ExtendedCfbBlockCipher.cs View File

@@ -13,9 +13,9 @@ namespace Org.BouncyCastle.Crypto.Modes
public class ExtendedCfbBlockCipher
: IBlockCipher
{
private byte[] IV;
private byte[] cfbV;
private byte[] cfbOutV;
private readonly byte[] IV;
private readonly byte[] cfbV;
private readonly byte[] cfbOutV;
private bool encrypting;

private readonly int blockSize;
@@ -63,9 +63,8 @@ namespace Org.BouncyCastle.Crypto.Modes
ICipherParameters parameters)
{
encrypting = forEncryption;
if (parameters is ParametersWithIV)
if (parameters is ParametersWithIV ivParam)
{
ParametersWithIV ivParam = (ParametersWithIV)parameters;
byte[] iv = ivParam.GetIV();
int diff = IV.Length - iv.Length;
Array.Copy(iv, 0, IV, diff, iv.Length);


+ 8
- 6
shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs View File

@@ -3,23 +3,24 @@ using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Shadowsocks.Encryption.Stream
{

public class StreamAesBouncyCastleEncryptor : StreamEncryptor
public class StreamAesCfbBouncyCastleEncryptor : StreamEncryptor
{
byte[] cfbBuf = new byte[MaxInputSize + 128];
readonly byte[] cfbBuf = new byte[MaxInputSize + 128];
int ptr = 0;
readonly ExtendedCfbBlockCipher b;
public StreamAesBouncyCastleEncryptor(string method, string password) : base(method, password)
public StreamAesCfbBouncyCastleEncryptor(string method, string password) : base(method, password)
{
b = new ExtendedCfbBlockCipher(new AesEngine(), 128);
}

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

@@ -35,6 +36,7 @@ namespace Shadowsocks.Encryption.Stream
return cipher.Length;
}

[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private void CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o)
{
Span<byte> ob = new byte[o.Length + 128];
@@ -82,7 +84,7 @@ namespace Shadowsocks.Encryption.Stream
return _ciphers;
}

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


+ 6
- 3
shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using NaCl.Core;

namespace Shadowsocks.Encryption.Stream
@@ -7,15 +8,16 @@ namespace Shadowsocks.Encryption.Stream
public class StreamChachaNaClEncryptor : StreamEncryptor
{
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...
byte[] chachaBuf = new byte[MaxInputSize + BlockSize];
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...
@@ -34,6 +36,7 @@ namespace Shadowsocks.Encryption.Stream
return CipherUpdate(plain, cipher, true);
}

[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc)
{
int len = i.Length;
@@ -58,7 +61,7 @@ namespace Shadowsocks.Encryption.Stream
return _ciphers;
}

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


+ 14
- 10
shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs View File

@@ -1,6 +1,7 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Shadowsocks.Encryption.Stream
@@ -26,7 +27,7 @@ namespace Shadowsocks.Encryption.Stream
public StreamEncryptor(string method, string password)
: base(method, password)
{
CipherInfo = getCiphers()[method.ToLower()];
CipherInfo = GetCiphers()[method.ToLower()];
cipherFamily = CipherInfo.Type;
StreamCipherParameter parameter = (StreamCipherParameter)CipherInfo.CipherParameter;
keyLen = parameter.KeySize;
@@ -37,7 +38,7 @@ namespace Shadowsocks.Encryption.Stream
logger.Dump($"key {instanceId}", key, keyLen);
}
protected abstract Dictionary<string, CipherInfo> getCiphers();
protected abstract Dictionary<string, CipherInfo> GetCiphers();
private void InitKey(string password)
{
@@ -51,6 +52,7 @@ namespace Shadowsocks.Encryption.Stream
LegacyDeriveKey(passbuf, key, keyLen);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen)
{
byte[] result = new byte[password.Length + MD5Length];
@@ -73,7 +75,7 @@ namespace Shadowsocks.Encryption.Stream
}
}
protected virtual void initCipher(byte[] iv, bool isEncrypt)
protected virtual void InitCipher(byte[] iv, bool isEncrypt)
{
if (ivLen == 0)
{
@@ -88,6 +90,7 @@ namespace Shadowsocks.Encryption.Stream
protected abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher);
#region TCP
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
int cipherOffset = 0;
@@ -96,7 +99,7 @@ namespace Shadowsocks.Encryption.Stream
{
// Generate IV
byte[] ivBytes = RNG.GetBytes(ivLen);
initCipher(ivBytes, true);
InitCipher(ivBytes, true);
ivBytes.CopyTo(cipher);
cipherOffset = ivLen;
cipher = cipher.Slice(cipherOffset);
@@ -111,9 +114,9 @@ namespace Shadowsocks.Encryption.Stream
}
private int recieveCtr = 0;
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
Span<byte> tmp;// = cipher;
logger.Trace($"{instanceId} decrypt TCP, read iv: {!ivReady}");
int cipherOffset = 0;
@@ -135,14 +138,13 @@ namespace Shadowsocks.Encryption.Stream
{
// read iv
byte[] iv = sharedBuffer.AsSpan(0, ivLen).ToArray();
initCipher(iv, false);
InitCipher(iv, false);
}
else
{
initCipher(Array.Empty<byte>(), false);
InitCipher(Array.Empty<byte>(), false);
}
cipherOffset += ivLen;
tmp = sharedBuffer.AsSpan(ivLen, recieveCtr - ivLen);
}
// read all data from buffer
@@ -156,17 +158,19 @@ namespace Shadowsocks.Encryption.Stream
#endregion
#region UDP
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
byte[] iv = RNG.GetBytes(ivLen);
iv.CopyTo(cipher);
initCipher(iv, true);
InitCipher(iv, true);
return ivLen + CipherEncrypt(plain, cipher.Slice(ivLen));
}
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.AggressiveOptimization)]
public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
initCipher(cipher.Slice(0, ivLen).ToArray(), false);
InitCipher(cipher.Slice(0, ivLen).ToArray(), false);
return CipherDecrypt(plain, cipher.Slice(ivLen));
}


+ 1
- 1
shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs View File

@@ -33,7 +33,7 @@ namespace Shadowsocks.Encryption.Stream
return _ciphers;
}

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


+ 8
- 4
shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Shadowsocks.Encryption.Stream
{
@@ -11,9 +12,9 @@ namespace Shadowsocks.Encryption.Stream
{
}

protected override void initCipher(byte[] iv, bool isEncrypt)
protected override void InitCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
base.InitCipher(iv, isEncrypt);
// rc4-md5 is rc4 with md5 based session key
if (cipherFamily == CipherFamily.Rc4Md5)
{
@@ -39,6 +40,7 @@ namespace Shadowsocks.Encryption.Stream
return CipherUpdate(cipher, plain);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o)
{
// don't know why we need third array, but it works...
@@ -62,7 +64,7 @@ namespace Shadowsocks.Encryption.Stream
return _ciphers;
}

protected override Dictionary<string, CipherInfo> getCiphers()
protected override Dictionary<string, CipherInfo> GetCiphers()
{
return _ciphers;
}
@@ -75,7 +77,7 @@ namespace Shadowsocks.Encryption.Stream
public int index2 = 0;
}

private Context ctx = new Context();
private readonly Context ctx = new Context();

private byte[] SBox(byte[] key)
{
@@ -96,6 +98,7 @@ namespace Shadowsocks.Encryption.Stream
return s;
}

[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private void RC4(Context ctx, Span<byte> s, Span<byte> data, int length)
{
for (int n = 0; n < length; n++)
@@ -110,6 +113,7 @@ namespace Shadowsocks.Encryption.Stream
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(Span<byte> s, int i, int j)
{
byte c = s[i];


+ 4
- 4
test/CryptographyTest.cs View File

@@ -11,7 +11,7 @@ namespace Shadowsocks.Test
[TestClass]
public class CryptographyTest
{
Random random = new Random();
readonly Random random = new Random();
[TestMethod]
@@ -161,9 +161,9 @@ namespace Shadowsocks.Test
[TestMethod]
public void TestStreamAesCfbBouncyCastleEncryption()
{
TestEncryptionMethod(typeof(StreamAesBouncyCastleEncryptor), "aes-128-cfb");
TestEncryptionMethod(typeof(StreamAesBouncyCastleEncryptor), "aes-192-cfb");
TestEncryptionMethod(typeof(StreamAesBouncyCastleEncryptor), "aes-256-cfb");
TestEncryptionMethod(typeof(StreamAesCfbBouncyCastleEncryptor), "aes-128-cfb");
TestEncryptionMethod(typeof(StreamAesCfbBouncyCastleEncryptor), "aes-192-cfb");
TestEncryptionMethod(typeof(StreamAesCfbBouncyCastleEncryptor), "aes-256-cfb");
}
[TestMethod]
public void TestStreamChachaNaClEncryption()


Loading…
Cancel
Save