HMacDsaKCalculator.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  9. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers
  10. {
  11. /**
  12. * A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
  13. */
  14. public class HMacDsaKCalculator
  15. : IDsaKCalculator
  16. {
  17. private readonly HMac hMac;
  18. private readonly byte[] K;
  19. private readonly byte[] V;
  20. private BigInteger n;
  21. /**
  22. * Base constructor.
  23. *
  24. * @param digest digest to build the HMAC on.
  25. */
  26. public HMacDsaKCalculator(IDigest digest)
  27. {
  28. this.hMac = new HMac(digest);
  29. this.V = new byte[hMac.GetMacSize()];
  30. this.K = new byte[hMac.GetMacSize()];
  31. }
  32. public virtual bool IsDeterministic
  33. {
  34. get { return true; }
  35. }
  36. public virtual void Init(BigInteger n, SecureRandom random)
  37. {
  38. throw new InvalidOperationException("Operation not supported");
  39. }
  40. public void Init(BigInteger n, BigInteger d, byte[] message)
  41. {
  42. this.n = n;
  43. Arrays.Fill(V, 0x01);
  44. Arrays.Fill(K, 0);
  45. BigInteger mInt = BitsToInt(message);
  46. if (mInt.CompareTo(n) >= 0)
  47. {
  48. mInt = mInt.Subtract(n);
  49. }
  50. int size = BigIntegers.GetUnsignedByteLength(n);
  51. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  52. int xmSize = size * 2;
  53. Span<byte> xm = xmSize <= 512
  54. ? stackalloc byte[xmSize]
  55. : new byte[xmSize];
  56. BigIntegers.AsUnsignedByteArray(d, xm[..size]);
  57. BigIntegers.AsUnsignedByteArray(mInt, xm[size..]);
  58. #else
  59. byte[] x = BigIntegers.AsUnsignedByteArray(size, d);
  60. byte[] m = BigIntegers.AsUnsignedByteArray(size, mInt);
  61. #endif
  62. hMac.Init(new KeyParameter(K));
  63. hMac.BlockUpdate(V, 0, V.Length);
  64. hMac.Update(0x00);
  65. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  66. hMac.BlockUpdate(xm);
  67. #else
  68. hMac.BlockUpdate(x, 0, x.Length);
  69. hMac.BlockUpdate(m, 0, m.Length);
  70. #endif
  71. InitAdditionalInput0(hMac);
  72. hMac.DoFinal(K, 0);
  73. hMac.Init(new KeyParameter(K));
  74. hMac.BlockUpdate(V, 0, V.Length);
  75. hMac.DoFinal(V, 0);
  76. hMac.BlockUpdate(V, 0, V.Length);
  77. hMac.Update(0x01);
  78. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  79. hMac.BlockUpdate(xm);
  80. #else
  81. hMac.BlockUpdate(x, 0, x.Length);
  82. hMac.BlockUpdate(m, 0, m.Length);
  83. #endif
  84. hMac.DoFinal(K, 0);
  85. hMac.Init(new KeyParameter(K));
  86. hMac.BlockUpdate(V, 0, V.Length);
  87. hMac.DoFinal(V, 0);
  88. }
  89. public virtual BigInteger NextK()
  90. {
  91. byte[] t = new byte[BigIntegers.GetUnsignedByteLength(n)];
  92. for (;;)
  93. {
  94. int tOff = 0;
  95. while (tOff < t.Length)
  96. {
  97. hMac.BlockUpdate(V, 0, V.Length);
  98. hMac.DoFinal(V, 0);
  99. int len = System.Math.Min(t.Length - tOff, V.Length);
  100. Array.Copy(V, 0, t, tOff, len);
  101. tOff += len;
  102. }
  103. BigInteger k = BitsToInt(t);
  104. if (k.SignValue > 0 && k.CompareTo(n) < 0)
  105. return k;
  106. hMac.BlockUpdate(V, 0, V.Length);
  107. hMac.Update(0x00);
  108. hMac.DoFinal(K, 0);
  109. hMac.Init(new KeyParameter(K));
  110. hMac.BlockUpdate(V, 0, V.Length);
  111. hMac.DoFinal(V, 0);
  112. }
  113. }
  114. /// <summary>Supports use of additional input.</summary>
  115. /// <remarks>
  116. /// RFC 6979 3.6. Additional data may be added to the input of HMAC [..]. A use case may be a protocol that
  117. /// requires a non-deterministic signature algorithm on a system that does not have access to a high-quality
  118. /// random source. It suffices that the additional data[..] is non-repeating(e.g., a signature counter or a
  119. /// monotonic clock) to ensure "random-looking" signatures are indistinguishable, in a cryptographic way, from
  120. /// plain (EC)DSA signatures.
  121. /// <para/>
  122. /// By default there is no additional input. Override this method to supply additional input, bearing in mind
  123. /// that this calculator may be used for many signatures.
  124. /// </remarks>
  125. /// <param name="hmac0">The <see cref="HMac"/> to which the additional input should be added.</param>
  126. protected virtual void InitAdditionalInput0(HMac hmac0)
  127. {
  128. }
  129. private BigInteger BitsToInt(byte[] t)
  130. {
  131. BigInteger v = new BigInteger(1, t);
  132. if (t.Length * 8 > n.BitLength)
  133. {
  134. v = v.ShiftRight(t.Length * 8 - n.BitLength);
  135. }
  136. return v;
  137. }
  138. }
  139. }
  140. #pragma warning restore
  141. #endif