/// <summary> /// Вырабатывает ЭЦП сообщения-Text /// </summary> /// <param name="Text">Сообщение</param> /// <returns>Подпись</returns> public static BigInt32 CreateSignature(byte[] Text, BigInt32 d, BigInt32 n) { byte[] hash = MD5hash(Text); BigInt32 BI_Text = new BigInt32(hash); return(BI_Text.modPow(d, n)); }
/// <summary> /// Проверка цифровой подписи Signature текста Text /// </summary> /// <param name="Text">Текст</param> /// <param name="Signature">Подпись</param> /// <param name="e">Открытый ключ</param> /// <param name="n">Модуль</param> /// <returns>true если подпись верна, false в обратном случае</returns> public static bool VerifySignature(byte[] Text, BigInt32 Signature, BigInt32 e, BigInt32 n) { BigInt32 R = new BigInt32(MD5hash(Text)); //Console.WriteLine(R); BigInt32 S = new BigInt32(Signature.modPow(e, n)); //Console.WriteLine(S); if (R == S) { return(true); } return(false); }
/// <summary> /// Вероятностный тест на простоту основанный на алгоритме Милера-Рабина /// Для любого p > 0, при p - 1 = 2^s * t /// p вероятно простое для любого a < p, /// 1) a^t mod p = 1 или /// 2) a^((2^j)*t) mod p = p-1 для некоторого 0 <= j <= s-1 /// </summary> public bool RabinMillerTest(int confidence) { BigInt32 thisVal = this; if (thisVal.dataLength == 1) { // для малых значений if (thisVal.data[0] == 0 || thisVal.data[0] == 1) { return(false); } else if (thisVal.data[0] == 2 || thisVal.data[0] == 3) { return(true); } } if ((thisVal.data[0] & 0x1) == 0) // четное число { return(false); } // Вычислим значение s и t BigInt32 p_sub1 = thisVal - (new BigInt32(1)); // р-1 int s = 0; for (int index = 0; index < p_sub1.dataLength; index++) { uint mask = 0x01; for (int i = 0; i < 32; i++) { if ((p_sub1.data[index] & mask) != 0) { index = p_sub1.dataLength; // разбить внутренний цикл break; } mask <<= 1; s++; } } BigInt32 t = p_sub1 >> s; int bits = thisVal.bitCount(); BigInt32 a = new BigInt32(); Random rand = new Random(); for (int round = 0; round < confidence; round++) { bool done = false; while (!done) // генерирует a < n { int testBits = 0; while (testBits < 2) { testBits = (int)(rand.NextDouble() * bits); } a.GetRandomBits(testBits, rand); int byteLen = a.dataLength; if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1)) // убедиться, что а != 0 { done = true; } } // проверка является ли а свидетелем простоты BigInt32 gcdTest = a.gcd(thisVal); if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1) { return(false); } BigInt32 b = a.modPow(t, thisVal); bool result = false; if (b.dataLength == 1 && b.data[0] == 1) // a^t mod p = 1 { result = true; } for (int j = 0; result == false && j < s; j++) { if (b == p_sub1) // a^((2^j)*t) mod p = p-1 для 0 <= j <= s-1 { result = true; break; } b = (b * b) % thisVal; } if (result == false) { return(false); } } return(true); }