X448.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc8032;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc7748
  9. {
  10. using F = X448Field;
  11. public static class X448
  12. {
  13. public const int PointSize = 56;
  14. public const int ScalarSize = 56;
  15. private const uint C_A = 156326;
  16. private const uint C_A24 = (C_A + 2)/4;
  17. //private static readonly uint[] Sqrt156324 = { 0x0551B193U, 0x07A21E17U, 0x0E635AD3U, 0x00812ABBU, 0x025B3F99U, 0x01605224U,
  18. // 0x0AF8CB32U, 0x0D2E7D68U, 0x06BA50FDU, 0x08E55693U, 0x0CB08EB4U, 0x02ABEBC1U, 0x051BA0BBU, 0x02F8812EU, 0x0829B611U,
  19. // 0x0BA4D3A0U };
  20. public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
  21. {
  22. ScalarMult(k, kOff, u, uOff, r, rOff);
  23. return !Arrays.AreAllZeroes(r, rOff, PointSize);
  24. }
  25. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  26. public static bool CalculateAgreement(ReadOnlySpan<byte> k, ReadOnlySpan<byte> u, Span<byte> r)
  27. {
  28. ScalarMult(k, u, r);
  29. return !Arrays.AreAllZeroes(r[..PointSize]);
  30. }
  31. #endif
  32. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  33. private static uint Decode32(ReadOnlySpan<byte> bs)
  34. {
  35. uint n = bs[0];
  36. n |= (uint)bs[1] << 8;
  37. n |= (uint)bs[2] << 16;
  38. n |= (uint)bs[3] << 24;
  39. return n;
  40. }
  41. private static void DecodeScalar(ReadOnlySpan<byte> k, uint[] n)
  42. {
  43. for (int i = 0; i < 14; ++i)
  44. {
  45. n[i] = Decode32(k[(i * 4)..]);
  46. }
  47. n[ 0] &= 0xFFFFFFFCU;
  48. n[13] |= 0x80000000U;
  49. }
  50. #else
  51. private static uint Decode32(byte[] bs, int off)
  52. {
  53. uint n = bs[off];
  54. n |= (uint)bs[++off] << 8;
  55. n |= (uint)bs[++off] << 16;
  56. n |= (uint)bs[++off] << 24;
  57. return n;
  58. }
  59. private static void DecodeScalar(byte[] k, int kOff, uint[] n)
  60. {
  61. for (int i = 0; i < 14; ++i)
  62. {
  63. n[i] = Decode32(k, kOff + i * 4);
  64. }
  65. n[ 0] &= 0xFFFFFFFCU;
  66. n[13] |= 0x80000000U;
  67. }
  68. #endif
  69. public static void GeneratePrivateKey(SecureRandom random, byte[] k)
  70. {
  71. if (k.Length != ScalarSize)
  72. throw new ArgumentException(nameof(k));
  73. random.NextBytes(k);
  74. k[0] &= 0xFC;
  75. k[ScalarSize - 1] |= 0x80;
  76. }
  77. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  78. public static void GeneratePrivateKey(SecureRandom random, Span<byte> k)
  79. {
  80. if (k.Length != ScalarSize)
  81. throw new ArgumentException(nameof(k));
  82. random.NextBytes(k);
  83. k[0] &= 0xFC;
  84. k[ScalarSize - 1] |= 0x80;
  85. }
  86. #endif
  87. public static void GeneratePublicKey(byte[] k, int kOff, byte[] r, int rOff)
  88. {
  89. ScalarMultBase(k, kOff, r, rOff);
  90. }
  91. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  92. public static void GeneratePublicKey(ReadOnlySpan<byte> k, Span<byte> r)
  93. {
  94. ScalarMultBase(k, r);
  95. }
  96. #endif
  97. private static void PointDouble(uint[] x, uint[] z)
  98. {
  99. uint[] a = F.Create();
  100. uint[] b = F.Create();
  101. //F.Apm(x, z, a, b);
  102. F.Add(x, z, a);
  103. F.Sub(x, z, b);
  104. F.Sqr(a, a);
  105. F.Sqr(b, b);
  106. F.Mul(a, b, x);
  107. F.Sub(a, b, a);
  108. F.Mul(a, C_A24, z);
  109. F.Add(z, b, z);
  110. F.Mul(z, a, z);
  111. }
  112. public static void Precompute()
  113. {
  114. Ed448.Precompute();
  115. }
  116. public static void ScalarMult(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
  117. {
  118. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  119. ScalarMult(k.AsSpan(kOff), u.AsSpan(uOff), r.AsSpan(rOff));
  120. #else
  121. uint[] n = new uint[14]; DecodeScalar(k, kOff, n);
  122. uint[] x1 = F.Create(); F.Decode(u, uOff, x1);
  123. uint[] x2 = F.Create(); F.Copy(x1, 0, x2, 0);
  124. uint[] z2 = F.Create(); z2[0] = 1;
  125. uint[] x3 = F.Create(); x3[0] = 1;
  126. uint[] z3 = F.Create();
  127. uint[] t1 = F.Create();
  128. uint[] t2 = F.Create();
  129. Debug.Assert(n[13] >> 31 == 1U);
  130. int bit = 447, swap = 1;
  131. do
  132. {
  133. //F.Apm(x3, z3, t1, x3);
  134. F.Add(x3, z3, t1);
  135. F.Sub(x3, z3, x3);
  136. //F.Apm(x2, z2, z3, x2);
  137. F.Add(x2, z2, z3);
  138. F.Sub(x2, z2, x2);
  139. F.Mul(t1, x2, t1);
  140. F.Mul(x3, z3, x3);
  141. F.Sqr(z3, z3);
  142. F.Sqr(x2, x2);
  143. F.Sub(z3, x2, t2);
  144. F.Mul(t2, C_A24, z2);
  145. F.Add(z2, x2, z2);
  146. F.Mul(z2, t2, z2);
  147. F.Mul(x2, z3, x2);
  148. //F.Apm(t1, x3, x3, z3);
  149. F.Sub(t1, x3, z3);
  150. F.Add(t1, x3, x3);
  151. F.Sqr(x3, x3);
  152. F.Sqr(z3, z3);
  153. F.Mul(z3, x1, z3);
  154. --bit;
  155. int word = bit >> 5, shift = bit & 0x1F;
  156. int kt = (int)(n[word] >> shift) & 1;
  157. swap ^= kt;
  158. F.CSwap(swap, x2, x3);
  159. F.CSwap(swap, z2, z3);
  160. swap = kt;
  161. }
  162. while (bit >= 2);
  163. Debug.Assert(swap == 0);
  164. for (int i = 0; i < 2; ++i)
  165. {
  166. PointDouble(x2, z2);
  167. }
  168. F.Inv(z2, z2);
  169. F.Mul(x2, z2, x2);
  170. F.Normalize(x2);
  171. F.Encode(x2, r, rOff);
  172. #endif
  173. }
  174. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  175. public static void ScalarMult(ReadOnlySpan<byte> k, ReadOnlySpan<byte> u, Span<byte> r)
  176. {
  177. uint[] n = new uint[14]; DecodeScalar(k, n);
  178. uint[] x1 = F.Create(); F.Decode(u, x1);
  179. uint[] x2 = F.Create(); F.Copy(x1, 0, x2, 0);
  180. uint[] z2 = F.Create(); z2[0] = 1;
  181. uint[] x3 = F.Create(); x3[0] = 1;
  182. uint[] z3 = F.Create();
  183. uint[] t1 = F.Create();
  184. uint[] t2 = F.Create();
  185. Debug.Assert(n[13] >> 31 == 1U);
  186. int bit = 447, swap = 1;
  187. do
  188. {
  189. //F.Apm(x3, z3, t1, x3);
  190. F.Add(x3, z3, t1);
  191. F.Sub(x3, z3, x3);
  192. //F.Apm(x2, z2, z3, x2);
  193. F.Add(x2, z2, z3);
  194. F.Sub(x2, z2, x2);
  195. F.Mul(t1, x2, t1);
  196. F.Mul(x3, z3, x3);
  197. F.Sqr(z3, z3);
  198. F.Sqr(x2, x2);
  199. F.Sub(z3, x2, t2);
  200. F.Mul(t2, C_A24, z2);
  201. F.Add(z2, x2, z2);
  202. F.Mul(z2, t2, z2);
  203. F.Mul(x2, z3, x2);
  204. //F.Apm(t1, x3, x3, z3);
  205. F.Sub(t1, x3, z3);
  206. F.Add(t1, x3, x3);
  207. F.Sqr(x3, x3);
  208. F.Sqr(z3, z3);
  209. F.Mul(z3, x1, z3);
  210. --bit;
  211. int word = bit >> 5, shift = bit & 0x1F;
  212. int kt = (int)(n[word] >> shift) & 1;
  213. swap ^= kt;
  214. F.CSwap(swap, x2, x3);
  215. F.CSwap(swap, z2, z3);
  216. swap = kt;
  217. }
  218. while (bit >= 2);
  219. Debug.Assert(swap == 0);
  220. for (int i = 0; i < 2; ++i)
  221. {
  222. PointDouble(x2, z2);
  223. }
  224. F.Inv(z2, z2);
  225. F.Mul(x2, z2, x2);
  226. F.Normalize(x2);
  227. F.Encode(x2, r);
  228. }
  229. #endif
  230. public static void ScalarMultBase(byte[] k, int kOff, byte[] r, int rOff)
  231. {
  232. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  233. ScalarMultBase(k.AsSpan(kOff), r.AsSpan(rOff));
  234. #else
  235. uint[] x = F.Create();
  236. uint[] y = F.Create();
  237. Ed448.ScalarMultBaseXY(k, kOff, x, y);
  238. F.Inv(x, x);
  239. F.Mul(x, y, x);
  240. F.Sqr(x, x);
  241. F.Normalize(x);
  242. F.Encode(x, r, rOff);
  243. #endif
  244. }
  245. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  246. public static void ScalarMultBase(ReadOnlySpan<byte> k, Span<byte> r)
  247. {
  248. uint[] x = F.Create();
  249. uint[] y = F.Create();
  250. Ed448.ScalarMultBaseXY(k, x, y);
  251. F.Inv(x, x);
  252. F.Mul(x, y, x);
  253. F.Sqr(x, x);
  254. F.Normalize(x);
  255. F.Encode(x, r);
  256. }
  257. #endif
  258. }
  259. }
  260. #pragma warning restore
  261. #endif