基于中国剩余定理的秘密共享方案(使用miracl库)

某电信安数基实验

该实验本意是在大数的场景下运行,故而需要使用miracl库,具体使用方法请看https://blog.csdn.net/qq_42450533/article/details/102493504的后半部分

基于中国剩余定理的秘密共享方案
秘密共享是将秘密以适当的方式拆分,拆分后的每一个子秘密由不同的参与者管理,单个参与者无法恢复秘密信息,只有若干个参与者一同协作才能恢复秘密消息。并且,当其中某些参与者出问题时,秘密仍可以恢复。
(𝒕,𝒏) 门限秘密共享方案
将秘密 𝒌 分成 𝒏 个子秘密 𝒌𝟏,𝒌𝟐,⋯,𝒌𝒏,满足下面两个条件:
(1) 如果已知任意 𝒕 个𝒌𝒊值,易于恢复出 𝒌;
(2) 如果已知任意 𝒕−𝟏 个或更少个𝒌𝒊值,不能恢复出 𝒌。
将一个密钥分成𝒏份,那么𝒏个人中至少𝒕人在场才能获得密钥。

在本实验中,我们以(3,5)门门限秘密共享方案为例,k值为500位左右的大整数

在这里插入图片描述
在这里插入图片描述

在程序编写过程中,我们发现如果使用穷举的方法去寻找d值的话,计算速度会非常慢,只要大数文件稍微大一些,运行时间就会指数级增长。
由于我们的k值是一个500位的大整数,所以我们可以这么想:寻找5个200位的整数,使其递增而且都是质数,由于我们的位数足够大,所以我们很容易能够找到这样子的5个数。
满足上述条件的5个大整数,由于其都是质数,所以两两互素;前3个数的乘积是600位的整数,这个乘积大于k值(500位),后2位的整数的乘积是400位的整数,这个乘积小于k值(500位)。故而满足上述条件即满足 d值递增,d值两两互素,N>k>M三个条件。
关于中国剩余定理的应用请看另一篇博文中国剩余定理的算法实现(基于c语言miracl库)

注意:测试运行时大数文件中的大整数必须在500位左右,必须关闭安全检查(属性,C/C++,代码生成,关闭安全检测)
程序运行需要几秒钟时间

C语言代码

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "miracl.h"
#include<Windows.h>
big ki[5], di[5];
void zhongguo(int t,int n)
{
	int i,num[5];//
	big x = mirvar(0);
	big one = mirvar(1);
	big m = mirvar(1);//m是di连乘的乘积
	big Mit[5];//Mi
	big Mit_1[5];//Mi的逆
	big g1[5];//中间变量,计算Mi*Mi的逆*ai(a1即Ki)

	printf("\n请选择%d个子秘密,输入序号1 - %d\n", t, n);
	for (i = 0; i < t; i++)
	{
		scanf("%d", &num[i]);
		num[i]--;//使序号从1 - t ,转化为 0 - t-1,符合数组下标的实际情况
	}

	//初始化
	for (i = 0; i < n; i++)
	{
		Mit[i] = mirvar(0);
		Mit_1[i] = mirvar(0);
		g1[i] = mirvar(0);
	}
	
	//m=di[num[i]]连乘
	for (i = 0; i < t; i++)
	{
		multiply(m, di[num[i]], m);//di[num[i]]表示的就是中国剩余定理中的mi
	}

	//Mit[t]=mt/di[num[i]],即计算Mi
	for (i = 0; i < t; i++)
	{
		fdiv(m, di[num[i]], Mit[i]);//除法
	}

	//Mit_1为Mit的逆
	for (i = 0; i < t; i++)
	{
		xgcd(Mit[i], di[num[i]], Mit_1[i], Mit_1[i], Mit_1[i]);//求逆运算
	}

	//g1 = Mi t* Mit_1 * ki[ num[i] ]
	for (i = 0; i < t; i++)
	{
		multiply(Mit[i], Mit_1[i], g1[i]);
		multiply(g1[i], ki[num[i]], g1[i]);
	}

	//x=g1[1]+g1[2]+...+g1[t]
	for (i = 0; i < t; i++)
	{
		add(x, g1[i], x);
	}
	powmod(x, one, m, x);// g1 = g1的一次方 mod m

	printf("\n");
	printf("秘密 is : \n");
	cotnum(x, stdout);
	printf("\n");
}
int coprime(int n)
{
	int i, j;
	big one = mirvar(1);//big型数值1
	big q = mirvar(0);
	int flag = 1;//假设两两互素
	for (i = 0; i < n; i++)
	{
		for (j = i + 1; j < n; j++)
		{
			egcd(di[i], di[j], q);
			if (compare(q, one) != 0)
			{
				flag = 0;
			}
		}
	}
	mirkill(q);
	mirkill(one);
	return flag;//如果不能够两两互素,则返回0,若能,则返回1

} 
int main()
{
	FILE *fp;
	char fpname[100];//文件名
	miracl *mip = mirsys(800, 10);
	big secret = mirvar(0);//k为秘密
	big one = mirvar(1);//big型数值1
	big zero = mirvar(0);//big型数值0
	big p = mirvar(0);
	int i;
	int n = 5, t = 3;//这是一个(t,n)门的秘密共享方案
	char num[250];

	for (i = 0; i < n; i++)
	{
		ki[i] = mirvar(0);//对每一个ki[]进行初始化
		di[i] = mirvar(0);//对每一个di[]进行初始化
	}

	//
	printf("输入大数secret的文件完整路径\n");
	scanf("%s", fpname);
	if ((fp = fopen(fpname, "r")) == NULL)
	{
		printf("fail to open the file\n");
		system("pause");
		exit(0);
	}
	else
	{
		/*随机创建一个秘密,这个秘密有500为
	    bigdig(500, 10, secret);
	    printf("随机的秘密为:\n");
	    cotnum(secret, stdout);
	    */

		cinnum(secret, fp);//从fp文件中把大数赋值给big型变量secret
		printf("\n");
		cotnum(secret, stdout);//打印一下

	    //创建一个字符串,这个字符串以1开头,以1结尾,一共有200位数
		num[0] = '1';
		for (i = 1; i < 200; i++)
		{
			num[i] = '0';
		}
		num[i - 1] = '1';
		num[i] = '\0';

		//将num转化为大数
		i = cinstr(p, num);

		//开始寻找di的值
		loop:for (i = 0; i < 5;)//找到5个符合条件的di就跳出
		{
			if (isprime(p))//判断p是否为素数,是的话把p赋给di[]
			{
				copy(p, di[i]);//di[i]=p,赋值操作
				i++;
			}
			incr(p, 2, p);//不管p是否为素数,每次循环加2
		}
		if (coprime(n) == 0)//fermat素性检测算法有极小概率出问题,故而验证d值是否两两互素,若不互素,则重新寻找一组d值
		{
			goto loop;
		}

		//计算ki
		for (i = 0; i < n; i++)
		{
			powmod(secret, one, di[i], ki[i]);//ki[i]=k(mod di[i])
		}
		//打印子秘密
		for (i = 0; i < n; i++)
		{
			printf("\n第%d个子秘密(di,ki)为:----------------------------\n", i + 1);
			cotnum(di[i], stdout);
			cotnum(ki[i], stdout);
			printf("---------------------------------------------------\n");
		}

		//接下来进行秘密复原
		zhongguo(t, n);
	}

	

	//程序结束
	system("pause");
	return 0;
}

结果截图
在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值