基于中国剩余定理的秘密共享方案

基于中国剩余定理的秘密共享方案

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

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "miracl.h"
#include<Windows.h>
#define SECRET_BITS 500		//秘密的位数 
#define N 5					//子秘密的个数n
#define T 3					//恢复秘密所需要的最少子秘密个数t
#define D_DIGBITS (((SECRET_BITS/T)+(SECRET_BITS/(T-1)))/2)	//di的位数,di的长度在B/t与B/(t-1)之间,使N(最小的前t个数的乘积)>k>M(最大的前t-1个数的乘积)
#define MAX_D ((N)*(D_DIGBITS)+(N))							// 定义大数系统的最大位数(稍微比N倍的d大就可以) 
big ki[N], di[N];
void zhongguo(big secret)
{
	int i, num[N];
	big x = mirvar(0);
	big one = mirvar(1);
	big m = mirvar(1);//m是di连乘的乘积
	big Mit[N];//Mi
	big Mit_1[N];//Mi的逆
	big g1[N];//中间变量,计算Mi*Mi的逆*ai(a1即Ki)

	printf("\n                                                     秘密恢复");
	printf("\n请选择%d个子秘密,输入序号1 - %d\n", T, N);
	for (i = 0; i < T; i++)
	{
		scanf_s("%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]=m/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]);//求逆运算,Mit_1为Mit在模di[num[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);// x = x^1 mod m

	printf("\n");
	printf("秘密: \n");
	cotnum(x, stdout);
	printf("\n");

	//判断恢复的秘密与原秘密是否相同
	if (mr_compare(x, secret) != 0)
		printf("恢复的秘密与所给秘密不同!");
	else printf("恢复的秘密与所给秘密相同!");
	printf("\n");
}


int main()
{
	FILE* fp;
	char fpname[] = "s.txt";//文件名
	miracl* mip = mirsys(MAX_D, 10);//初始化大数系统,最大位数和进制
	big secret = mirvar(0);//秘密
	big one = mirvar(1);//big型数值1
	big a= mirvar(1);//代表D_DIGBITS位的10进制随机数
	big n= mirvar(1);//代表N=d1*d2*...*dt
	big m = mirvar(1);//代表M=d(n-t+2)*d(n-t+3)*...*dn
	int i;

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

	//从文件中读秘密
	if ((fp = fopen(fpname, "r")) == NULL)
	{
		printf("Fail to open the file\n");
		return -1;
	}
	else
	{
		cinnum(secret, fp);//从fp文件中把大数赋值给big型变量secret
		printf("                                                     秘密读取\n");
		cotnum(secret, stdout);//打印secret内容

		

	//挑选出五个素数,满足严格递增。只需要产生相邻的素数即可。
	printf("                                                     秘密分割");
	printf("\n产生的di:\n");
	bigdig(D_DIGBITS,10, a);//产生一个D_DIGBITS位的10进制随机数a
	i = 0;
	while (i != N) 
	{
		add(a,one, a);//a=a+1
		if (isprime(a)) //判断大数a是否为素数,为素数返回TRUE,否则返回FALSE
		{
			absol(a, di[i]);//di=|a| 
			cotnum(di[i], stdout);
			printf("\n");
			i++;
		}
	}
		
	//求出子秘密
	printf("\n产生的子秘密为:\n");
	for (i = 0; i < N; i++) 
	{
		ki[i] = mirvar(1);
		powmod(secret,one, di[i], ki[i]);//模幂运算,ki[i]=secret^1(mod di[i])
		printf("\n第%d个子秘密k%d为:\n", i + 1,i+1);
		cotnum(ki[i], stdout);
	}

	//打印N=d1*d2*...*dt
	for (i = 0; i < T; i++)
	{
		multiply(di[i], n, n);
	}
	printf("\nN的值为:\n");
	cotnum(n, stdout);
		
	//打印M=d(n-t+2)*d(n-t+3)*...*dn
	for (i = N-1; i >(N-T); i--)
	{
		multiply(di[i], m, m);
	}
	printf("\nM的值为:\n");
	cotnum(m, stdout);
	printf("\n");

	//进行秘密复原
	zhongguo(secret);
	}

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值