信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)

    信息安全基础综合实验总共包含有二大块的内容,分为小组作业(小组作业有四项任务,为Fermat素性检验算法、中国剩余定理、密钥分配以及SM3的实现)和个人作业(SM2加密算法的实现),我也会分别通过五篇博客来分别记录。先进行小组作业,等把小组作业的四次做完之后,就可以对Miracl库的使用基本上掌握了。

    俗话说的好,要做实验,肯定要先搭建环境,环境两小时,实验五分钟。而实验所需要的环境就是把miracl库添加进来即可。首先编译miracl包,参加我同学W的这个博客:https://blog.csdn.net/Baron_wu/article/details/83151473,里面讲述了如何生成所需要的miracl.lib,如果搞不定的话,那就来问我索取吧(邮箱联系[email protected]);得到了这个包之后,那环境就算是完成了90%了,下面是在Visual Studio中调用此库即可,过程可以继续参考我这个同学W的另外一篇博客:https://blog.csdn.net/Baron_wu/article/details/83177251。通过这两个步骤后,就可以很开心的去编程吧!顺便感谢一下这个同学W,为什么他的出镜率这么高呢,因为我们两个是一组的,当时为了能够成功地调用Miracl库也是费了一番心思。

    那下面就切入正题,看看如何通过Miracl库来实现Fermat素性检验算法。因为这是第一篇的博客嘛,除了对Fermat素性检验的介绍之外,对于一些Miracl库中的函数也会有一个很简单的介绍。

一、实验目的

  在前面的四次小实验中,对我们的考察难度不是很大,四个小实验对我们提出来的要求是,通过完成验证四个定理的过程,让我们能够相比较才学习信息安全数学基础与现代密码学时,能更加详细的了解关于这四个定理的内容。第一次的实验是使用Fermat素性检验算法(这是一个概率性算法),来判断从文本文件中输入进去的大整数是不是一个素数。在平时我们接触到的C语言结构中,最大的表示数值是unsigned int型数据,其最大可以表示数据2^{64},也就是八个字节的大小,即使是这样,对于我们信息安全实验来说,这样的数据类型长度是远远不够的。在实验中,我们需要用到miracl函数库,它定义了两种新的数据类型——表示大整数的big类型和表示有理数的flash(short for floating-slash)类型。通过本次实验,可以让我们熟悉miracl库中的一些基本操作函数,将Fermat素性检验算法在实验中展示出来。

二、方案设计

2.1 Fermat素性检验

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第1张图片

也就是说,要判断一个奇整数是不是素数(如果这个数是偶数那肯定就不是素数了),我们可以通过随机选取同m互为质数的一个整数a(如果m和a不互质的话,那么m也肯定不是素数),判断m和a是否满足费马小定理,如果满足的话,m就会以不低于\frac{1}{2}的概率是一个素数。对于这个定理的证明,我也去网上查找了相关的资料,但是依旧对这个定理的证明不是特别的了解,等到以后能力提升再来读懂此定理的证明,也不在报告里附上此定理的证明了。

   下面是Fermat素性检验算法的步骤,这儿我用一张图来阐明Fermat素性检验算法的原理:

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第2张图片

 2.2 关于Fermat素性检验算法单身的背景以及Carmichael

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第3张图片

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第4张图片

       人们自然会想,如果考虑了所有小于n的底数a,出错的概率是否就可以降到0呢?没想到的是,居然就有这样的合数,它可以通过所有a的测试。第一个发现这样极端的伪素数,他把它们称作Carmichael数。你一定会以为这样的数一定很大。错。第一个Carmichael数小得惊人,仅仅是一个三位数,561。前10亿个自然数中Carmichael数也有600个之多。Carmichael数的存在说明,我们还需要继续加强素性判断的算法。

      比如说,1105就是一个Carmichael数,对于用Fermat素性检验算法来判断1105(十六进制下表示是451)是不是质数,得出的结果是1105能够以98.4375的概率成为一个素数。所以这点很直观的体现出了Fermat素性检验是一个概率性算法。

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第5张图片

 

三、方案实现

3.1 算法流程图

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第6张图片

3.2 主要函数的介绍

   引入了miracl库后,其中定义了两种新的数据类型——表示大整数的big类型和表示有理数的flash(short for floating-slash)类型,因此随之也引入了能够操作big类型和flash类型的操作函数。整体上来说,完成实验所需要的语言是C语言,但是在其中一些关键地方的操作上,我们需要使用库中自己定义的函数,将这些函数的功能了解后,基本上写出Fermat素性检验算法就没有什么问题了。在miracl_5.5.4中,附带着一个manual.doc文件供我们参考,里面有所有函数的定义以及如何使用等,这个文件对于我们了解如何使用miracl库有非常重要的作用。

3.2.1 mirsys()

    函数原型: miracl *mirsys(int nd, int nb);

功能说明: 初始化当前程序线程的MIRACL系统,如下所述,必须在尝试使用任何其他MIRACL例程之前调用:

(1)初始化错误跟踪机制。

(2)从nd和nb计算用于每个大/闪存号的计算机字数。

(3)初始化了16个大的工作变量(其中4个为双倍长度)。

(4)某些实例变量被赋予默认初始值。

(5)通过调用irand(0L)启动随机数发生器。

这个函数的返回值是是一个miracl实例指针,通过它可以访问所有实例变量,如果没有足够的内存来创建实例,则为NULL。

操作实例是miracl *mip=mirsys(500,10),意思是我定义的这些变量最大长度都是500位(这个位是后面进制的位数),输入、输出、运算用的进制都是10进制。

3.2.2 实例变量IOBASE

   IOBASE是用于控制输入和输出的进制问题的,可以在程序中随意更改, 必须大于或等于2且小于或等于256。使用实例是像这样的:mip->IOBASE=16,这样子输入的变量和输出的变量所使用的进制都是十六进制。

3.2.3 mirvar()

      函数原型:flash mirvar(iv)

     功能说明:通过为其保留适当数量的内存位置来初始化大/闪存变量,可以通过对函数mirkill()的后续调用来释放该存储器。并且在程序中,每个big型变量都必须赋初始值,否则会出错。

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第7张图片

      例如上面的这段代码是用来演示没有初始化big型变量带来的错误,如果没有初始化变量,在compile和build阶段系统都会告诉我们没有警告,没有错误,但是一旦执行可执行文件后,系统就会崩溃。出错信息如下: 

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第8张图片

3.2.4 decr()

   函数原型:void decr(x,n,z)

             big x,z;

             int n;

   这个函数实现的功能是对一个big型的变量x减去一个int型的值后得出的big型数据,例如我们在Fermat素性检验算法中,产生的随机数范围在2至m-2中,如果我们需要得出m-2的话,有两种途径:第一,如果将减去的2视作为int类型的话,直接相减是不可行的,相当于是big型减去int型,需要用到这个函数,即decr(m,2,y),返回的结果是big y=m-2;第二,如果将2作为大数来看待的话,就需要先用negify()函数取2的复数,再使用add()函数得到m-2的结果。

3.2.5 bigrand()&bigdig()

函数原型: void bigrand(big w, big x);

功能说明: 使用内置的随机数发生器,产生一个小于w的大数随机数,x

  函数原型: void bigdig(int n, int b, big x);

功能说明: 产生一个指定长度的进制的随机数,该函数使用内置的随机数发生器,初始化种子调用irand函数。

这两个函数都是可以生成随机数的,但是它们的功能确实略有差异的。bigrand()是产生一个小于w的大数随机数,x

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第9张图片

上面的截图是我测试的bigdig()这个函数,为了验证这个函数是产生一个指定长度的进制的随机数,我在这里只让它生成二位十进制数,并且循环随机生成一千次(这种情况下,从概率角度来说,0-100这些数每个数出现的次数都能平均在10次左右),从输出的结果中看,只会产生10-99这个区间内的数,不会产生01、05这样的一位十进制数,证明了bigdig()只会产生指定长度的进制的随机数。

   下面的截图是我测试的bigrand()这个函数的功能,和上面测试的原理是一样的,在这次的输出结果中,可以看到不仅仅有二位十进制数字,还有一位十进制数字,证明了bigrand()是产生一个小于给定数值的大数随机数。

   在Fermat素性检验算法中,每轮的算法使用到的底数a是在2至m-2这些数中随机选取一个数作为底数,然后进行下面的算法,因此,在每轮中随机选取出的随机数必须是表现出完全的随机性。因此对于随机函数的选择是十分有必要的,在这里我选择的是bigrand()。

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第10张图片

3.2.6 compare()

函数原型: int compare(big x, big y);

功能说明: 比较两个大数的大小。

返回值: x>y时返回+1, x=y时返回0, x

3.2.7 egcd()

函数原型:   int egcd(bigx, big y, big z);

功能说明:计算两个大数的最大公约数,z=gcd(x,y)。

3.2.8 powmod()

函数原型: void powmod(big x, big y,big z, big w);

功能说明: 模幂运算。

3.2.9 mirkill()

函数原型:void mirkill(x)      big x;

功能说明:通过将其归零并释放其内存来安全地杀死大/闪存数字。

3.2.10 mirexit()

函数原型: void mirexit();

功能说明: 清除MIRACL系统,释放所有内部变量。

3.3 算法实现的主要代码

#include "miracl.h"
#include 
#include 
#include 
#include 
#define round 6
int Fermatjdu_prime(big obj);
main()
{
    FILE *fp;
	big obj;
    miracl *mip = mirsys(1500, 16);//定义的这些变量最大长度都是5000位(这个位是后面进制的位数),输入、输出、运算用的进制都是16进制。
    mip->IOBASE = 16;
	obj=mirvar(0);   //初始化变量obj,obj是输入的需要判断是否为素数的大数
    if((fp=fopen("data.txt","r+"))==NULL){
        printf("Open the file failure...\n");
        exit(0);
    } //判断文件是否能够正确打开
	while(!feof(fp)){    //检测文件结束符
		cinnum(obj, fp); //从文件中读取一个数字进入,并将其强制转化为十六进制表的大数obj
		cotnum(obj, stdout); //向屏幕上输出一个大数obj
		if (Fermatjdu_prime(obj))
			printf("This number has a %6.4f%% probability of being a prime number.\n", 100 * (1 - pow(0.5, round)));
		else
			printf("This number is 100%% definitely a Composite number! \n");
	}
	fclose(fp);
	mirkill(obj);  //释放大数obj所占用的空间
	mirexit();     //清楚miracl系统
}

int Fermatjdu_prime(big obj)
{
big radn,trans,mgcd,trans1,r,num1,num2,cons;
int i,j;
miracl *mip = mirsys(1500, 16);
mip->IOBASE=16;
radn=mirvar(0);//对函数中使用到的big型变量进行初始化
trans=mirvar(0);
mgcd=mirvar(0);
trans1=mirvar(0);
r=mirvar(0);
num1=mirvar(1);
num2=mirvar(2);
cons=mirvar(0);
i=0;
j=0;
decr(obj,2,trans);    //trans=obj-2
decr(obj,1,trans1);   //trans=obj-1
srand((unsigned int)time(NULL));
for(i=0;i

 

四、数据分析

  在这部分的数据分析时,还未给老师验收,这部分测试的数据是我自己生成的数。这些数据是我借鉴的一个同学用python脚本写出来的,生成的时候是按一个合数一个素数进行生成的,用写成的算法跑了一下之后,和预期是一样的,用Fermat素性检验算法能够把里面所有的合数都检测出来,里面所有的素数都能够以概率98.4375%确定(轮数是六轮,当然这些数都是自己生成的素数,所以可以判断写出的程序没有问题)。

  此外,在查阅资料的过程中,有这样的一种数的存在,即Carmichael数,我用自己的程序也跑了一下,确实这种数对于Fermat素性检验算法来说无法识别。

 

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第11张图片

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第12张图片

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第13张图片

 

五、总结

  在本次上机实验中,主要需要我们解决的问题有两个方面:一方面是实验环境的搭建,另外一方面是对miracl库中的函数需要一定的熟悉度。我们组在环境的搭建上采用了两条路线,一条是Win10系统+编译器是Visual Studio,另外一条的环境就是和实验室一样的Win7系统+编译器是Visual C++ 6.0。最初拿到实验任务,首先想到的肯定是网上搜索一翻资料看看如何配置这样的环境,在网上看到的一个比较靠谱的教程是叫我们将miracl.h、mirdef.h以及ms32.lib添加到工程下面,miracl.h、mirdef.h这两个文件直接可以在/include文件夹下找到,但是找不到ms32.lib这个链接库,所以我们就去CSDN上下载了一个别人编译过的链接库,但是装入到工程下面后,经过一些简单的调试却出错:告诉我们连接不到这个库,所以从网上下载的ms32.lib是不完善的库。所以我们决定自己编译一下静态链接库。

信息安全基础综合实验之Fermat素性检验算法(通过调用miracl大数库来实现)_第14张图片

 

你可能感兴趣的:(信息安全数学基础系列实验,Miracl大数库,信息安全数学基础实验,Fermat素性检验算法,C语言)