123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- 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.Agreement.Srp
- {
- public class Srp6Utilities
- {
- public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
- {
- return HashPaddedPair(digest, N, N, g);
- }
- public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
- {
- return HashPaddedPair(digest, N, A, B);
- }
- public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
- {
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- return CalculateX(digest, N, salt.AsSpan(), identity.AsSpan(), password.AsSpan());
- #else
- byte[] output = new byte[digest.GetDigestSize()];
- digest.BlockUpdate(identity, 0, identity.Length);
- digest.Update((byte)':');
- digest.BlockUpdate(password, 0, password.Length);
- digest.DoFinal(output, 0);
- digest.BlockUpdate(salt, 0, salt.Length);
- digest.BlockUpdate(output, 0, output.Length);
- digest.DoFinal(output, 0);
- return new BigInteger(1, output);
- #endif
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- public static BigInteger CalculateX(IDigest digest, BigInteger N, ReadOnlySpan<byte> salt,
- ReadOnlySpan<byte> identity, ReadOnlySpan<byte> password)
- {
- int digestSize = digest.GetDigestSize();
- Span<byte> output = digestSize <= 128
- ? stackalloc byte[digestSize]
- : new byte[digestSize];
- digest.BlockUpdate(identity);
- digest.Update((byte)':');
- digest.BlockUpdate(password);
- digest.DoFinal(output);
- digest.BlockUpdate(salt);
- digest.BlockUpdate(output);
- digest.DoFinal(output);
- return new BigInteger(1, output);
- }
- #endif
- public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
- {
- int minBits = System.Math.Min(256, N.BitLength / 2);
- BigInteger min = BigInteger.One.ShiftLeft(minBits - 1);
- BigInteger max = N.Subtract(BigInteger.One);
- return BigIntegers.CreateRandomInRange(min, max, random);
- }
- public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
- {
- val = val.Mod(N);
- // Check that val % N != 0
- if (val.Equals(BigInteger.Zero))
- throw new CryptoException("Invalid public value: 0");
- return val;
- }
- /**
- * Computes the client evidence message (M1) according to the standard routine:
- * M1 = H( A | B | S )
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param A The public client value
- * @param B The public server value
- * @param S The secret calculated by both sides
- * @return M1 The calculated client evidence message
- */
- public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S)
- {
- BigInteger M1 = HashPaddedTriplet(digest, N, A, B, S);
- return M1;
- }
- /**
- * Computes the server evidence message (M2) according to the standard routine:
- * M2 = H( A | M1 | S )
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param A The public client value
- * @param M1 The client evidence message
- * @param S The secret calculated by both sides
- * @return M2 The calculated server evidence message
- */
- public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S)
- {
- BigInteger M2 = HashPaddedTriplet(digest, N, A, M1, S);
- return M2;
- }
- /**
- * Computes the final Key according to the standard routine: Key = H(S)
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param S The secret calculated by both sides
- * @return
- */
- public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S)
- {
- int paddedLength = (N.BitLength + 7) / 8;
- int digestSize = digest.GetDigestSize();
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- Span<byte> bytes = paddedLength <= 512
- ? stackalloc byte[paddedLength]
- : new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(S, bytes);
- digest.BlockUpdate(bytes);
- Span<byte> output = digestSize <= 128
- ? stackalloc byte[digestSize]
- : new byte[digestSize];
- digest.DoFinal(output);
- #else
- byte[] bytes = new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(S, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- byte[] output = new byte[digestSize];
- digest.DoFinal(output, 0);
- #endif
- return new BigInteger(1, output);
- }
- private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3)
- {
- int paddedLength = (N.BitLength + 7) / 8;
- int digestSize = digest.GetDigestSize();
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- Span<byte> bytes = paddedLength <= 512
- ? stackalloc byte[paddedLength]
- : new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(n1, bytes);
- digest.BlockUpdate(bytes);
- BigIntegers.AsUnsignedByteArray(n2, bytes);
- digest.BlockUpdate(bytes);
- BigIntegers.AsUnsignedByteArray(n3, bytes);
- digest.BlockUpdate(bytes);
- Span<byte> output = digestSize <= 128
- ? stackalloc byte[digestSize]
- : new byte[digestSize];
- digest.DoFinal(output);
- #else
- byte[] bytes = new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- BigIntegers.AsUnsignedByteArray(n3, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- byte[] output = new byte[digestSize];
- digest.DoFinal(output, 0);
- #endif
- return new BigInteger(1, output);
- }
- private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
- {
- int paddedLength = (N.BitLength + 7) / 8;
- int digestSize = digest.GetDigestSize();
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- Span<byte> bytes = paddedLength <= 512
- ? stackalloc byte[paddedLength]
- : new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(n1, bytes);
- digest.BlockUpdate(bytes);
- BigIntegers.AsUnsignedByteArray(n2, bytes);
- digest.BlockUpdate(bytes);
- Span<byte> output = digestSize <= 128
- ? stackalloc byte[digestSize]
- : new byte[digestSize];
- digest.DoFinal(output);
- #else
- byte[] bytes = new byte[paddedLength];
- BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- byte[] output = new byte[digestSize];
- digest.DoFinal(output, 0);
- #endif
- return new BigInteger(1, output);
- }
- }
- }
- #pragma warning restore
- #endif
|