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.

CryptoUtils.cs 3.1 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using Org.BouncyCastle.Crypto.Digests;
  2. using Org.BouncyCastle.Crypto.Generators;
  3. using Org.BouncyCastle.Crypto.Parameters;
  4. using System;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Threading;
  8. namespace Shadowsocks.Protocol.Shadowsocks.Crypto
  9. {
  10. public static class CryptoUtils
  11. {
  12. private static readonly ThreadLocal<MD5> Md5Hasher = new ThreadLocal<MD5>(System.Security.Cryptography.MD5.Create);
  13. public static byte[] MD5(byte[] b)
  14. {
  15. var hash = new byte[16];
  16. Md5Hasher.Value?.TryComputeHash(b, hash, out _);
  17. return hash;
  18. }
  19. // currently useless, just keep api same
  20. public static Span<byte> MD5(Span<byte> span)
  21. {
  22. Span<byte> hash = new byte[16];
  23. Md5Hasher.Value?.TryComputeHash(span, hash, out _);
  24. return hash;
  25. }
  26. public static byte[] HKDF(int keylen, byte[] master, byte[] salt, byte[] info)
  27. {
  28. var ret = new byte[keylen];
  29. var degist = new Sha1Digest();
  30. var parameters = new HkdfParameters(master, salt, info);
  31. var hkdf = new HkdfBytesGenerator(degist);
  32. hkdf.Init(parameters);
  33. hkdf.GenerateBytes(ret, 0, keylen);
  34. return ret;
  35. }
  36. // currently useless, just keep api same, again
  37. public static Span<byte> HKDF(int keylen, Span<byte> master, Span<byte> salt, Span<byte> info)
  38. {
  39. var ret = new byte[keylen];
  40. var degist = new Sha1Digest();
  41. var parameters = new HkdfParameters(master.ToArray(), salt.ToArray(), info.ToArray());
  42. var hkdf = new HkdfBytesGenerator(degist);
  43. hkdf.Init(parameters);
  44. hkdf.GenerateBytes(ret, 0, keylen);
  45. return ret.AsSpan();
  46. }
  47. public static byte[] SSKDF(string password, int keylen)
  48. {
  49. var key = new byte[keylen];
  50. var pw = Encoding.UTF8.GetBytes(password);
  51. var result = new byte[password.Length + 16];
  52. var i = 0;
  53. var md5sum = Array.Empty<byte>();
  54. while (i < keylen)
  55. {
  56. if (i == 0)
  57. {
  58. md5sum = MD5(pw);
  59. }
  60. else
  61. {
  62. Array.Copy(md5sum, 0, result, 0, 16);
  63. Array.Copy(pw, 0, result, 16, password.Length);
  64. md5sum = MD5(result);
  65. }
  66. Array.Copy(md5sum, 0, key, i, Math.Min(16, keylen - i));
  67. i += 16;
  68. }
  69. return key;
  70. }
  71. public static void SodiumIncrement(Span<byte> salt)
  72. {
  73. for (var i = 0; i < salt.Length; ++i)
  74. {
  75. if (++salt[i] != 0)
  76. {
  77. break;
  78. }
  79. }
  80. }
  81. public static void RandomSpan(Span<byte> span)
  82. {
  83. using (var rng = RandomNumberGenerator.Create())
  84. {
  85. rng.GetBytes(span);
  86. }
  87. }
  88. }
  89. }