赞
踩
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
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.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; }
S
e
t
u
p
(
1
λ
)
Setup(1^{\lambda})
Setup(1λ):随机
G
←
G
G
e
n
(
λ
)
\mathbb{G}\leftarrow GGen(\lambda)
G←GGen(λ)和
g
←
G
g\leftarrow \mathbb{G}
g←G。返回
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=2D−1,默认
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; }
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)}
C←gf^(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)} C←gf^(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; }
source/eval_prover.c
;source/eval_verifier.c
。 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}] [−2p−1,2p−1]是有问题的。。。
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);
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
d≥1且
d
+
1
d+1
d+1为偶数:
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 接口函数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。