TransferCodec.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System;
  2. using System.IO;
  3. using System.IO.Compression;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. namespace UdPunching
  7. {
  8. public static class TransferCodec
  9. {
  10. // [0.....15] GUID PeerId
  11. // [16....17] Encrypted data length prefix (LeInt16)
  12. // [18...END] Encrypted data content
  13. public static Guid ReadId(byte[] recvData)
  14. {
  15. return new Guid(recvData.Take(16).ToArray());
  16. }
  17. public static byte[] DecodeData(RSACryptoServiceProvider localKey, byte[] recvData)
  18. {
  19. recvData.ReadLeInt16(out var len, 16);
  20. var raw = recvData.Skip(18).Take(len).ToArray();
  21. var decompressed = Decompress(raw);
  22. var decodeData = localKey.Decrypt(decompressed, false);
  23. return decodeData;
  24. }
  25. public static byte[] Encode(RSACryptoServiceProvider receiverKey, Guid id, byte[] data)
  26. {
  27. var encryptedBytes = receiverKey.Encrypt(data, false);
  28. var compressedData = Compress(encryptedBytes);
  29. var buf = new byte[16 + 2 + compressedData.Length];
  30. var ptr = -1;
  31. ptr += id.WriteTo(buf, ++ptr); // 16
  32. ptr += compressedData.Length.WriteLeInt16To(buf, ++ptr); // 2
  33. compressedData.WriteTo(buf, ++ptr);
  34. return buf;
  35. }
  36. private static byte[] Compress(byte[] data)
  37. {
  38. using (var rawIn = new MemoryStream(data))
  39. using (var gzOut = new MemoryStream())
  40. using (var gZipStream = new GZipStream(gzOut, CompressionLevel.Optimal))
  41. using (var finalOut = new MemoryStream())
  42. {
  43. rawIn.CopyTo(gZipStream);
  44. gZipStream.Close();
  45. var compressed = gzOut.ToArray();
  46. if (compressed.Length >= data.Length)
  47. {
  48. finalOut.WriteByte(0);
  49. finalOut.Write(data, 0, data.Length);
  50. }
  51. else
  52. {
  53. finalOut.WriteByte(1);
  54. finalOut.Write(compressed, 0, compressed.Length);
  55. }
  56. return finalOut.ToArray();
  57. }
  58. }
  59. private static byte[] Decompress(byte[] data)
  60. {
  61. using (var rawIn = new MemoryStream(data))
  62. using (var finalOut = new MemoryStream())
  63. {
  64. if (rawIn.ReadByte() == 1)
  65. {
  66. using (var gZipStream = new GZipStream(rawIn, CompressionMode.Decompress))
  67. {
  68. gZipStream.CopyTo(finalOut);
  69. }
  70. }
  71. else
  72. {
  73. rawIn.CopyTo(finalOut);
  74. }
  75. return finalOut.ToArray();
  76. }
  77. }
  78. }
  79. }