「密码学」-Elgamal密码体制
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\)
\(\therefore\)公钥\(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\)
\(\therefore\)密文为\((1430,697)\)解密
依题意:其中\(p=2357,\alpha=2,a=1751,C:(1430,697)\)
\(\therefore\)求出\(1430^{1751}\)在模\(p\)的逆元\(w=872\)
\(\therefore 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\n");
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\n");
scanf("%lld%lld%lld%lld",&p,&a,&b,&x);
byg = cal(p);
printf("%lld\n", 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)\n",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\n", 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\n",B,C);
// ll K=inv(qpow(B,a,p),p);
// cout<<C *K%p<<endl;
return 0;
}