Browse Source

drop byte array based Encrypt Decrypt

pull/2865/head
Student Main 5 years ago
parent
commit
a972813e45
6 changed files with 18 additions and 301 deletions
  1. +6
    -4
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  2. +6
    -6
      shadowsocks-csharp/Controller/Service/UDPRelay.cs
  3. +4
    -176
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  4. +0
    -8
      shadowsocks-csharp/Encryption/EncryptorBase.cs
  5. +0
    -5
      shadowsocks-csharp/Encryption/IEncryptor.cs
  6. +2
    -102
      shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs

+ 6
- 4
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -339,7 +339,7 @@ namespace Shadowsocks.Controller
if (bytesRead >= 5)
{
_command = _connetionRecvBuffer[1];
switch(_command)
switch (_command)
{
case CMD_CONNECT:
@@ -467,7 +467,7 @@ namespace Shadowsocks.Controller
break;
}
Logger.Debug($"connect to {dstAddr}:{dstPort}");
Logger.Debug($"connect to {dstAddr}:{dstPort}");
_destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort);
@@ -820,7 +820,8 @@ namespace Shadowsocks.Controller
{
try
{
decryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend);
bytesToSend = decryptor.Decrypt(_remoteSendBuffer, _remoteRecvBuffer.AsSpan(0, bytesRead));
// decryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend);
}
catch (CryptoErrorException)
{
@@ -893,7 +894,8 @@ namespace Shadowsocks.Controller
{
try
{
encryptor.Encrypt(_connetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
bytesToSend = encryptor.Encrypt(_connetionRecvBuffer.AsSpan(0, length), _connetionSendBuffer);
// encryptor.Encrypt(_connetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
}
catch (CryptoErrorException)
{


+ 6
- 6
shadowsocks-csharp/Controller/Service/UDPRelay.cs View File

@@ -96,11 +96,11 @@ namespace Shadowsocks.Controller
public void Send(byte[] data, int length)
{
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
byte[] dataIn = new byte[length - 3];
Array.Copy(data, 3, dataIn, 0, length - 3);
// byte[] dataIn = new byte[length - 3];
// Array.Copy(data, 3, dataIn, 0, length - 3);
byte[] dataOut = new byte[65536]; // enough space for AEAD ciphers
int outlen;
encryptor.EncryptUDP(dataIn, length - 3, dataOut, out outlen);
// encryptor.EncryptUDP(dataIn, length - 3, dataOut, out outlen);
int outlen = encryptor.EncryptUDP(data.AsSpan(3), dataOut);
logger.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay");
_remote?.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint);
}
@@ -124,8 +124,8 @@ namespace Shadowsocks.Controller
int outlen;
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
encryptor.DecryptUDP(_buffer, bytesRead, dataOut, out outlen);
// encryptor.DecryptUDP(_buffer, bytesRead, dataOut, out outlen);
outlen = encryptor.DecryptUDP(dataOut, _buffer.AsSpan(0, bytesRead));
byte[] sendBuf = new byte[outlen + 3];
Array.Copy(dataOut, 0, sendBuf, 3, outlen);


+ 4
- 176
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -57,6 +57,8 @@ namespace Shadowsocks.Encryption.AEAD
InitKey(password);
// 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();
@@ -99,9 +101,10 @@ namespace Shadowsocks.Encryption.AEAD
{
this.salt = new byte[saltLen];
Array.Copy(salt, this.salt, saltLen);
logger.Dump("Salt", salt, saltLen);
DeriveSessionKey(salt, masterKey, sessionKey);
logger.Dump($"salt {instanceId}", salt, saltLen);
logger.Dump($"sessionkey {instanceId}", sessionKey, keyLen);
}
public abstract int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher);
@@ -109,85 +112,6 @@ namespace Shadowsocks.Encryption.AEAD
#region TCP
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
// push data
buf.CopyTo(sharedBuffer, bufPtr);
Span<byte> tmp = sharedBuffer.AsSpan(0, length + bufPtr);
outlength = 0;
logger.Debug("---Start Encryption");
if (!saltReady)
{
saltReady = true;
// Generate salt
byte[] saltBytes = RNG.GetBytes(saltLen);
InitCipher(saltBytes, true, false);
Array.Copy(saltBytes, 0, outbuf, 0, saltLen);
outlength = saltLen;
logger.Debug($"_encryptSaltSent outlength {outlength}");
}
if (!tcpRequestSent)
{
tcpRequestSent = true;
// The first TCP request
byte[] encAddrBufBytes = new byte[AddressBufferLength + tagLen * 2 + ChunkLengthBytes];
// read addr byte to encrypt
byte[] addrBytes = tmp.Slice(0, AddressBufferLength).ToArray();
tmp = tmp.Slice(AddressBufferLength);
int encAddrBufLength = ChunkEncrypt(addrBytes, encAddrBufBytes);
Array.Copy(encAddrBufBytes, 0, outbuf, outlength, encAddrBufLength);
outlength += encAddrBufLength;
logger.Debug($"_tcpRequestSent outlength {outlength}");
}
// handle other chunks
while (true)
{
// calculate next chunk size
int bufSize = tmp.Length;
if (bufSize <= 0)
{
return;
}
int chunklength = (int)Math.Min(bufSize, ChunkLengthMask);
// read next chunk
byte[] chunkBytes = tmp.Slice(0, chunklength).ToArray();
tmp = tmp.Slice(chunklength);
byte[] encChunkBytes = new byte[chunklength + tagLen * 2 + ChunkLengthBytes];
int encChunkLength = ChunkEncrypt(chunkBytes, encChunkBytes);
Buffer.BlockCopy(encChunkBytes, 0, outbuf, outlength, encChunkLength);
outlength += encChunkLength;
logger.Debug("chunks enc outlength " + outlength);
// check if we have enough space for outbuf
// if not, keep buf for next run, at this condition, buffer is not empty
if (outlength + TCPHandler.ChunkOverheadSize > TCPHandler.BufferSize)
{
logger.Debug("enc outbuf almost full, giving up");
// write rest data to head of shared buffer
tmp.CopyTo(sharedBuffer);
bufPtr = tmp.Length;
return;
}
// check if buffer empty
bufSize = tmp.Length;
if (bufSize <= 0)
{
logger.Debug("No more data to encrypt, leaving");
return;
}
}
}
public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
// push data
@@ -253,86 +177,6 @@ namespace Shadowsocks.Encryption.AEAD
}
}
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
outlength = 0;
// drop all into buffer
buf.CopyTo(sharedBuffer, bufPtr);
Span<byte> tmp = buf.AsSpan(0, length + bufPtr);
int bufSize = tmp.Length;
logger.Debug("---Start Decryption");
if (!saltReady)
{
// check if we get the leading salt
if (bufSize <= saltLen)
{
// need more, write back cache
tmp.CopyTo(sharedBuffer);
bufPtr = tmp.Length;
return;
}
saltReady = true;
// buffer.Get(saltLen);
byte[] salt = tmp.Slice(0, saltLen).ToArray();
tmp = tmp.Slice(saltLen);
InitCipher(salt, false, false);
logger.Debug("get salt len " + saltLen);
}
// handle chunks
while (true)
{
bufSize = tmp.Length;
// check if we have any data
if (bufSize <= 0)
{
logger.Debug("No data in _decCircularBuffer");
return;
}
// first get chunk length
if (bufSize <= ChunkLengthBytes + tagLen)
{
// so we only have chunk length and its tag?
// wait more
tmp.CopyTo(sharedBuffer);
bufPtr = tmp.Length;
return;
}
int len = ChunkDecrypt(outbuf.AsSpan(outlength), tmp);
if (len <= 0)
{
tmp.CopyTo(sharedBuffer);
bufPtr = tmp.Length;
return;
}
tmp = tmp.Slice(ChunkLengthBytes + tagLen + len + tagLen);
// output to outbuf
outlength += len;
logger.Debug("aead dec outlength " + outlength);
if (outlength + 100 > TCPHandler.BufferSize)
{
logger.Debug("dec outbuf almost full, giving up");
tmp.CopyTo(sharedBuffer);
bufPtr = tmp.Length;
return;
}
bufSize = tmp.Length;
// check if we already done all of them
if (bufSize <= 0)
{
logger.Debug("No data in _decCircularBuffer, already all done");
return;
}
}
}
public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
int outlength = 0;
@@ -416,16 +260,6 @@ namespace Shadowsocks.Encryption.AEAD
#endregion
#region UDP
public override void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength)
{
// Generate salt
RNG.GetSpan(outbuf.AsSpan(0, saltLen));
InitCipher(outbuf, true, true);
outlength = saltLen + CipherEncrypt(
buf.AsSpan(0, length),
outbuf.AsSpan(saltLen, length + tagLen));
}
public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
RNG.GetSpan(cipher.Slice(0, saltLen));
@@ -433,12 +267,6 @@ namespace Shadowsocks.Encryption.AEAD
return saltLen + CipherEncrypt(plain, cipher.Slice(saltLen));
}
public override void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength)
{
InitCipher(buf, false, true);
outlength = CipherDecrypt(outbuf, buf.AsSpan(saltLen, length - saltLen));
}
public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
InitCipher(cipher.Slice(0, saltLen).ToArray(), false, true);


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

@@ -33,14 +33,6 @@ namespace Shadowsocks.Encryption
protected string Method;
protected string Password;
public abstract void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
public abstract void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
public abstract void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);
public abstract void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);
public override string ToString()
{
return $"{instanceId}({Method},{Password})";


+ 0
- 5
shadowsocks-csharp/Encryption/IEncryptor.cs View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
namespace Shadowsocks.Encryption
{
@@ -7,10 +6,6 @@ namespace Shadowsocks.Encryption
{
/* length == -1 means not used */
int AddressBufferLength { set; get; }
void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);
void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);
int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher);
int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher);
int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher);


+ 2
- 102
shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs View File

@@ -1,7 +1,6 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Shadowsocks.Encryption.Stream
@@ -89,34 +88,6 @@ namespace Shadowsocks.Encryption.Stream
protected abstract int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher);
#region TCP
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
int cipherOffset = 0;
Span<byte> tmp = buf.AsSpan(0, length);
logger.Trace($"{instanceId} encrypt TCP, generate iv: {!ivReady}");
if (!ivReady)
{
// Generate IV
byte[] ivBytes = RNG.GetBytes(ivLen);
initCipher(ivBytes, true);
Array.Copy(ivBytes, 0, outbuf, 0, ivLen);
cipherOffset = ivLen;
ivReady = true;
}
int size = tmp.Length;
byte[] cipher = new byte[size];
CipherEncrypt(tmp, cipher);
logger.DumpBase64($"plain {instanceId}", tmp.ToArray(), size);
logger.DumpBase64($"cipher {instanceId}", cipher, cipher.Length);
logger.Dump($"iv {instanceId}", iv, ivLen);
Buffer.BlockCopy(cipher, 0, outbuf, cipherOffset, size);
outlength = size + cipherOffset;
}
public override int Encrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
int cipherOffset = 0;
@@ -134,55 +105,12 @@ namespace Shadowsocks.Encryption.Stream
int clen = CipherEncrypt(plain, cipher);
logger.DumpBase64($"plain {instanceId}", plain);
logger.DumpBase64($"cipher {instanceId}", cipher);
logger.DumpBase64($"cipher {instanceId}", cipher.Slice(0, clen));
logger.Dump($"iv {instanceId}", iv, ivLen);
return clen + cipherOffset;
}
private int recieveCtr = 0;
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
{
Span<byte> tmp = buf.AsSpan(0, length);
logger.Trace($"{instanceId} decrypt TCP, read iv: {!ivReady}");
// is first packet, need read iv
if (!ivReady)
{
// push to buffer in case of not enough data
tmp.CopyTo(sharedBuffer.AsSpan(recieveCtr));
recieveCtr += tmp.Length;
// not enough data for read iv, return 0 byte data
if (recieveCtr <= ivLen)
{
outlength = 0;
return;
}
// start decryption
ivReady = true;
if (ivLen > 0)
{
// read iv
byte[] iv = sharedBuffer.AsSpan(0, ivLen).ToArray();
initCipher(iv, false);
}
else
{
initCipher(Array.Empty<byte>(), false);
}
tmp = sharedBuffer.AsSpan(ivLen, recieveCtr - ivLen);
}
// read all data from buffer
CipherDecrypt(outbuf, tmp);
logger.DumpBase64($"cipher {instanceId}", tmp.ToArray(), tmp.Length);
logger.DumpBase64($"plain {instanceId}", outbuf, tmp.Length);
logger.Dump($"iv {instanceId}", iv, ivLen);
outlength = tmp.Length;
}
public override int Decrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
Span<byte> tmp;// = cipher;
@@ -220,7 +148,7 @@ namespace Shadowsocks.Encryption.Stream
// read all data from buffer
int len = CipherDecrypt(plain, cipher.Slice(cipherOffset));
logger.DumpBase64($"cipher {instanceId}", cipher.Slice(cipherOffset));
logger.DumpBase64($"plain {instanceId}", plain);
logger.DumpBase64($"plain {instanceId}", plain.Slice(0, len));
logger.Dump($"iv {instanceId}", iv, ivLen);
return len;
}
@@ -228,20 +156,6 @@ namespace Shadowsocks.Encryption.Stream
#endregion
#region UDP
[MethodImpl(MethodImplOptions.Synchronized)]
public override void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength)
{
// Generate IV
RNG.GetBytes(outbuf, ivLen);
initCipher(outbuf, true);
lock (sharedBuffer)
{
CipherEncrypt(buf, sharedBuffer);
outlength = length + ivLen;
Buffer.BlockCopy(sharedBuffer, 0, outbuf, ivLen, length);
}
}
public override int EncryptUDP(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
byte[] iv = RNG.GetBytes(ivLen);
@@ -250,20 +164,6 @@ namespace Shadowsocks.Encryption.Stream
return ivLen + CipherEncrypt(plain, cipher.Slice(ivLen));
}
[MethodImpl(MethodImplOptions.Synchronized)]
public override void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength)
{
// Get IV from first pos
initCipher(buf, false);
outlength = length - ivLen;
lock (sharedBuffer)
{
// C# could be multi-threaded
Buffer.BlockCopy(buf, ivLen, sharedBuffer, 0, length - ivLen);
CipherDecrypt(outbuf, sharedBuffer);
}
}
public override int DecryptUDP(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
initCipher(cipher.Slice(0, ivLen).ToArray(), false);


Loading…
Cancel
Save