ElGamal проверка подписи

Я пытаюсь реализовать подпись ElGamal, но у меня проблемы с проверкой. Согласно википедии, подпись (r,s) сообщения m является правильной, если:
формула проверки

Существует известный алгоритм расчета ModPow, который используется на шаге подписи:

Но я не могу найти способ рассчитать первую формулу. Кажется, что это будет слишком большое число, если я попытаюсь рассчитать мощность напрямую. Я кодирую на C# и использую BigInteger, который даже не позволяет рассчитать мощность по показателю BigInteger - принимаются только общие целые числа, что, я полагаю, разумно.
Есть ли какое-то упрощение? Как это должно быть рассчитано? Спасибо

2 ответа

Вы рассчитываете его, используя точно такой же алгоритм, который вы используете для вычисления g^k (mod p), квадрат и умножить. Вам не нужно реализовывать этот алгоритм самостоятельно, ModPow метод является частью BigInteger тип.

bool success = BigInteger.ModPow(g, h, p) ==
               (BigInteger.ModPow(y, r, p) + BigInteger.ModPow(r, s, p)) % p;

Обратите внимание, что (mod p) справа математическая формула не является оператором, она говорит вам, что все уравнение следует рассматривать как конгруэнтность по модулю р.

Да, вы можете использовать библиотеку gmp, связав опцию -lgmp.
Хотя в Python есть большое число, скорость вычислений слишком мала для использования.
Это пример проверки параметров вывода OpenSSL в DSA。 Используйте эту функцию:

Функция: void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "gmp.h"
int main()
{
    mpz_t P;    // a big prime
    mpz_t Q;    // order
    mpz_t G;    // generator 
    mpz_t pub;  // public key
    mpz_t priv; // private key
    mpz_t tmp; //  tmp variable

    //  Initialize a NULL-terminated list of mpz_t variables, and set their values to 0.
    mpz_inits (P ,Q, G, pub, priv,  tmp, NULL);

    mpz_set_str (P, "0x00e79d25ca547dc8931850eaaa6784e365eecf69374243d902c12df7d4896a9e5b8717c4c7b24e30d1b468061838f5bc76df050ef6b7c58105ee2cf23ecb67e7d89830a0976f606e194d0b85e6566cca6275b7b184416337fc7ac37bebe9c9f76e982b9a82ee0a904900a0a7f76f4760e76120ecd2732a1dfe9a1dfa568757690670460688205a7e0d744feacdc27416a27afe5233dd58945801af83c7fd7199dcbed00819750c81cd3f2b5d68c29cd43e035eed70bfd85f55259df953f4f69d719ebe5c06b3443d249b110e602d81366ea88407ed81d3cf6f6fcea1bb7f9af563d2ca436d5c2d794f06407d1f111cb25a86f7568368e085ebe31f7eb8b9bedb89", 0); //  the prime P 
    mpz_set_str (Q, "0x00c39250922561c4b56a9c1bfb0d523bbfe8395182c5464b38a1d9959aa121871b", 0); // the order 
    mpz_set_str (G, "0x6cde6920c61fa80e51212de15be6b2aca93174e3fd5d479d08affb57222370c9047b099ea9e9d53b694915967709580b77a5cfd70629e1308c9db7a9e8c2f41f3c7c792c9ffe9dd6695bbc549d2a008005c18e75096c9d455de4d75011dfaa4d18df4ee955de3da692b2a49084285794d9e53df199b0dd5514bee1e387e897d971b6e56f9dcb49bf8a5a4470bf0216816b4ce1ab498957cb5dcc4ef64146a1a424b2d829fe29215e998590213053735618df90485353cee4702194c4de66bd77c3d9cf0fa45ef4b64b5c41186735b46805d2eaf91542507a28805db5838ac3d17ed3227764f5b80d19d8f752f58f01eec5ba12a4c8375a5a47b11f0dc36c2679", 0);  // generator
    mpz_set_str (priv, "0x404dcd0061be1e3d4e5dac6322600d442c1f55fd15b5ecc3d6ad52b527cf44b8", 0); // private key 
    mpz_set_str (pub, "0x71fd06b1b4c4ea7b392b6f33486063db6fe318559046bf750e4b236d59b883ca9174b3e8c9fc788aa2b926d2eaddd36fa7610e6d91822818a69526057d65c4fe1f7e7620ac54164c21ea2c27783eeb58880a3758b7b8f570383c964f37756f5b331d2afda9bc104e99d1a7fb2d29abf9017fac13cf87b4a6d18838c16aa52e130a3ca1b8b88ce830f982200c5dba7369934af4aee15a83963874b0c04d1fd57cf7525b46e4add4f57c892fefa698be330c22282145ada2589a1a2d2816c470164341a8482de9ad72ed1d636a7836b91218932c565c2b5a5ab03ca5704ca5da13904e0bbd6288d99a9827b751de19bb7c165ce3d910f94f43d6166def03aa895b", 0); // public key 

    // verify (G^Q)%P==1
    //Negative exp is supported if an inverse base^-1 mod mod exists (see mpz_invert in Number Theoretic Functions). If an inverse doesn’t exist then a divide by zero is raised.
    mpz_powm(tmp, G, Q, P);
    printf("the modulus :");
    mpz_out_str(stdout, 10, tmp);
    printf("\n");

    // verify the private == public key 
    mpz_powm(tmp, G, priv, P);
    int result = mpz_cmp(tmp, pub);
    printf("the result:%d\n", result);
}

Его можно составить как:

Установите пакет в системе debian
 sudo aptitude install libgmp-dev      
компилировать
   g++ -Wall -g -lgmp   dsa_alg.cpp -o dsa_alg  
запустить./dsa_alg
  the modulus :1     
  the result:0   

Я реализовал алгоритм в Matlab и он работает нормально. Я использовал переменную точность целого числа (vpi) для больших чисел.

zvyr = vpi(mod(((y^r)*(r^s)),p))

Я верю, что нечто подобное будет доступно для C#.

Другие вопросы по тегам