123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers
- {
- /**
- * A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
- */
- public class HMacDsaKCalculator
- : IDsaKCalculator
- {
- private readonly HMac hMac;
- private readonly byte[] K;
- private readonly byte[] V;
- private BigInteger n;
- /**
- * Base constructor.
- *
- * @param digest digest to build the HMAC on.
- */
- public HMacDsaKCalculator(IDigest digest)
- {
- this.hMac = new HMac(digest);
- this.V = new byte[hMac.GetMacSize()];
- this.K = new byte[hMac.GetMacSize()];
- }
- public virtual bool IsDeterministic
- {
- get { return true; }
- }
- public virtual void Init(BigInteger n, SecureRandom random)
- {
- throw new InvalidOperationException("Operation not supported");
- }
- public void Init(BigInteger n, BigInteger d, byte[] message)
- {
- this.n = n;
- Arrays.Fill(V, 0x01);
- Arrays.Fill(K, 0);
- BigInteger mInt = BitsToInt(message);
- if (mInt.CompareTo(n) >= 0)
- {
- mInt = mInt.Subtract(n);
- }
- int size = BigIntegers.GetUnsignedByteLength(n);
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- int xmSize = size * 2;
- Span<byte> xm = xmSize <= 512
- ? stackalloc byte[xmSize]
- : new byte[xmSize];
- BigIntegers.AsUnsignedByteArray(d, xm[..size]);
- BigIntegers.AsUnsignedByteArray(mInt, xm[size..]);
- #else
- byte[] x = BigIntegers.AsUnsignedByteArray(size, d);
- byte[] m = BigIntegers.AsUnsignedByteArray(size, mInt);
- #endif
- hMac.Init(new KeyParameter(K));
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.Update(0x00);
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- hMac.BlockUpdate(xm);
- #else
- hMac.BlockUpdate(x, 0, x.Length);
- hMac.BlockUpdate(m, 0, m.Length);
- #endif
- InitAdditionalInput0(hMac);
- hMac.DoFinal(K, 0);
- hMac.Init(new KeyParameter(K));
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.DoFinal(V, 0);
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.Update(0x01);
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- hMac.BlockUpdate(xm);
- #else
- hMac.BlockUpdate(x, 0, x.Length);
- hMac.BlockUpdate(m, 0, m.Length);
- #endif
- hMac.DoFinal(K, 0);
- hMac.Init(new KeyParameter(K));
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.DoFinal(V, 0);
- }
- public virtual BigInteger NextK()
- {
- byte[] t = new byte[BigIntegers.GetUnsignedByteLength(n)];
- for (;;)
- {
- int tOff = 0;
- while (tOff < t.Length)
- {
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.DoFinal(V, 0);
- int len = System.Math.Min(t.Length - tOff, V.Length);
- Array.Copy(V, 0, t, tOff, len);
- tOff += len;
- }
- BigInteger k = BitsToInt(t);
- if (k.SignValue > 0 && k.CompareTo(n) < 0)
- return k;
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.Update(0x00);
- hMac.DoFinal(K, 0);
- hMac.Init(new KeyParameter(K));
- hMac.BlockUpdate(V, 0, V.Length);
- hMac.DoFinal(V, 0);
- }
- }
- /// <summary>Supports use of additional input.</summary>
- /// <remarks>
- /// RFC 6979 3.6. Additional data may be added to the input of HMAC [..]. A use case may be a protocol that
- /// requires a non-deterministic signature algorithm on a system that does not have access to a high-quality
- /// random source. It suffices that the additional data[..] is non-repeating(e.g., a signature counter or a
- /// monotonic clock) to ensure "random-looking" signatures are indistinguishable, in a cryptographic way, from
- /// plain (EC)DSA signatures.
- /// <para/>
- /// By default there is no additional input. Override this method to supply additional input, bearing in mind
- /// that this calculator may be used for many signatures.
- /// </remarks>
- /// <param name="hmac0">The <see cref="HMac"/> to which the additional input should be added.</param>
- protected virtual void InitAdditionalInput0(HMac hmac0)
- {
- }
- private BigInteger BitsToInt(byte[] t)
- {
- BigInteger v = new BigInteger(1, t);
- if (t.Length * 8 > n.BitLength)
- {
- v = v.ShiftRight(t.Length * 8 - n.BitLength);
- }
- return v;
- }
- }
- }
- #pragma warning restore
- #endif
|