关于ElGamal加密算法实现的总结(附最小本原元代码)

重点:ElGamal既能够加密,也能够用来签名。两者虽然过程很像,但并不是同一件事。例如:

https://blog.csdn.net/boksic/article/details/7014386

这个展示了很多原理,也介绍了加密与解密过程的实现,算是比较直接的。

而  http://blog.sina.com.cn/s/blog_5b5ed0720100atsy.htm 和  https://www.cnblogs.com/math/p/discrete-log.html 则是对ElGamal算法的依靠:离散对数问题进行了深入的探究。可以选看。

在我们实现该算法的时候会遇到大量的幂运算,模运算的混合运算公式,例如:y = a^b mod (p)  如果 b太大,则会出现Int 类型装不下的情况。因此可以结合 https://www.cnblogs.com/juruohx/p/7787415.html 这里介绍的模运算公式 (a + b) % p = (a % p + b % p) % p  来写出如下代码来进行计算:

private int calc_BigNum(int c1,int c2,int p)
        {
            //递归方法
            //if (c2 == 1)
            //{
            //    return Convert.ToInt32(c1 % p);
            //}
            //else
            //{
            //    return Convert.ToInt32(((c1 % p) * calc_BigNum(c1, c2 - 1, p)) % p);
            //}

            //非递归方法
            if (c2 == 0)
            {
                return 1;
            }

            List result = new List();
            while (c2>0)
            {
                result.Add(Convert.ToInt32(c1 % p));
                c2 -= 1;
            }
            int value = Convert.ToInt32(result[0] % p);
            for (int i = 1; i < result.Count; i++)
            {
                value *= Convert.ToInt32(result[i] % p);
                value = Convert.ToInt32(value % p);

            }
            return Convert.ToInt32(value % p);

        }

这样就能够解决了(不推荐递归的算法,容易溢出)

最后,关于讲的最好的和最全面的应该是:https://www.jiamisoft.com/blog/20564-elgamal.html 

但是这一句:

再用扩展 Euclidean 算法对下面方程求解b:
M = xa + kb ( mod p - 1 ) ,签名就是( a, b )。随机数k须丢弃。

则是没有解释怎么在已知m,x,a,k,p的情况下求b。我自己写了下面的方法来求:

private int calc_c2(int m,int x , int c1 , int k, int p)
        {
            while (true)
            {
                if(m-c1*x > 0 && Convert.ToInt32((m - c1 * x) % k) == 0)
                {
                    int c2 = (m - c1*x) / k;
                    return c2;
                }
                else
                {
                    m += p - 1;
                }
            }

            
        }

因为我和该文章的一些变量名没有相同,所以看起来很乱,在我这个代码中,该方程是这样写的:m = x*c1 + k*c2  mod (p-1)

就辛苦你们这些读者了(●ˇ∀ˇ●)


附:如果有人需要有求本原元的代码,下面的代码希望对你有用

#include 
#include 
#include 
#include 
using namespace std;
int P;
const int NUM = 32170;
int prime[NUM/4];
bool f[NUM];
int pNum = 0;
void getPrime()//线性筛选素数
{
	for (int i = 2; i < NUM; ++ i)
	{
		if (!f[i])
		{
			f[i] = 1;
			prime[pNum++] = i;
		}
		for (int j = 0; j < pNum && i*prime[j] < NUM; ++ j)
		{
			f[i*prime[j]] = 1;
			if (i%prime[j] == 0)
			{
				break;
			}
		}
	}
}
__int64 getProduct(int a,int b,int P)//快速求次幂mod
{
	__int64 ans = 1;
	__int64 tmp = a;
	while (b)
	{
		if (b&1)
		{
			ans = ans*tmp%P;
		}
		tmp = tmp*tmp%P;
		b>>=1;
	}
	return ans;
}
 
bool judge(int num)//求num的所有的质因子
{
	int elem[1000];
	int elemNum = 0;
	int k = P - 1;
	for (int i = 0; i < pNum; ++ i)
	{
		bool flag = false;
		while (!(k%prime[i]))
		{
			flag = true;
			k /= prime[i];
		}
		if (flag)
		{
			elem[elemNum ++] = prime[i];
		}
		if (k==1)
		{
			break;
		}
		if (k/prime[i]> P)
	{
		for (int i = 2;;++i)
		{
			if (judge(i) && i

 

你可能感兴趣的:(密码学,c#,winform,密码学,gcd,算法)