X448.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc8032;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC.Rfc7748
  9. {
  10. public abstract class X448
  11. {
  12. public const int PointSize = 56;
  13. public const int ScalarSize = 56;
  14. private const uint C_A = 156326;
  15. private const uint C_A24 = (C_A + 2)/4;
  16. //private static readonly uint[] Sqrt156324 = { 0x0551B193U, 0x07A21E17U, 0x0E635AD3U, 0x00812ABBU, 0x025B3F99U, 0x01605224U,
  17. // 0x0AF8CB32U, 0x0D2E7D68U, 0x06BA50FDU, 0x08E55693U, 0x0CB08EB4U, 0x02ABEBC1U, 0x051BA0BBU, 0x02F8812EU, 0x0829B611U,
  18. // 0x0BA4D3A0U };
  19. public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
  20. {
  21. ScalarMult(k, kOff, u, uOff, r, rOff);
  22. return !Arrays.AreAllZeroes(r, rOff, PointSize);
  23. }
  24. private static uint Decode32(byte[] bs, int off)
  25. {
  26. uint n = bs[off];
  27. n |= (uint)bs[++off] << 8;
  28. n |= (uint)bs[++off] << 16;
  29. n |= (uint)bs[++off] << 24;
  30. return n;
  31. }
  32. private static void DecodeScalar(byte[] k, int kOff, uint[] n)
  33. {
  34. for (int i = 0; i < 14; ++i)
  35. {
  36. n[i] = Decode32(k, kOff + i * 4);
  37. }
  38. n[ 0] &= 0xFFFFFFFCU;
  39. n[13] |= 0x80000000U;
  40. }
  41. public static void GeneratePrivateKey(SecureRandom random, byte[] k)
  42. {
  43. random.NextBytes(k);
  44. k[0] &= 0xFC;
  45. k[ScalarSize - 1] |= 0x80;
  46. }
  47. public static void GeneratePublicKey(byte[] k, int kOff, byte[] r, int rOff)
  48. {
  49. ScalarMultBase(k, kOff, r, rOff);
  50. }
  51. private static void PointDouble(uint[] x, uint[] z)
  52. {
  53. uint[] A = X448Field.Create();
  54. uint[] B = X448Field.Create();
  55. //X448Field.Apm(x, z, A, B);
  56. X448Field.Add(x, z, A);
  57. X448Field.Sub(x, z, B);
  58. X448Field.Sqr(A, A);
  59. X448Field.Sqr(B, B);
  60. X448Field.Mul(A, B, x);
  61. X448Field.Sub(A, B, A);
  62. X448Field.Mul(A, C_A24, z);
  63. X448Field.Add(z, B, z);
  64. X448Field.Mul(z, A, z);
  65. }
  66. public static void Precompute()
  67. {
  68. Ed448.Precompute();
  69. }
  70. public static void ScalarMult(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
  71. {
  72. uint[] n = new uint[14]; DecodeScalar(k, kOff, n);
  73. uint[] x1 = X448Field.Create(); X448Field.Decode(u, uOff, x1);
  74. uint[] x2 = X448Field.Create(); X448Field.Copy(x1, 0, x2, 0);
  75. uint[] z2 = X448Field.Create(); z2[0] = 1;
  76. uint[] x3 = X448Field.Create(); x3[0] = 1;
  77. uint[] z3 = X448Field.Create();
  78. uint[] t1 = X448Field.Create();
  79. uint[] t2 = X448Field.Create();
  80. Debug.Assert(n[13] >> 31 == 1U);
  81. int bit = 447, swap = 1;
  82. do
  83. {
  84. //X448Field.Apm(x3, z3, t1, x3);
  85. X448Field.Add(x3, z3, t1);
  86. X448Field.Sub(x3, z3, x3);
  87. //X448Field.Apm(x2, z2, z3, x2);
  88. X448Field.Add(x2, z2, z3);
  89. X448Field.Sub(x2, z2, x2);
  90. X448Field.Mul(t1, x2, t1);
  91. X448Field.Mul(x3, z3, x3);
  92. X448Field.Sqr(z3, z3);
  93. X448Field.Sqr(x2, x2);
  94. X448Field.Sub(z3, x2, t2);
  95. X448Field.Mul(t2, C_A24, z2);
  96. X448Field.Add(z2, x2, z2);
  97. X448Field.Mul(z2, t2, z2);
  98. X448Field.Mul(x2, z3, x2);
  99. //X448Field.Apm(t1, x3, x3, z3);
  100. X448Field.Sub(t1, x3, z3);
  101. X448Field.Add(t1, x3, x3);
  102. X448Field.Sqr(x3, x3);
  103. X448Field.Sqr(z3, z3);
  104. X448Field.Mul(z3, x1, z3);
  105. --bit;
  106. int word = bit >> 5, shift = bit & 0x1F;
  107. int kt = (int)(n[word] >> shift) & 1;
  108. swap ^= kt;
  109. X448Field.CSwap(swap, x2, x3);
  110. X448Field.CSwap(swap, z2, z3);
  111. swap = kt;
  112. }
  113. while (bit >= 2);
  114. Debug.Assert(swap == 0);
  115. for (int i = 0; i < 2; ++i)
  116. {
  117. PointDouble(x2, z2);
  118. }
  119. X448Field.Inv(z2, z2);
  120. X448Field.Mul(x2, z2, x2);
  121. X448Field.Normalize(x2);
  122. X448Field.Encode(x2, r, rOff);
  123. }
  124. public static void ScalarMultBase(byte[] k, int kOff, byte[] r, int rOff)
  125. {
  126. uint[] x = X448Field.Create();
  127. uint[] y = X448Field.Create();
  128. Ed448.ScalarMultBaseXY(k, kOff, x, y);
  129. X448Field.Inv(x, x);
  130. X448Field.Mul(x, y, x);
  131. X448Field.Sqr(x, x);
  132. X448Field.Normalize(x);
  133. X448Field.Encode(x, r, rOff);
  134. }
  135. }
  136. }
  137. #pragma warning restore
  138. #endif