Supersonic代码解析

1. 引言

Bünz 等人2020年论文《Transparent SNARKs from DARK Compilers》,首次发表于IACR-EUROCRYPT-2020。

代码实现为:https://github.com/ksju6561/Transparent-SNARKs-from-DARK-Compilers

该代码库采用C++基于RSA group做了相应实现,有点小问题,第一次运行需手工创建下文件夹:

mkdir Txt
mkdir record

编译运行:

bash test_script.sh

2. 库依赖及主要结构体

2.1 库依赖

  • gmp:全称为GNU Multiple Precision Arithmetic Library,是一个开源的数学运算库,它可以用于任意精度的数学运算,包括有符号整数、有理数和浮点数。它本身并没有精度限制,只取决于机器的硬件情况。
  • crypto:即openssl中的crypto库。所用到的一些接口函数有:
    BN_generate_prime_ex:generate prime numbers larger than the specified bitsize。
    int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);:multiplies a and b and places the result in r (“r=a*b”). r may be the same BIGNUM as a or b. For multiplication by powers of 2, use bn_lshift(3)。
    BN_num_bits:计算bit位数。
    BN_rand_range:从特定范围内选择随机值。
    BN_gcd:求最大公约数。
    int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);:computes a to the p-th power modulo m (“r=a^p % m”). This function uses less time and space than BN_exp()。
    BN_dec2bn:将十进制字符串转换为BIGNUM。
    BN_cmp(): compares the numbers a and b.
    BN_ucmp(): compares their absolute values.

2.2 主要结构体

	typedef struct{
		int security_level;
		BIGNUM* G;
		BIGNUM* g;
		BIGNUM* q;
		BIGNUM* p;
	}_struct_pp_;

	typedef struct{
		BIGNUM* C;
		BIGNUM* Fhat;
	}_struct_commit_;

	typedef struct{
		BIGNUM** Fx;
		BIGNUM* input;
		int d;
	}_struct_poly_;

读取多项式参数的方法为:

int Read_poly(_struct_poly_* poly)
{
	FILE *fp;
	int i = 0, flag = 1;
	unsigned char *str;//[10000] = {0};
	str = (unsigned char *)calloc(sizeof(unsigned char),(10000000+2));    

	fp = fopen("./Txt/poly.txt", "r");
	poly->Fx = (BIGNUM**)calloc(sizeof(BIGNUM*), 10000000+2);
	while(1){								     
		poly->Fx[i] = BN_new();
		fscanf(fp, "%s", str);
		i++;
		if(feof(fp) != 0)
			break;
	}
	fseek(fp, 0, SEEK_SET ); 	
	poly->d = i-1;
	i=0;
	while(1){
		fscanf(fp, "%s", str);
		//printf("F[%d] : %s\n", i, str);
		flag &= BN_dec2bn(&(poly->Fx[poly->d-i]), str);
		i++;
		if(feof(fp) != 0)
			break;
	}

	poly->input = BN_new();

	fscanf(fp, "%s", str);
	flag &= BN_dec2bn(&(poly->input), str);

	fclose(fp);
	return flag;
}

3. Setup算法

S e t u p ( 1 λ ) Setup(1^{\lambda}) Setup(1λ):随机 G ← G G e n ( λ ) \mathbb{G}\leftarrow GGen(\lambda) GGGen(λ) g ← G g\leftarrow \mathbb{G} gG。返回 p p = ( λ , G , g , q ) pp=(\lambda,\mathbb{G},g,q) pp=(λ,G,g,q)
参见source/setup.c
代码中设置 λ = 512 \lambda=512 λ=512,多项式的degree d d d 通过参数 D D D传入,满足 d = 2 D − 1 d=2^{D-1} d=2D1,默认 d = 2 13 d=2^{13} d=213
构建的degree为 d d d的多项式(其系数默认为 ( 1 , 2 , ⋯   , d ) (1,2,\cdots,d) (1,2,,d)):

make_poly((1<<(DD-1)));

int make_poly(int d)
{
	BIGNUM* bn_tmp = BN_new();
	FILE *fp;
	int i = 0, flag = 1;
	unsigned char* str;

	fp = fopen("./Txt/poly.txt", "w");

	for(int i =0; i<d; i++)
	{
		flag *= BN_set_word(bn_tmp, 1+i); // random 
		str = BN_bn2dec(bn_tmp);
		flag *= fprintf(fp, "%s ", str);
	}

	fclose(fp);
	BN_free(bn_tmp);

	return flag;
}

注意,对于RSA group,要求 q > p 2 log ⁡ 2 ( d + 1 ) + 1 q>p^{2\log_2(d+1)+1} q>p2log2(d+1)+1

	BN_generate_prime_ex(pp,128,1,NULL,NULL,NULL);
	BN_set_word(qq,0);
	BN_set_bit(qq,128*(2*DD+1));

	#define D 14
	int DD;

	int security_level = 512;
	BIGNUM* pk = BN_new();
	BIGNUM* g = BN_new();
	BIGNUM* q = BN_new();
	BIGNUM* p = BN_new();

	if(argc == 2)
		DD = atoi(argv[1]);
	else
		DD = D;

	KeyGen_RSAsetup(pk, NULL, g, q, p, security_level);
int KeyGen_RSAsetup( BIGNUM *pk,  BIGNUM *sk, BIGNUM *g, BIGNUM *qq, BIGNUM *pp, const int k)
{
	BIGNUM* one = BN_new();
	BIGNUM* p = BN_new();
	BIGNUM* q = BN_new();
	BIGNUM* tmp = BN_new();
	BN_CTX* ctx = BN_CTX_new();

	do{
		BN_generate_prime_ex(p,(k>>1),1,NULL,NULL,NULL);
		BN_generate_prime_ex(q,(k>>1),1,NULL,NULL,NULL);
		BN_mul(pk,p,q, ctx);
	}while(BN_num_bits(pk) != k);

	//printf("%d\n", BN_num_bits(pk));
	if(sk != NULL){		
		BN_sub_word(p,1);
		BN_sub_word(q,1);
		BN_mul(sk,p,q,ctx);
	}

	BN_set_word(one,1);
	do{
		BN_rand_range(g, pk);
		BN_gcd(tmp, g, pk, ctx);
	}while(BN_cmp(tmp,one) != 0);

	BN_generate_prime_ex(pp,128,1,NULL,NULL,NULL);
	BN_set_word(qq,0);
	BN_set_bit(qq,128*(2*DD+1));

	BN_free(p);
	BN_free(q);
	BN_free(one);
	BN_free(tmp);
	BN_CTX_free(ctx);
	return 1;
}

4. commit算法

C o m m i t ( p p ; f ( X ) ∈ Z p [ X ] ) Commit(pp;f(X)\in\mathbb{Z}_p[X]) Commit(pp;f(X)Zp[X]):计算 C ← g f ^ ( q ) C\leftarrow g^{\hat{f}(q)} Cgf^(q),返回 ( C ; f ^ ( X ) ) (C;\hat{f}(X)) (C;f^(X))
参见source/commit.c代码。

	Read_pp( &pp ); //读取pp参数
	Read_poly(&poly);//读取多项式系数

	_struct_commit_ cm;
	cm.C = BN_new();
	cm.Fhat = BN_new();

	commit_new(&cm, pp, poly);

// 计算 C ← g f ^ ( q ) C\leftarrow g^{\hat{f}(q)} Cgf^(q)

int commit_new(_struct_commit_* cm, const _struct_pp_ pp, const _struct_poly_ poly)
{
	int flag = 1, i = 0;
	BN_CTX* ctx = BN_CTX_new();
	BIGNUM* bn_tmp1 = BN_new();
	BIGNUM* bn_tmp2 = BN_new();

	BN_set_word(bn_tmp1,1);
	BN_set_word(bn_tmp2,0);
	BN_set_word(cm->Fhat,0);
	BN_set_word(cm->C,1);

	for(i = poly.d; i >= 0; i--)
	{
		BN_mod_exp( cm->C, cm->C, pp.q, pp.G, ctx);
		BN_mod_exp( bn_tmp1, pp.g, poly.Fx[i], pp.G, ctx);
		BN_mod_mul( cm->C, cm->C, bn_tmp1, pp.G, ctx);
	}

	BN_CTX_free(ctx);
	BN_free(bn_tmp1);
	BN_free(bn_tmp2);

	return flag;
}

5. Evaluation protocol

在这里插入图片描述

  • Prover的工作参见source/eval_prover.c;
  • Verifier的工作参见source/eval_verifier.c

5.1 Evaluation protocol 的 Prover 部分

  • 读取多项式系数,将所有系数范围调整至 [ − p − 1 2 , p − 1 2 ] [-\frac{p-1}{2},\frac{p-1}{2}] [2p1,2p1]
	BN_copy(C, cm->C);	
	BN_copy(p, pp->p);	
	BN_sub_word(p,1);
	BN_rshift1(p,p); //此时p=(p-1)/2

// 这段代码在将系数限定在 [ − p − 1 2 , p − 1 2 ] [-\frac{p-1}{2},\frac{p-1}{2}] [2p1,2p1]是有问题的。。。

	BN_set_word(zero,0);
	BN_set_word(y,0);
	BN_set_word(z,100);
	BN_set_word(z_tmp, 1);

	i=0;
	do{
		//BN_mod_inverse(poly->Fx[i], poly->Fx[i], pp->p, ctx);
		i++;
	}while(i<= poly->d);

	i = 0;
	do{
		BN_mod_mul(zero, poly->Fx[i], z_tmp, pp->p, ctx);
		BN_mod_add(y, y, zero, pp->p, ctx);
		BN_mod_mul(z_tmp,z_tmp,z, pp->p, ctx);
		i++;
	}while(i<= poly->d);

  • EvalBounded中Prover的部分:
    – 若多项式degree d d d为0,直接将常量值 f 0 f_0 f0发送给Verifier:
	if(poly->d == 0)
	{		
		Write_proof(NULL, poly->Fx[0]);
	}

– 当 d + 1 d+1 d+1为奇数时:
在这里插入图片描述

	else if( ((1+poly->d)%2) == 1 )
	{
		printf("d+1 is odd  [d : %d -> d' : %d]\n", poly->d, poly->d + 1);
		TimerOn();

		BN_mod_exp(*C,*C,pp->q,pp->G,ctx);	// C' = C^q
		BN_mod_mul(*y,*y,z,pp->p,ctx);		// y=y*z mod p
		BN_set_word(y_tmp, poly->d);
		BN_mul(*b, *b, y_tmp, ctx);			// b =  bd
		
		poly->d = poly->d + 1;				//d = d + 1		
		if( poly->Fx[poly->d] == NULL)
			poly->Fx[poly->d] = BN_new();
	
		for(int i = poly->d-1; i >= 0; i--){// f'(X) = Xf(X);
			BN_copy(poly->Fx[i+1], poly->Fx[i]);
		}
		BN_set_word(poly->Fx[0],0);	
		RunTime_eval += TimerOff();

		EvalBounded(pp, C, z, y, b, poly);
	}

d ≥ 1 d\geq1 d1 d + 1 d+1 d+1为偶数:
在这里插入图片描述


5.2 Evaluation protocol 的 Verifier 部分

  • EvalBounded中Verifier的部分:
    在这里插入图片描述
Spd(spd, pp->p, poly->d);

int Spd(BIGNUM* output, BIGNUM* p, unsigned int d)
{
	BN_CTX* ctx = BN_CTX_new();
	BIGNUM* bn_tmp = BN_new();

	int nbit = 0;
	d++;
	for(nbit=0; d != 0; (d >>= 1), nbit++);
	//printf("%d\n", nbit);
	BN_set_word(bn_tmp, nbit);
	BN_exp(output, p, bn_tmp, ctx);
	//printf("Spd : %s\n", BN_bn2hex(output));
	BN_CTX_free(ctx);
	BN_free(bn_tmp);
	
	return 1;
}

在这里插入图片描述

	if(poly->d == 0)
	{
		TimerOn();
		fscanf(fp, "%s", buffer);
		BN_hex2bn(&poly->Fx[0], buffer);
		RunTime_file_IO += TimerOff();

		TimerOn();
		BN_mul(z_tmp, *b, spd, ctx);
		if(BN_cmp(*b, pp->q) != -1 || BN_cmp(spd, pp->q) != -1){ // 步骤3
			printf("bounded fail!! [ b * spd > q]\n");
			flag = 0;
		}
		
		if(BN_cmp(poly->Fx[0], *b) != -1){ // 步骤4
			printf("bounded fail!! [ |f| > b ]\n");
			printf("f : %s\n", BN_bn2hex(poly->Fx[0]));
			printf("b : %s\n", BN_bn2hex(*b));
			flag = 0;
		}

		BN_mod(z_tmp, *y, pp->p, ctx);
		BN_mod(y_tmp, poly->Fx[0], pp->p, ctx);
		if(BN_cmp(z_tmp, y_tmp) != 0){ // 步骤5
			printf("ERROR : f mod p != y mod p\n");
			printf("f : %s\n", BN_bn2hex(y_tmp));
			printf("y : %s\n", BN_bn2hex(z_tmp));
			flag = 0;
		}

		BN_mod_exp(z_tmp, pp->g, poly->Fx[0],pp->G, ctx);
		if(BN_cmp(z_tmp, *C) != 0){ // 步骤6
			printf("ERROR : g^f != C\n");
			printf("g^f : %s\n", BN_bn2hex(z_tmp));
			printf("  C : %s\n", BN_bn2hex(*C));
			flag = 0;
		}
		RunTime_eval += TimerOff();

		if(	flag == 1 ) // 步骤7
			printf("Verify Success!!\n");
		else
			printf("Verify Fail.....\n");
		
	}

参考资料

[1] Openssl 接口函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值