Fermat素性检验算法(基于miracl的大数运算)

时间:2024-04-12 07:13:16

Fermat素性检验算法

一、实验目的

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

二、方案设计(算法流程图)

Fermat素性检验算法(基于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型变量都必须赋初始值,否则会出错。

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<w

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

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

这两个函数都是可以生成随机数的,但是它们的功能确实略有差异的。bigrand()是产生一个小于w的大数随机数,x<w,如果w是一个十位的十进制数,那么x可能是一个十位的十进制数,只有九位的十进制数,也可能使只有一位的十进制数;bigdig()是产生一个指定长度的进制的随机数,比如说指定了产生一个十位的十进制数,那么这个函数就会严格的产生一个十位的十进制数。

3.2.6 compare()

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

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

返回值: x>y时返回+1, x=y时返回0, x<y时返回-1。在这里需要注意的是,compare()函数比较的是两个big类型的数,此函数的返回值是int型的+1和-1。

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系统,释放所有内部变量。

四、算法实现的主要代码

#include "miracl.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#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<round;i++)
    {
        bigrand(obj,radn); //生成所需要的随机数
        egcd(radn,obj,mgcd);  //计算obj和生成的随机数的最大公因数
	    if(!compare(mgcd,num1))  //判断obj和随机数是否互素,它们的最大公因数如果不是1的话,            compare函数将会返回1,不满足条件
	    {
          powmod(radn,trans1,obj,r);  //计算 ,如果r=1,则obj可能是素数,进入下一个if语句
	      if(!compare(r,num1))  j++  //j是判断因子,如果一个数能够满足在当前的轮数下,满足上述的算法,则j能够计数;如果j不等于轮数,那么这个数就不是素数;
	    }
    }
       if(j==round)
       return 1;
       else 
       return 0;

    mirkill(obj);
    mirkill(radn);
    mirkill(trans);
    mirkill(trans1);
    mirkill(r);
    mirkill(mgcd);
}  

最后说明环境配置问题:

编译miracl.lib文件和在VS2017中调用miracl库。网址链接分别是:

Win10下编译miracl包

Miracl配置