Elgamal:
加密
- 随机选择一个质数(p),并且求出模(p)情况下的本原根(alpha),并将(p,alpha)公开
- 随机选择一个整数(a),作为私钥,并对(a)保密。
- 计算出公钥(A=alpha^{a}( mod p))
- 对于一段明文(x),随机选择一个整数(b),分别计算出(C_1=alpha^b( mod p) C_2=x*A^b( mod p))
解密
- 对于密文((C_1,C_2))进行解密,首先应当计算(C_1^{a})模(p)情况下的逆元(w)。然后明文(m=w*C_2( mod p))
本原根:最小的原根被称为本原根
习题
选择一个质数(p=2357),在模(p)情况下的最小原根是(alpha=2),选择一个数(a=1751,b=1520),写出对明文(x=2035)加密密文和解密过程。
加密
依题意:其中的(p=2357,alpha=2,a=1751,b=1520)
( herefore)公钥(A=alpha^a( mod p)=2^{1751}\%2357=1185)
(C_1=alpha^b( mod p)=2^{1520}\%2357=1430)
(C_2=x*A^b( mod p)=2035*1185^{1520}\%2357=697)
( herefore)密文为((1430,697))解密
依题意:其中(p=2357,alpha=2,a=1751,C:(1430,697))
( herefore)求出(1430^{1751})在模(p)的逆元(w=872)
( herefore x=872*697\%2357=2035)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 5;
ll factor[maxn], k;
bool prim(ll x)
{
if(x==1)
{
return false;
}
if(x==2)
{
return true;
}
if(x%2==0)
{
return false;
}
for(ll i=3; i*i<=x; i++)
{
if(x%i==0)
{
return false;
}
}
return true;
}
ll qpow(ll a,ll n,ll mod)
{
ll ans=1;
ll base=a;
while(n)
{
if(n&1)
{
ans=ans*base%mod;
}
base=base*base%mod;
n>>=1;
}
return ans%mod;
}
void decompose(ll x) //分解质因子
{
ll ans = 0;
for (ll i = 2; i * i <= x; i++)
{
if (x % i == 0)
{
factor[k++] = i;
while (x % i == 0) x /= i;
}
}
if (x > 1) factor[k++] = x;
}
ll cal(ll n) //求素数最小原根
{
k=0;
decompose(n - 1);
for (ll g = 2; g < n; g++)
{
int flag = 1;
for (int i = 0; i < k; i++)
{
ll t = (n - 1) / factor[i];
if (qpow(g, t, n) == 1)
{
flag = 0;
break;
}
}
if (flag == 1)
return g;
}
}
void exgcd(ll a,ll b,ll &gcd,ll &x,ll &y)
{
if(b==0)
{
gcd=a;
x=1;
y=0;
}
else
{
exgcd(b,a%b,gcd,y,x);
y-=x*(a/b);
}
}
ll inv(ll a,ll b)
{
ll gcd,x,y;
exgcd(a,b,gcd,x,y);
return gcd==1?(x%b+b)%b:-1;
}
int main()
{
printf("encry 1,decry2
");
int flag;
scanf("%d",&flag);
ll p,a,b,x;
ll A,B,C,byg;
if(flag==1)
{
//printf("随机生成一个大的质数p");
printf("Prime p,a,b,x
");
scanf("%lld%lld%lld%lld",&p,&a,&b,&x);
byg = cal(p);
printf("%lld
", byg);
A=qpow(byg,a,p);
cout<<A<<endl;
B=qpow(byg,b,p);
C=(x*qpow(A,b,p))%p;
printf("C(%lld,%lld)
",B,C);
}
else if(flag==2)
{
printf("Prime p,a,B,C");
scanf("%lld%lld%lld%lld", &p,&a,&B,&C);
ll K=inv(qpow(B,a,p),p);
cout<<C *K%p<<endl;
}
// printf("输入质数p,随机数a,随机数b,明文x");
// scanf("%lld%lld%lld%lld", &p,&a,&b,&x);
// ll byg = cal(p);
// printf("%lld
", byg);
// ll A=qpow(byg,a,p);
// cout<<A<<" A "<<endl;
// ll B=qpow(byg,b,p);
// ll C=(x*qpow(A,b,p)%p)%p;
// printf("%lld %lld
",B,C);
// ll K=inv(qpow(B,a,p),p);
// cout<<C *K%p<<endl;
return 0;
}