You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

AeadBlockMessage.cs 2.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using Shadowsocks.Protocol.Shadowsocks.Crypto;
  2. using System;
  3. using System.Diagnostics.CodeAnalysis;
  4. namespace Shadowsocks.Protocol.Shadowsocks
  5. {
  6. class AeadBlockMessage : IProtocolMessage
  7. {
  8. public Memory<byte> Data;
  9. private readonly int tagLength;
  10. private readonly ICrypto aead;
  11. private Memory<byte> nonce;
  12. private int expectedDataLength;
  13. public AeadBlockMessage(ICrypto aead, Memory<byte> nonce, CryptoParameter parameter)
  14. {
  15. this.aead = aead;
  16. this.nonce = nonce;
  17. tagLength = parameter.TagSize;
  18. }
  19. public bool Equals([AllowNull] IProtocolMessage other) => throw new NotImplementedException();
  20. public int Serialize(Memory<byte> buffer)
  21. {
  22. var len = Data.Length + 2 * tagLength + 2;
  23. if (buffer.Length < len)
  24. throw Util.BufferTooSmall(len, buffer.Length, nameof(buffer));
  25. Memory<byte> m = new byte[2];
  26. m.Span[0] = (byte)(Data.Length / 256);
  27. m.Span[1] = (byte)(Data.Length % 256);
  28. var len1 = aead.Encrypt(nonce.Span, m.Span, buffer.Span);
  29. Util.SodiumIncrement(nonce.Span);
  30. buffer = buffer.Slice(len1);
  31. aead.Encrypt(nonce.Span, Data.Span, buffer.Span);
  32. Util.SodiumIncrement(nonce.Span);
  33. return len;
  34. }
  35. public (bool success, int length) TryLoad(ReadOnlyMemory<byte> buffer)
  36. {
  37. int len;
  38. if (expectedDataLength == 0)
  39. {
  40. if (buffer.Length < tagLength + 2) return (false, tagLength + 2);
  41. // decrypt length
  42. Memory<byte> m = new byte[2];
  43. len = aead.Decrypt(nonce.Span, m.Span, buffer.Span);
  44. Util.SodiumIncrement(nonce.Span);
  45. if (len != 2) return (false, 0);
  46. expectedDataLength = m.Span[0] * 256 + m.Span[1];
  47. if (expectedDataLength > 0x3fff) return (false, 0);
  48. }
  49. var totalLength = expectedDataLength + 2 * tagLength + 2;
  50. if (buffer.Length < totalLength) return (false, totalLength);
  51. // decrypt data
  52. var dataBuffer = buffer.Slice(tagLength + 2);
  53. Data = new byte[expectedDataLength];
  54. len = aead.Decrypt(nonce.Span, Data.Span, dataBuffer.Span);
  55. Util.SodiumIncrement(nonce.Span);
  56. if (len != expectedDataLength) return (false, 0);
  57. return (true, totalLength);
  58. }
  59. }
  60. }