用生日攻击方法求解离散对数问题(C语言实现)-大三密码学实验

article/2025/4/22 12:29:33

实验原理:

生日攻击:输入为生成元a的阶p-1和元b,输出为离散对数x= log_{a}^{b}。设置两个长度为p的列表:

1)列表1包含a^{k} mod p,通过随机选取p个k得到;                                                                         

 2)列表2包含b a^{-l}modp,通过随机选取p个l得到;                                                                     

则在两个列表中很有可能出现重复的项,即a^{k}=ba^{-l},因此a^{k+l}=b(mod p),那么x=k+l(mod(p-1))就是要找的离散对数。

生日攻击是一个概率算法,无法保证一定能得到输出结果。

实验内容:

 a.简单的同余函数的构造

int tongyu(int a,int m,int n){//递归原理 long long int temp=a%n,ans;if(m==1){ans=temp;}else if(m>=2){ans=(temp*tongyu(a,m-1,n))%n;}return ans;
}

 原理:(a*b)mod c=((a mod c)*(b mod c))mod c

这里是a^{m}mod n,m逐步减小,直到1

但是这个顶多m为10000多,再多就不能运行了,而我们如果需要计算很大的m,就需要分解计算

b.对较大数字的拆分

void chaifen(int a,int b[10]){//把a按照万,千,百,十,个位上的数字区分开来,便于计算 int i,temp=10000;for(i=0;i<5;i++){b[i]=a/temp;a=a%temp;temp/=10;}
}

数组b是用来储存a的万位,千位,百位,十位,个位上的值

类似于水仙花数的处理

c.求a的10000,1000,100,10,1的次方的mod p

void qiu_cd(int c1[10],int a,int p){int temp=10000;for(int i=0;i<5;i++)//求对于a的10000,1000等次方对于p的求余 {c1[i]=tongyu(a,temp,p);temp/=10;}}

d.对a的万位,千位,百位,十位,个位的值的次方分别求余

void cheng(int p,int c1[10],int c11[10],int c111[10]){//各位上的数字的求余 for(int i=0;i<5;i++){if(c11[i]>0){c111[i]=tongyu(c1[i],c11[i],p);}else{c111[i]=0;}}
}

如果c11[i]=0,直接置0,否则就用用到tongyu函数,(a*b)mod c=((a mod c)*(b mod c))mod c

 e.对a各个位的值整合起来

long long int result_c(int a, int c1[10],int p,int c11[10],int c111[10]){//输出列表的值 long long int temp=1; chaifen(a,c11);cheng(p,c1,c11,c111);for(int j=0;j<5;j++){//万位到个位上的求余结合起来 if(c111[j]!=0){temp=((temp%p)*(c111[j]%p))%p;			}}return temp;
}

也是利用那个公式(a*b)mod c=((a mod c)*(b mod c))mod c

但是c111[j]=0不能带进去,因为会使得一个乘数为0,整体为0

f.构造列表并比较

void bijiao(int p,int a, int b,int p1,long long int c[15000][2],unsigned long long int ans,long long int d[15000][2],int c1[10],int c11[10],int c111[10],int count){int flag=0;for(int i=0;i<p1;i++){//求第一个列表 c[i][0] = 1+ rand() % (p-2);c[i][1] = result_c(c[i][0],c1,p,c11,c111);}for(int i=0;i<p1;i++){//求第二个列表 d[i][0] = 1+ rand() % (p-2);ans=result_c(d[i][0],c1,p,c11,c111);ans=((b%p)*ans)%p;d[i][1]=ans;}for(int i=0;i<p1;i++){		for(int j=0;j<p1;j++){if(c[i][1]==d[j][1]){//如果找到 cout<<"能找到离散对数x="<<c[i][0]-d[j][0]<<"(mod "<<p-1<<")"; flag=1;break;}}if(flag==1){//如果找到了,跳出循环 break;}}count++;if(count>10){//超过十轮,还是没找到 cout<<"找不到";flag=1;}if(flag==0){bijiao(p,a,b,p1,c,ans,d,c1,c11,c111,count);}
}

rand是随机数,rand()%(b),表明随机生成0-b之间的数字

两个for循环找相同值,找不到继续找,进入下一轮,再次调用bijiao函数,如果找了十轮还没找到,就说明真的很难找,建议不找,找到了通过flag跳出两个for循环。

g.总函数

#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<math.h>
using namespace std;
int tongyu(int a,int m,int n){//递归原理 long long int temp=a%n,ans;if(m==1){ans=temp;}else if(m>=2){ans=(temp*tongyu(a,m-1,n))%n;}return ans;
}void cheng(int p,int c1[10],int c11[10],int c111[10]){//各位上的数字的求余 for(int i=0;i<5;i++){if(c11[i]>0){c111[i]=tongyu(c1[i],c11[i],p);}else{c111[i]=0;}}
}void chaifen(int a,int b[10]){//把a按照万,千,百,十,个位上的数字区分开来,便于计算 int i,temp=10000;for(i=0;i<5;i++){b[i]=a/temp;a=a%temp;temp/=10;}
}void qiu_cd(int c1[10],int a,int p){int temp=10000;for(int i=0;i<5;i++)//求对于a的10000,1000等次方对于p的求余 {c1[i]=tongyu(a,temp,p);temp/=10;}}long long int result_c(int a, int c1[10],int p,int c11[10],int c111[10]){//输出列表的值 long long int temp=1; chaifen(a,c11);cheng(p,c1,c11,c111);for(int j=0;j<5;j++){//万位到个位上的求余结合起来 if(c111[j]!=0){temp=((temp%p)*(c111[j]%p))%p;			}}return temp;
}
void bijiao(int p,int a, int b,int p1,long long int c[15000][2],unsigned long long int ans,long long int d[15000][2],int c1[10],int c11[10],int c111[10],int count){int flag=0;for(int i=0;i<p1;i++){//求第一个列表 c[i][0] = 1+ rand() % (p-2);c[i][1] = result_c(c[i][0],c1,p,c11,c111);}for(int i=0;i<p1;i++){//求第二个列表 d[i][0] = 1+ rand() % (p-2);ans=result_c(d[i][0],c1,p,c11,c111);ans=((b%p)*ans)%p;d[i][1]=ans;}for(int i=0;i<p1;i++){		for(int j=0;j<p1;j++){if(c[i][1]==d[j][1]){//如果找到 cout<<"能找到离散对数x="<<c[i][0]-d[j][0]<<"(mod "<<p-1<<")"; flag=1;break;}}if(flag==1){//如果找到了,跳出循环 break;}}count++;if(count>10){//超过十轮,还是没找到 cout<<"找不到";flag=1;}if(flag==0){bijiao(p,a,b,p1,c,ans,d,c1,c11,c111,count);}
}
int main(){int a,b,p,p1,count=0;unsigned long long int ans=0;//p1为p的开方,ans中间值,count为轮数 long long int c[15000][2],d[15000][2];//c,d为两个列表 int c1[10],c11[10],c111[10];//c1为求a的10000等对p的余,c11为随机数的各个位上的数,c111为各个位上余数的集合 cout<<"输入三个数:";cin>>a>>b>>p;p1=int(sqrt(p));//求关于p的开方 qiu_cd(c1,a,p);//求c1 bijiao(p,a,b,p1,c,ans,d,c1,c11,c111,count);return 0;
}

h.测试结果


http://chatgpt.dhexx.cn/article/eEGBmM1a.shtml

相关文章

抗碰撞性、生日攻击及安全散列函数结构解析

回顾一下&#xff0c;密码学的上篇是完整性&#xff0c;完整性的保证是由一段定长的散列&#xff0c;俗称tag来确定的。又因为tag是定长的&#xff0c;而需要确保完整性的内容种类却可以认为是无限的。因此总有tag(mi)tag(mj)&#xff0c;mi ! mj&#xff0c;因此我们要引入抗碰…

密码学之生日攻击 离散对数问题求解 python实现

生日攻击 离散对数问题&#xff08; DLP &#xff09; 给定素数 p, α \alpha α, β \beta β 是模 p 非零的整数&#xff0c;令 β α x m o d p \beta \alpha^x\mod p βαxmodp &#xff0c;则求 x 的问题称为离散对数问题。 生日攻击是一种密码攻击&#xff0c;它利…

Hash函数与生日攻击

简介 Hash函数也叫杂凑函数、散列函数、哈希函数&#xff0c;可以把消息或数据压缩成固定长度的摘要 性质 等长性&#xff1a;给出任意的输入&#xff0c;得到的输出&#xff08;摘要&#xff09;长度不变。比如sha-1得到的摘要固定是160位&#xff0c;md5为128位单向性&#…

【Hash函数与生日攻击】

文章目录 一、Hash函数Hash函数关于密钥s散列函数定义碰撞发现实验-可忽略的散列函数安全性的三个典型的安全水平通用生日攻击 参考文献 一、Hash函数 Hash函数 将任意长度字符串压缩成短字符串的函数 关于密钥s 散列函数定义 碰撞发现实验-可忽略的 最强的安全性要求&…

生日攻击理解

1.什么是哈希碰撞&#xff1f;产生哈希碰撞的原因是什么&#xff1f;如何避免&#xff1f; 两个不同的输入&#xff0c;经过哈希算法后&#xff0c;得到了同样的哈希值&#xff0c;就叫做哈希碰撞。由于通常的哈希算法中&#xff0c;哈希值的空间远小于输入的空间&#xff0c;这…

哈希碰撞与生日相同概率

一、哈希碰撞是什么&#xff1f; 所谓哈希&#xff08;hash&#xff09;&#xff0c;就是将不同的输入映射成独一无二的、固定长度的值&#xff08;又称"哈希值"&#xff09;。它是最常见的软件运算之一。 如果不同的输入得到了同一个哈希值&#xff0c;就发生了&q…

密码学系列之:生日攻击

简介 生日攻击其实是一个概率论的问题&#xff0c;也就是说一个看起来很难发生的事情&#xff0c;事实上它发生的概率却很大。这种主观上和事实上的概率差距&#xff0c;让随机攻击成功的几率变的更高&#xff0c;这样的攻击就叫做生日攻击。 生日问题的由来 生日问题也叫做…

linux 清空redis缓存

1&#xff0c;进入目录redis下src目录。 #cd redis-2.8.17/src 2&#xff0c;执行redis-cli文件 #./redis-cli 3&#xff0c;执行命令&#xff1a;flushall&#xff0c;出现OK代表执行成功 #flushall 4&#xff0c;退出命令exit #exit 实例&#xff1a;

【redis】linux服务器清空redis

redis-cli 进入redis命令行 flushall 清除所有 如果报出“NOAUTH Authentication required.”错误&#xff0c;那么需要用密码授权 使用 auth [密码] 就可以继续操作了

redis数据清空脚本

redis服务经常因服务器内存不够用而自动死掉。需要经常连接进去做数据清理后启动服务。 所以写了个脚本每天清理一遍。 echo "flushall" | redis-cli -p 7000 -a password echo "flushall" | redis-cli -p 7001 -a password echo "flushall" |…

docker部署python程序清空redis数据

这里还是要推荐下小编的Python学习群: 823137423,不管你是小白还是大牛,小编我都欢迎 ,不定期分享干货,包括小编自己整理的一份2019年最新的Python资料和0基础入门教程视频,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。 docker部署python程序清空redis数据 线…

Windows 清空Redis数据

1.redis安装目录下输入cmd 2.redis-cli -p 端口号 3.flushdb 清除当前数据库缓存 4.flushall 清除整个redis所有缓存

Laravel 清空 Redis 队列

先说问题&#xff0c;我的网站搜索使用的 Laravel Scout Algolia 因为 Algolia 是收费的&#xff0c;免费版有容量限制。免费版应该是如下的限制&#xff1a; 一旦你的 计划超出配额&#xff0c;那么 Laravel 队列就会一直失败。失败他会重试导致 &#xff0c;队列一直累加、…

教你Redis 如何清空所有数据

这篇文章主要介绍了Redis 如何清空所有数据&#xff0c;具有很好的参考价值&#xff0c;希望对大家有所帮助。如有错误或未考虑完全的地方&#xff0c;望不吝赐教 Redis 清空所有数据步骤总结 1、打开cmd 命令窗口&#xff0c;切换至Redis 安装目录下的bin文件夹 2、在cmd 命…

lnx的导数证明

https://zhidao.baidu.com/question/524121644.html

MT【80】单调性求函数表达式

提示&#xff1a;$f(f(f(x)-lnx)-ln(f(x)-lnx))1ef(f(x)-lnx),\because f(x)$单调.得&#xff1a; $f(f(x)-lnx)-ln(f(x)-lnx)f(x)-lnx$,可以解出$f(x)ln(x)e$ 转载于:https://www.cnblogs.com/mathstudy/p/7630632.html

C语言:综合题,按x的值计算sinx,cosx,ex,lnx

0<x<10,输出sinx 10<x<20,输出cosx 20<x<30,输出ex 30<x<40,输出lnx x<0或x>40,输出zsdy #include<stdio.h> #include<math.h> int main() {double x;printf("input x");scanf("%lf",&x);if(x>0&am…