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.

AEADSodiumEncryptor.cs 4.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using Shadowsocks.Controller;
  5. using Shadowsocks.Encryption.Exception;
  6. namespace Shadowsocks.Encryption.AEAD
  7. {
  8. public class AEADSodiumEncryptor
  9. : AEADEncryptor, IDisposable
  10. {
  11. private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
  12. private const int CIPHER_AES256GCM = 2;
  13. private byte[] _sodiumEncSubkey;
  14. private byte[] _sodiumDecSubkey;
  15. public AEADSodiumEncryptor(string method, string password)
  16. : base(method, password)
  17. {
  18. _sodiumEncSubkey = new byte[keyLen];
  19. _sodiumDecSubkey = new byte[keyLen];
  20. }
  21. private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
  22. {
  23. {"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
  24. {"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
  25. };
  26. public static List<string> SupportedCiphers()
  27. {
  28. return new List<string>(_ciphers.Keys);
  29. }
  30. protected override Dictionary<string, EncryptorInfo> getCiphers()
  31. {
  32. return _ciphers;
  33. }
  34. public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
  35. {
  36. base.InitCipher(salt, isEncrypt, isUdp);
  37. DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey,
  38. isEncrypt ? _sodiumEncSubkey : _sodiumDecSubkey);
  39. }
  40. public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
  41. {
  42. Debug.Assert(_sodiumEncSubkey != null);
  43. // buf: all plaintext
  44. // outbuf: ciphertext + tag
  45. int ret;
  46. ulong encClen = 0;
  47. Logging.Dump("_encNonce before enc", _encNonce, nonceLen);
  48. Logging.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen);
  49. Logging.Dump("before cipherEncrypt: plain", plaintext, (int) plen);
  50. switch (_cipher)
  51. {
  52. case CIPHER_CHACHA20IETFPOLY1305:
  53. ret = Sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, ref encClen,
  54. plaintext, (ulong) plen,
  55. null, 0,
  56. null, _encNonce,
  57. _sodiumEncSubkey);
  58. break;
  59. case CIPHER_AES256GCM:
  60. ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
  61. plaintext, (ulong)plen,
  62. null, 0,
  63. null, _encNonce,
  64. _sodiumEncSubkey);
  65. break;
  66. default:
  67. throw new System.Exception("not implemented");
  68. }
  69. if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
  70. Logging.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen);
  71. clen = (uint) encClen;
  72. }
  73. public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
  74. {
  75. Debug.Assert(_sodiumDecSubkey != null);
  76. // buf: ciphertext + tag
  77. // outbuf: plaintext
  78. int ret;
  79. ulong decPlen = 0;
  80. Logging.Dump("_decNonce before dec", _decNonce, nonceLen);
  81. Logging.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen);
  82. Logging.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen);
  83. switch (_cipher)
  84. {
  85. case CIPHER_CHACHA20IETFPOLY1305:
  86. ret = Sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, ref decPlen,
  87. null,
  88. ciphertext, (ulong) clen,
  89. null, 0,
  90. _decNonce, _sodiumDecSubkey);
  91. break;
  92. case CIPHER_AES256GCM:
  93. ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
  94. null,
  95. ciphertext, (ulong)clen,
  96. null, 0,
  97. _decNonce, _sodiumDecSubkey);
  98. break;
  99. default:
  100. throw new System.Exception("not implemented");
  101. }
  102. if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
  103. Logging.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen);
  104. plen = (uint) decPlen;
  105. }
  106. public override void Dispose()
  107. {
  108. }
  109. }
  110. }