问题描述:设 a=g^x mod p,记 log g,p a=x,称 x 为 a 的(以 g 为底模除 p)对数。从 p,g,a 计算 x 称为离散对数问题。
问题在于:给出 p,g,a,怎么求 x
简单算法:
1 ∀x, 计算 g ^x
最多计算 0≤x≤ p-1 或 1≤x≤p,因为实际上离散对数
2 验证 a=g ^x mod p 是否成立。
dlog(g, a, p) { // 当这样的对数不存在时,算法返回 p
x ← 0; y ← 1;
do {
x++;
y ← y*g; // 计算 y=g^ x
} while ( a ≠ y mod p) and (x ≠ p);
return x
}
问题:最坏 O(p),若 P 很大怎么办?所以简单算法不行,而且 x 的算出来的快慢取决于 a 的取值, a 的取值能够让算法较早找到正确的 x,则算法很快就完了,否则很慢,直到 p。
Sherwood 算法解决方法
算法f(x)可改造为Sherwood算法:
RH(x) {
// 用Sherwood算法计算f(x)
n ← length[x]; // x的size为n
r ← uniform(A n ); // 随机取一元素
y ← u(x, r); //将原实例x转化为随机实例y
s ← f(y); // 用确定算法求y的解s
return v(r, s); // 将s的解变换为x的解
}
Sherwood算法的核是找到u,v方法
应用上面这个算法框架 我们可以来改写这个离散对数计算的Sherwood 算法
根据上面的分析,Sherwood 算法应该使得这个算法不会根据 a,p 的取值影响算法的快慢
算法依据的定理:
1. Log g,p (st mod p) = (log g,p s + log g,p t) mod (p - 1)
2. Log g,p (g ^r mod p) = r, 0 <= r <= p – 2
dlogRH(g, a p) { // 求 log g,p a, a = g^x mod p,求 x Sherwood算法
r ← uniform(0..p-2);
b ← ModularExponent(g, r, p); //求幂模 b=g^r mod p,定理 1 真数的一部分
c ← ba mod p; //((g^r modp)(g^x modp))modp=g ^(r+x)modp=c, 定理 2 中的真数
y ← log g,p c; // 使用确定性算法求 log p,g c, y=r+x,定理 2
return (y-r)mod(p-1); //求x,定理1
}
在这里,唯一耗费时间的是 b ← ModularExponent(g, r, p),它的执行时间与a,p 的取值无关,只与随机取出的 r 有关
实现代码如下:
//编程计算离散对数
//定义:设 a=g^x mod p,记 log g,p a=x,称x为a的(以g为底模除p)对数。
#include
#include
#include
#include
int dlog(int g,int a,int p); //求离散对数的确定性算法
int dlogRH(int g,int a,int p);//求a的(以g为底模除p)对数的Sherwood算法
int ModularExponent(int g,int r,int p); //求 g^r mod p
int main()
{
int p,g,a,x;
printf("计算离散对数的Sherwood算法\n");
printf("要求x 输入a,g,p的值,a=g^x mod p\n");
scanf("%d %d %d",&a,&g,&p);
x = dlogRH(g,a,p);
printf("求a的(以g为底模除p)对数x的值为 %d \n",x);
return 0;
}
int dlog(int g,int a,int p)
{
int x =0,y=1;
do{
x++;
y = y*g;
}while((a != y%p)&&(x != p));
return x;
}
int dlogRH(int g,int a,int p)
{
int r,y,c,b;
int i = 0,j= p-2;
srand((unsigned)time(NULL));
r = rand()%(j-i+1)+i;
b = ModularExponent(g,r,p);
c = (a*b)%p;
y = dlog(g,c,p);
return (y-r)%(p-1);
}
int ModularExponent(int g,int r,int p)
{
int y = 1;
while(r--)
y = y*g;
return y%p;
}