C语言实现的shamir秘密共享

(ps:需提前安装pbc库 )

0、生成公共参数(椭圆曲线)

char *param = "type a\n"
              "q 8780710799663312522437781984754049815806883199414208211028653399266475630880222957078625179422662221423155858769582317459277713367317481324925129998224791\n"
              "h 12016012264891146079388821366740534204802954401251311822919615131047207289359704531102844802183906537786776\n"
              "r 730750818665451621361119245571504901405976559617\n"
              "exp2 159\n"
              "exp1 107\n"
              "sign1 1\n"
              "sign0 1";

int t = 3, n = 5;

int num = 16;

void initPP(PublicParameter *PP,char* param){
    pairing_init_set_buf(PP->pairing, param, strlen(param));
    element_init_G1(PP->P,PP->pairing);
    element_random(PP->P);

    return;
}

1、生成秘密共享

生成的secretshare会存在result里

​
void genshare(element_t secret,int n,int t,element_t *result,pairing_t pairing)
{

    element_t *a;//多项式系数a0....a(t-1)
    a = (element_t*)malloc(sizeof(element_t) * (t));
    element_t *share;//分享的密钥
    share = (element_t*)malloc(sizeof(element_t) * (n));

    //element_printf("secret in = %B\n",secret);

    element_init_Zr(a[0],pairing);//a0 = secret

    element_set(a[0],secret);
    //element_printf("a[0] = %B\n",a[0]);

    for(int i=1;i<t;i++)
    {
        element_init_Zr(a[i],pairing);
//        element_set1(a[i]);
        element_random(a[i]);
        //element_printf("a[%d] = %B\n",i,a[i]);
    }

    for(int i=0;i<n;i++)//share初始化
    {
        element_init_Zr(share[i],pairing);
        element_set(share[i],a[0]);
        //element_printf("share[%d] = %B\n",i,share[i]);
    }

    for(int i=1;i<=n;i++)//计算share0...4 sharei对应x=i+1
    {
        element_t tmp;//存储x ... x^(t-1)
        element_t x;

        element_init_Zr(tmp,pairing);
        element_init_Zr(x,pairing);

        element_set_si(x,i);

        for(int j =1;j<t;j++)
        {
            element_t tmp1;//存储a[j]*x^j
            element_t xpowj;
            element_t jz;

            element_init_Zr(tmp1,pairing);
            element_init_Zr(xpowj,pairing);
            element_init_Zr(jz,pairing);

            element_set_si(jz,j);
            element_pow_zn(xpowj,x,jz);

            element_mul(tmp1,a[j],xpowj);
            element_add(share[i-1],share[i-1],tmp1);

            element_set0(tmp1);
        }
    }
    for(int i=0;i<n;i++)//赋值
    {
        element_init_Zr(result[i],pairing);
        element_set(result[i],share[i]);
        element_printf("%B\n",result[i]);
    }
    free(a);
    free(share);


}

​

2、随机选择服务器做门限

需要注意这里的result和上面不同,这里的result是服务器列表

void random_select(int* result)
{
    // 初始化数组
    for (int i = 0; i < n; i++) {
        result[i] = i;
    }
    // 随机交换数组中的元素
    srand(time(NULL));
    for (int i = n - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        int temp = result[i];
        result[i] = result[j];
        result[j] = temp;
    }
    // 返回前 t 个元素
    for (int i = 0; i < t; i++) {
        printf("%d ", result[i]);
    }
    printf("\n");
}

3、抽象拉格朗日差值法

void get_lagrange_coefficient(int a,int *shareid,element_t *lagrange_co,pairing_t pairing)
{
    //printf("lagrang\n");
    int thisid = a+1;
    int idgroup[t];
    for(int i=0;i<t;i++)
    {
        idgroup[i]=shareid[i];
        //printf("%d\n",idgroup[i]);
        idgroup[i]++;
    }


    element_t l;
    element_t ll,lr;
    element_t lrn;

    element_init_Zr(l,pairing);
    element_init_Zr(lrn,pairing);

    element_init_Zr(ll,pairing);
    element_init_Zr(lr,pairing);

    signed long int lleft=1;
    for(int i=0;i<t;i++)
    {
        if(idgroup[i]==thisid)
        {
            continue;
        }
        lleft = lleft * (0-idgroup[i]);
    }

    signed long int lright=1;
    for(int i=0;i<t;i++)
    {
        if(idgroup[i]==thisid)
        {
            continue;
        }
        lright = lright * (idgroup[i]-thisid);
    }

    element_set_si(ll,lleft);
    element_set_si(lr,lright);
    element_invert(lrn,lr);

    element_mul(l,ll,lrn);
    element_init_Zr(lagrange_co,pairing);
    element_set(lagrange_co,l);
    element_printf("lagl %B\n",ll);
    element_printf("lagr %B\n",lr);
    element_printf("lagrn %B\n",lrn);
}

4、恢复秘密

void recover_secret(element_t* s,element_t *result,pairing_t pairing)
{
//    int shareid[3] = {3,2,1};
    int shareid[t];
    printf("选择的%d个用于计算w的服务器为:\n",t);
    random_select(&shareid);
//    for(int i=0;i<t;i++)
//    {
//        IS[shareid[i]].chosen=1;
//    }
    // for(int i=0;i<n;i++)
    // {
    //     printf("%d\n",IS[i].chosen);
    // }

    element_t *l;
    l = (element_t*)malloc(sizeof(element_t) * (t));

    for(int i=0;i<t;i++)
    {
        element_init_Zr(l[i],pairing);
        get_lagrange_coefficient(shareid[i],shareid,&l[i],pairing);
        //element_printf("lagrange_co%d=%B\n",i,l[i]);
    }


    element_t *wl;
    wl = (element_t*)malloc(sizeof(element_t) * (t));
    for(int i=0;i<t;i++)
    {
        element_init_Zr(wl[i],pairing);
        element_mul(wl[i],result[shareid[i]],l[i]);
        element_printf("%B\n",wl[i]);
    }
//    element_add(wl[1],wl[0],wl[1]);
//    element_add(wl[2],wl[1],wl[2]);
//    element_printf("wl %B\n",wl[2]);


    element_t *w_compute;//w_c[0]存w1w2,w_c[1]存w1w2w3....w_c[t-2]存最终结果
    w_compute = (element_t*)malloc(sizeof(element_t) * (t-1));
    element_init_Zr(w_compute[0],pairing);
    element_add(w_compute[0],wl[0],wl[1]);
//    element_printf("%B\n",w_compute[0]);

    for(int i=1;i<t-1;i++)
    {
        element_init_Zr(w_compute[i],pairing);
        element_add(w_compute[i],w_compute[i-1],wl[i+1]);
//        element_printf("%B\n",w_compute[i]);
    }

    element_init_Zr(s,pairing);
    element_set(s,w_compute[t-2]);
    element_printf("\nrecover secret = %B\n",s);
//    printf("here1\n");

    free(l);
    free(wl);
    free(w_compute);


}

5、主函数

int main() {
    printf("Hello, World!\n");

    initPP(&PP, param);

    element_t secret;
    element_t *result;
    element_t s;
    result = (element_t*) malloc(sizeof(element_t)*n);
    element_init_Zr(secret,PP.pairing);
    element_set_si(secret,10086);
    element_printf("%B\n",secret);
    genshare(secret,n,t,result,PP.pairing);
    recover_secret(&s,result,PP.pairing);
    
    return 0;
}

6、运行结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值