<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />

Gost3410ParametersGenerator

using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using System; namespace Org.BouncyCastle.Crypto.Generators { public class Gost3410ParametersGenerator { private int size; private int typeproc; private SecureRandom init_random; public void Init(int size, int typeProcedure, SecureRandom random) { this.size = size; typeproc = typeProcedure; init_random = random; } private int procedure_A(int x0, int c, BigInteger[] pq, int size) { while (x0 < 0 || x0 > 65536) { x0 = init_random.NextInt() / 32768; } while (c < 0 || c > 65536 || c / 2 == 0) { c = init_random.NextInt() / 32768 + 1; } BigInteger value = BigInteger.ValueOf(c); BigInteger val = BigInteger.ValueOf(19381); BigInteger[] array = new BigInteger[1] { BigInteger.ValueOf(x0) }; int[] array2 = new int[1] { size }; int num = 0; for (int i = 0; array2[i] >= 17; i++) { int[] array3 = new int[array2.Length + 1]; Array.Copy(array2, 0, array3, 0, array2.Length); array2 = new int[array3.Length]; Array.Copy(array3, 0, array2, 0, array3.Length); array2[i + 1] = array2[i] / 2; num = i + 1; } BigInteger[] array4 = new BigInteger[num + 1]; array4[num] = new BigInteger("8003", 16); int num2 = num - 1; for (int j = 0; j < num; j++) { int num3 = array2[num2] / 16; while (true) { BigInteger[] array5 = new BigInteger[array.Length]; Array.Copy(array, 0, array5, 0, array.Length); array = new BigInteger[num3 + 1]; Array.Copy(array5, 0, array, 0, array5.Length); for (int k = 0; k < num3; k++) { array[k + 1] = array[k].Multiply(val).Add(value).Mod(BigInteger.Two.Pow(16)); } BigInteger bigInteger = BigInteger.Zero; for (int l = 0; l < num3; l++) { bigInteger = bigInteger.Add(array[l].ShiftLeft(16 * l)); } array[0] = array[num3]; BigInteger bigInteger2 = BigInteger.One.ShiftLeft(array2[num2] - 1).Divide(array4[num2 + 1]).Add(bigInteger.ShiftLeft(array2[num2] - 1).Divide(array4[num2 + 1].ShiftLeft(16 * num3))); if (bigInteger2.TestBit(0)) bigInteger2 = bigInteger2.Add(BigInteger.One); while (true) { BigInteger bigInteger3 = bigInteger2.Multiply(array4[num2 + 1]); if (bigInteger3.BitLength > array2[num2]) break; array4[num2] = bigInteger3.Add(BigInteger.One); if (BigInteger.Two.ModPow(bigInteger3, array4[num2]).CompareTo(BigInteger.One) == 0 && BigInteger.Two.ModPow(bigInteger2, array4[num2]).CompareTo(BigInteger.One) != 0) goto end_IL_0103; bigInteger2 = bigInteger2.Add(BigInteger.Two); } continue; continue; end_IL_0103: break; } if (--num2 < 0) { pq[0] = array4[0]; pq[1] = array4[1]; return array[0].IntValue; } } return array[0].IntValue; } private long procedure_Aa(long x0, long c, BigInteger[] pq, int size) { while (x0 < 0 || x0 > 4294967296) { x0 = init_random.NextInt() * 2; } while (c < 0 || c > 4294967296 || c / 2 == 0) { c = init_random.NextInt() * 2 + 1; } BigInteger value = BigInteger.ValueOf(c); BigInteger val = BigInteger.ValueOf(97781173); BigInteger[] array = new BigInteger[1] { BigInteger.ValueOf(x0) }; int[] array2 = new int[1] { size }; int num = 0; for (int i = 0; array2[i] >= 33; i++) { int[] array3 = new int[array2.Length + 1]; Array.Copy(array2, 0, array3, 0, array2.Length); array2 = new int[array3.Length]; Array.Copy(array3, 0, array2, 0, array3.Length); array2[i + 1] = array2[i] / 2; num = i + 1; } BigInteger[] array4 = new BigInteger[num + 1]; array4[num] = new BigInteger("8000000B", 16); int num2 = num - 1; for (int j = 0; j < num; j++) { int num3 = array2[num2] / 32; while (true) { BigInteger[] array5 = new BigInteger[array.Length]; Array.Copy(array, 0, array5, 0, array.Length); array = new BigInteger[num3 + 1]; Array.Copy(array5, 0, array, 0, array5.Length); for (int k = 0; k < num3; k++) { array[k + 1] = array[k].Multiply(val).Add(value).Mod(BigInteger.Two.Pow(32)); } BigInteger bigInteger = BigInteger.Zero; for (int l = 0; l < num3; l++) { bigInteger = bigInteger.Add(array[l].ShiftLeft(32 * l)); } array[0] = array[num3]; BigInteger bigInteger2 = BigInteger.One.ShiftLeft(array2[num2] - 1).Divide(array4[num2 + 1]).Add(bigInteger.ShiftLeft(array2[num2] - 1).Divide(array4[num2 + 1].ShiftLeft(32 * num3))); if (bigInteger2.TestBit(0)) bigInteger2 = bigInteger2.Add(BigInteger.One); while (true) { BigInteger bigInteger3 = bigInteger2.Multiply(array4[num2 + 1]); if (bigInteger3.BitLength > array2[num2]) break; array4[num2] = bigInteger3.Add(BigInteger.One); if (BigInteger.Two.ModPow(bigInteger3, array4[num2]).CompareTo(BigInteger.One) == 0 && BigInteger.Two.ModPow(bigInteger2, array4[num2]).CompareTo(BigInteger.One) != 0) goto end_IL_0108; bigInteger2 = bigInteger2.Add(BigInteger.Two); } continue; continue; end_IL_0108: break; } if (--num2 < 0) { pq[0] = array4[0]; pq[1] = array4[1]; return array[0].LongValue; } } return array[0].LongValue; } private void procedure_B(int x0, int c, BigInteger[] pq) { while (x0 < 0 || x0 > 65536) { x0 = init_random.NextInt() / 32768; } while (c < 0 || c > 65536 || c / 2 == 0) { c = init_random.NextInt() / 32768 + 1; } BigInteger[] array = new BigInteger[2]; BigInteger bigInteger = null; BigInteger bigInteger2 = null; BigInteger bigInteger3 = null; BigInteger value = BigInteger.ValueOf(c); BigInteger val = BigInteger.ValueOf(19381); x0 = procedure_A(x0, c, array, 256); bigInteger = array[0]; x0 = procedure_A(x0, c, array, 512); bigInteger2 = array[0]; BigInteger[] array2 = new BigInteger[65] { BigInteger.ValueOf(x0), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; BigInteger bigInteger4 = bigInteger.Multiply(bigInteger2); while (true) { for (int i = 0; i < 64; i++) { array2[i + 1] = array2[i].Multiply(val).Add(value).Mod(BigInteger.Two.Pow(16)); } BigInteger bigInteger5 = BigInteger.Zero; for (int j = 0; j < 64; j++) { bigInteger5 = bigInteger5.Add(array2[j].ShiftLeft(16 * j)); } array2[0] = array2[64]; BigInteger bigInteger6 = BigInteger.One.ShiftLeft(1023).Divide(bigInteger4).Add(bigInteger5.ShiftLeft(1023).Divide(bigInteger4.ShiftLeft(1024))); if (bigInteger6.TestBit(0)) bigInteger6 = bigInteger6.Add(BigInteger.One); while (true) { BigInteger bigInteger7 = bigInteger4.Multiply(bigInteger6); if (bigInteger7.BitLength > 1024) break; bigInteger3 = bigInteger7.Add(BigInteger.One); if (BigInteger.Two.ModPow(bigInteger7, bigInteger3).CompareTo(BigInteger.One) == 0 && BigInteger.Two.ModPow(bigInteger.Multiply(bigInteger6), bigInteger3).CompareTo(BigInteger.One) != 0) { pq[0] = bigInteger3; pq[1] = bigInteger; return; } bigInteger6 = bigInteger6.Add(BigInteger.Two); } } } private void procedure_Bb(long x0, long c, BigInteger[] pq) { while (x0 < 0 || x0 > 4294967296) { x0 = init_random.NextInt() * 2; } while (c < 0 || c > 4294967296 || c / 2 == 0) { c = init_random.NextInt() * 2 + 1; } BigInteger[] array = new BigInteger[2]; BigInteger bigInteger = null; BigInteger bigInteger2 = null; BigInteger bigInteger3 = null; BigInteger value = BigInteger.ValueOf(c); BigInteger val = BigInteger.ValueOf(97781173); x0 = procedure_Aa(x0, c, array, 256); bigInteger = array[0]; x0 = procedure_Aa(x0, c, array, 512); bigInteger2 = array[0]; BigInteger[] array2 = new BigInteger[33] { BigInteger.ValueOf(x0), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; BigInteger bigInteger4 = bigInteger.Multiply(bigInteger2); while (true) { for (int i = 0; i < 32; i++) { array2[i + 1] = array2[i].Multiply(val).Add(value).Mod(BigInteger.Two.Pow(32)); } BigInteger bigInteger5 = BigInteger.Zero; for (int j = 0; j < 32; j++) { bigInteger5 = bigInteger5.Add(array2[j].ShiftLeft(32 * j)); } array2[0] = array2[32]; BigInteger bigInteger6 = BigInteger.One.ShiftLeft(1023).Divide(bigInteger4).Add(bigInteger5.ShiftLeft(1023).Divide(bigInteger4.ShiftLeft(1024))); if (bigInteger6.TestBit(0)) bigInteger6 = bigInteger6.Add(BigInteger.One); while (true) { BigInteger bigInteger7 = bigInteger4.Multiply(bigInteger6); if (bigInteger7.BitLength > 1024) break; bigInteger3 = bigInteger7.Add(BigInteger.One); if (BigInteger.Two.ModPow(bigInteger7, bigInteger3).CompareTo(BigInteger.One) == 0 && BigInteger.Two.ModPow(bigInteger.Multiply(bigInteger6), bigInteger3).CompareTo(BigInteger.One) != 0) { pq[0] = bigInteger3; pq[1] = bigInteger; return; } bigInteger6 = bigInteger6.Add(BigInteger.Two); } } } private BigInteger procedure_C(BigInteger p, BigInteger q) { BigInteger bigInteger = p.Subtract(BigInteger.One); BigInteger e = bigInteger.Divide(q); BigInteger bigInteger3; while (true) { BigInteger bigInteger2 = new BigInteger(p.BitLength, init_random); if (bigInteger2.CompareTo(BigInteger.One) > 0 && bigInteger2.CompareTo(bigInteger) < 0) { bigInteger3 = bigInteger2.ModPow(e, p); if (bigInteger3.CompareTo(BigInteger.One) != 0) break; } } return bigInteger3; } public Gost3410Parameters GenerateParameters() { BigInteger[] array = new BigInteger[2]; BigInteger bigInteger = null; BigInteger bigInteger2 = null; BigInteger bigInteger3 = null; if (typeproc == 1) { int x = init_random.NextInt(); int c = init_random.NextInt(); switch (size) { case 512: procedure_A(x, c, array, 512); break; case 1024: procedure_B(x, c, array); break; default: throw new ArgumentException("Ooops! key size 512 or 1024 bit."); } bigInteger2 = array[0]; bigInteger = array[1]; bigInteger3 = procedure_C(bigInteger2, bigInteger); return new Gost3410Parameters(bigInteger2, bigInteger, bigInteger3, new Gost3410ValidationParameters(x, c)); } long num = init_random.NextLong(); long num2 = init_random.NextLong(); switch (size) { case 512: procedure_Aa(num, num2, array, 512); break; case 1024: procedure_Bb(num, num2, array); break; default: throw new InvalidOperationException("Ooops! key size 512 or 1024 bit."); } bigInteger2 = array[0]; bigInteger = array[1]; bigInteger3 = procedure_C(bigInteger2, bigInteger); return new Gost3410Parameters(bigInteger2, bigInteger, bigInteger3, new Gost3410ValidationParameters(num, num2)); } } }