xd信息安全数学基础密码学实验-2 中国剩余定理


上一篇fermat素性检测算法的文章请跳转到:
https://blog.csdn.net/Koz_0/article/details/109177491

一、基础知识原理

基础知识上课老师都讲了,也有相关的ppt,这里就不多说了。
但是我个人觉得这个逆元的概念比较有趣。
其基本思想和解方程组差不多,但这里是同余方程组。
在这里插入图片描述

visio流程图如下图所示:
在这里插入图片描述

二、算法实现

1.环境

使用的是vc 6++ 和miracl大整数库。
miracl整数库的配置可以自行去百度一下,应该也有不少。我这里提供一下miracl整数库的配置资源吧。见链接:
如果在配置的时候有什么问题可以私信或者评论,我会尽力而为的。
链接:http@@s://p@@an.baidu.c@@om/s/1HKP-v0OFQIPyZmMjRSPFJw
提取码:jops (把@删除掉就是完整链接)

2.Miracl库函数说明

此部分主要列举了一些用到的函数,因为是大整数,所以对于一般的“=”赋值或者“*”乘法都无法实现,需要用函数实现。

	1、
    miracl *mip = mirsys(10000,10); //初始化10的五次方
    mip->IOBASE = 10;  //设置 10进制
	2、
	x = mirvar(0);   //初始化
	//给x赋值大整数0
	3cinnum(m,fp);//从文件中读取一个数
	4bigrand(x,a);//生成随机数 
	//a<x=m-1
	5egcd(a,m,g);//求a和m的最大公约数 
	//g = (a,m)
	6powmod(a,x,m,r);//模幂运算,
	//r=ax (mod m)
	7cotnum(m,stdout)//把大整数m打印到终端
	8multiply(mj[i],m, m);
	//m = m * mi
	9divide(x, y, z) 
	//z = x / y
	//也可以求模值
	divide(x,y,z) //x = x mod y
	10xgcd(Mj[i], mj[i], Mj_contrary[i], Mj_contrary[i], Mj_contrary[i]);
	//计算mj的逆
	xgcd(x,p,z,z,z);   //z = x^-1 mod p => z*x = 1 (mod p)
	

3.主要代码

这里就不多说什么了,算法比较简单,难点是其中库函数的运用。
代码中也有注释,不懂的可以私信我。
P.S.我的代码里面那块注释我也没有什么好方法来实现,如果有大佬有什么好方法希望能指明方向。
代码如下:

#include<stdio.h>
#include<math.h>
#include"miracl.h"

int main()
{

	int j = 0;
	int i = 0;
	FILE *fd;
	int k = 3;
	miracl *mip = mirsys(1000, 10);//初始化10的五次方
	//mip->IOBASE = 10;  //设置 10进制
	big a[3], mj[3], Mj[3], Mj_contrary[3];
	big m, res;
	big temp, one;
	big nok;
	m = mirvar(1);
	one = mirvar(1);
	res = mirvar(0);
	temp = mirvar(0);
	nok = mirvar(1);
	for (i=0;i<k;i++) {
		a[i] = mirvar(0);
		mj[i] = mirvar(0);
		Mj[i] = mirvar(0);
		Mj_contrary[i] = mirvar(0);
	}
	
    fd = fopen("2.txt","r");
	if(fd == NULL) {
		printf("Error!");
		return 0;
	}

	for (i=0;i<k;i++) {
		cinnum(a[i],fd);
	}
	for (i=0;i<k;i++) {
		cinnum(mj[i],fd);
	}
	fclose(fd);

	for (i=0;i<k;i++){            //判断mi是否是互素的≡
		for (j=i+1;j<k;j++) {
			egcd(mj[i], mj[j], temp);
			if (compare(one, temp)) {
				printf("mj不互素");
				return 0;
			}
		}
	}
	/*没有办法把cotnum自带的换行取消掉,没法打印出来方程组
	printf("同余方程组为:\n");
	for(i=0;i<k;i++){
		printf(" x≡ ");
		cotnum(a[i], stdout);
		printf(" ( mod ");
		cotnum(mj[i],stdout);
		printf(" )");
		printf("\n");
	}
	printf("\n");
	*/

	for (i=0;i<k;i++){//m = m1*m2*m3
		multiply(mj[i],m, m);//m = m * mi
	}

	for (i=0;i<k;i++) {
		copy(m, temp);// temp = m
		divide(temp, mj[i], Mj[i]);//求Mj = m / mj
		//divide(x, y, z) z = x / y
		//这里不能直接用m,因为divide也有取余的功能,会改变m的值
	}

	for (i=0;i<k;i++){
		xgcd(Mj[i], mj[i], Mj_contrary[i], Mj_contrary[i], Mj_contrary[i]);//计算mj的逆 
        //xgcd(x,p,z,z,z);   z = x^-1 mod p => z*x = 1 (mod p)
	}

	for (i=0;i<k;i++) {
		multiply(Mj[i], Mj_contrary[i], Mj[i]);
		multiply(Mj[i], a[i], temp);
		divide(temp, m, nok); //求temp (mod m)  
		//divide(x,y,z) =>x = x mod y
		add(res, temp, res);
	}

	divide(res, m, temp);
	printf("得到方程组的解为:\n");
	printf("x = ");
	cotnum(res, stdout);

	mirkill(m);  //释放内存
    mirkill(one);
    mirkill(res);
    mirkill(m);
    mirkill(temp);
	/*好像加上不知道为什么会报错,就不加了,对结果无影响
	mirkill(a[3]);
	mirkill(mj[3]);
	mirkill(Mj[3]);
	mirkill(Mj_contrary[3]);
	*/
	mirexit(); //清除MIRACL系统,释放所有的内部变量
	getchar();
	return 0;
}

三、总结

这个是此课程的第二个实验。下一个实验我也会尽快上传的。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值