<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0-beta.98" />

Srp6Utilities

public class Srp6Utilities
using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace 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) { return CalculateX(digest, N, salt.AsSpan(), identity.AsSpan(), password.AsSpan()); } public unsafe static BigInteger CalculateX(IDigest digest, BigInteger N, ReadOnlySpan<byte> salt, ReadOnlySpan<byte> identity, ReadOnlySpan<byte> password) { int digestSize = digest.GetDigestSize(); Span<byte> span; if (digestSize <= 128) { int num = digestSize; span = new Span<byte>(stackalloc byte[(int)(uint)num], num); } else span = new byte[digestSize]; Span<byte> span2 = span; digest.BlockUpdate(identity); digest.Update(58); digest.BlockUpdate(password); digest.DoFinal(span2); digest.BlockUpdate(salt); digest.BlockUpdate(span2); digest.DoFinal(span2); return new BigInteger(1, span2); } public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random) { int num = System.Math.Min(256, N.BitLength / 2); BigInteger min = BigInteger.One.ShiftLeft(num - 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); if (val.Equals(BigInteger.Zero)) throw new CryptoException("Invalid public value: 0"); return val; } public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) { return HashPaddedTriplet(digest, N, A, B, S); } public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S) { return HashPaddedTriplet(digest, N, A, M1, S); } public unsafe static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S) { int num = (N.BitLength + 7) / 8; int digestSize = digest.GetDigestSize(); Span<byte> span; if (num <= 512) { int num2 = num; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[num]; Span<byte> span2 = span; BigIntegers.AsUnsignedByteArray(S, span2); digest.BlockUpdate(span2); if (digestSize <= 128) { int num2 = digestSize; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[digestSize]; Span<byte> span3 = span; digest.DoFinal(span3); return new BigInteger(1, span3); } private unsafe static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3) { int num = (N.BitLength + 7) / 8; int digestSize = digest.GetDigestSize(); Span<byte> span; if (num <= 512) { int num2 = num; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[num]; Span<byte> span2 = span; BigIntegers.AsUnsignedByteArray(n1, span2); digest.BlockUpdate(span2); BigIntegers.AsUnsignedByteArray(n2, span2); digest.BlockUpdate(span2); BigIntegers.AsUnsignedByteArray(n3, span2); digest.BlockUpdate(span2); if (digestSize <= 128) { int num2 = digestSize; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[digestSize]; Span<byte> span3 = span; digest.DoFinal(span3); return new BigInteger(1, span3); } private unsafe static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2) { int num = (N.BitLength + 7) / 8; int digestSize = digest.GetDigestSize(); Span<byte> span; if (num <= 512) { int num2 = num; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[num]; Span<byte> span2 = span; BigIntegers.AsUnsignedByteArray(n1, span2); digest.BlockUpdate(span2); BigIntegers.AsUnsignedByteArray(n2, span2); digest.BlockUpdate(span2); if (digestSize <= 128) { int num2 = digestSize; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[digestSize]; Span<byte> span3 = span; digest.DoFinal(span3); return new BigInteger(1, span3); } } }