/* Blinds the c, by computing c *= r^e (mod n), for a random r. Also returns the inverse (ri), for use by rsa_unblind. */ void _rsa_blind (const struct rsa_public_key *pub, void *random_ctx, nettle_random_func *random, mpz_t c, mpz_t ri) { mpz_t r; mpz_init(r); /* c = c*(r^e) * ri = r^(-1) */ do { nettle_mpz_random(r, random_ctx, random, pub->n); /* invert r */ } while (!mpz_invert (ri, r, pub->n)); /* c = c*(r^e) mod n */ mpz_powm_sec(r, r, pub->e, pub->n); mpz_mul(c, c, r); mpz_fdiv_r(c, c, pub->n); mpz_clear(r); }
void bg_decrypt_block(bg_prikey key, FILE *in, FILE *out, mp_size_t len) { mpz_t y, xqmp, xpmq, pp, qq, negone; unsigned long int l; bbs_state *bbs; mpz_init(y); mpz_init(xqmp); mpz_init(xpmq); mpz_init(pp); mpz_init(qq); mpz_init_set_si(negone, -1); bbs = init_bbs(negone, key.n); bbs_gen(bbs, NULL, 8*len, 0); bbs_iter(bbs); bbs_close(bbs); l = bbs->len; mpz_inp_raw(y, in); mpz_add_ui(pp, key.p, 1); mpz_tdiv_q_ui(pp, pp, 4); mpz_pow_ui(pp, pp, l); mpz_powm_sec(pp, y, pp, key.p); mpz_add_ui(qq, key.q, 1); mpz_tdiv_q_ui(qq, qq, 4); mpz_pow_ui(qq, qq, l); mpz_powm_sec(qq, y, qq, key.q); mpz_mul(xqmp, key.q, pp); mpz_powm(pp, key.q, negone, key.p); mpz_mul(xqmp, xqmp, pp); mpz_mul(xpmq, key.p, qq); mpz_powm(qq, key.p, negone, key.q); mpz_mul(xpmq, xpmq, qq); mpz_add(y, xqmp, xpmq); mpz_mod(y, y, key.n); bbs = init_bbs(y, key.n); while(len && !feof(in)) len -= bg_xor(bbs, in, out, len); bbs_close(bbs); }
/** * \fn void dechiffrement(const char* nom_fichier, mpz_t d, mpz_t n, unsigned int blocs) * \brief déchiffrement d'un fichier binaire avec la clé privée * \param nom_fichier le nom du fichier à déchiffrer * \param d premier nombre de la clé * \param n second nombre de la clé * \param blocs taille des blocs * */ void dechiffrement(const char* nom_fichier, mpz_t d, mpz_t n, unsigned int blocs) { FILE *fchiffre, *fclair; unsigned char *buffer, *buffer2; char nom_fichier_dechiffrer[100]; mpz_t temp,temp2; int taille; clock_t s1,s2; mpz_init(temp); mpz_init(temp2); strcpy(nom_fichier_dechiffrer,nom_fichier); strcat(nom_fichier_dechiffrer,".decrypt"); fchiffre = fopen(nom_fichier,"rb"); // ouverture fichier chiffré if (fchiffre != NULL) { s1 = clock(); fclair = fopen(nom_fichier_dechiffrer,"wb+"); buffer = (unsigned char*)calloc((blocs+1), sizeof(unsigned char)); buffer2 = (unsigned char*)calloc((blocs), sizeof(unsigned char)); fread(&taille,sizeof(int),1,fchiffre); //lecture de la taille du fichier while(fread(buffer,sizeof(unsigned char), blocs+1, fchiffre) > 0) { conversion10(temp,buffer,blocs+1); // conversion base 10 mpz_powm_sec(temp2,temp,d,n); // déchiffrement conversion256(buffer2,temp2,blocs); // convertion base 256 if (taille < blocs && taille > 0) decalage(buffer2, &blocs); // suppression des caractères inutiles fwrite(buffer2,sizeof(unsigned char),blocs,fclair); // écriture dans le fichier clair taille-=blocs; mpz_init(temp); } free(buffer); free(buffer2); fclose(fclair); fclose(fchiffre); s2 = clock(); printf ("=> Déchiffrement effectué avec succés (%.2fs) dans %s\n", (float)(s2-s1)/CLOCKS_PER_SEC,nom_fichier_dechiffrer); } else printf("Fichier %s introuvable !\n", nom_fichier); mpz_clear(temp); mpz_clear(temp2); }
int main(int argc, char **argv){ mpz_t prime; mpz_init(prime); mpz_set_str(prime, "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff", 16); mpz_t base; mpz_init(base); mpz_set_ui(base, 2); mpz_t exp; mpz_init(exp); mpz_set_str(exp, "16ffd3bddcd2076e9130eed97d6eb59dc4463f3d751ba7e953399e4ea9ada84a3714619b038d63761bcfa786cb0c1124ecdccdb4fd417f25b1458f5acd2d9088c1b5e4661139c8382e3b52841d3dd3f81855f0dbb0705a05304705a69709922e26c80042513c7cbfdbf6c3dbdb11c6f8d45a5d30dd5320a40d935d2cadb3ff2202719ce9fc197dacfee65f2ed5cb7147ee49a2aad18404cf16c9584ba56eef71ba085ad9cd9c61ff0f8dafa43f54e07b2c346389eebdc359afafd3e27d4d6a48", 16); mpz_t ans; mpz_init(ans); mpz_powm_sec(ans, base, exp, prime); gmp_printf("modexp(%#Zx, %#Zx, %#Zx) == %#Zx\n", base, exp, prime, ans); return 0; }
int dh(unsigned char * k, int knum,unsigned char * n, int nnum, int s){ if(VISIBLE){ printf("\n\n****** Diffie-Hellman begin ******\n\n"); } int i,j=0,itemp; mpz_t p,g,a,A,B,S; char buf[BUF_SIZE],*string_A,*string_p, *string_g, *tempkey; unsigned long int rand; size_t count; unsigned int temp; FILE *fp; mpz_init(a); mpz_init(A); mpz_init(B); mpz_init(S); // Setts g and p according to RFC 3526 1536 bits. http://tools.ietf.org/html/rfc3526 mpz_init_set_str(g,"2",10); mpz_init_set_str(p,"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 \ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD \ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 \ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D \ C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F \ 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D \ 670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF", 16); if(VISIBLE){ printf("\np:\n"); mpz_out_str(NULL,10,p); printf("\n\ng:\n"); mpz_out_str(NULL,10,g); printf("\n"); } //Randomizar a ( Bättre seed nu ) gmp_randstate_t state; gmp_randinit_mt(state); // Initializerar state random måstes för att urandomm ska funka fp = fopen("/dev/urandom", "r"); fread(&rand, 8, 1, fp); fclose(fp); gmp_randseed_ui(state,rand); mpz_urandomm(a,state,p); // Ger a random värde mellan 0 <= a <= p-1 if(VISIBLE){ printf("\na:\n"); mpz_out_str(NULL,10,a); printf("\n"); } // ^Frågan är om urandom skall användas för att generara hela A?????? mpz_powm_sec(A,g,a,p); // g^a mod p = A if(VISIBLE){ printf("\nA:\n"); mpz_out_str(NULL,10,A); printf("\n"); } string_p = (char *)mpz_export (NULL,&count,1,1,0,0, p); // Antal bytes i word är 1 // Sätter första meddelandet till standard: (bokstav(1 byte(char)),storlek(4 byte(unsigned int)),content und so weiter...) i=0; buf[i++] = 'p'; memcpy(&buf[i],(char *)&count,sizeof(unsigned int)); //Detta för att hålla någon slags struktur i = i+sizeof(unsigned int); itemp = i; for(;i<count+itemp;i++){ buf[i]=string_p[i-itemp]; } string_g = (char *)mpz_export(NULL,&count,1,1,0,0,g); buf[i++] = 'g'; memcpy(&buf[i],(char *)&count,sizeof(unsigned int)); i = i+sizeof(unsigned int); itemp = i; for(;i<count+itemp;i++){ buf[i]=string_g[i-itemp]; } string_A = (char *)mpz_export(NULL,&count,1,1,0,0,A); buf[i++] = 'A'; memcpy(&buf[i],(char *)&count,sizeof(unsigned int)); i = i+sizeof(unsigned int); itemp = i; for(;i<count+itemp;i++){ buf[i]=string_A[i-itemp]; } if(write(s,buf,sizeof(buf))==-1){ return 0; //Diffie-hellman fail } read(s,buf,BUF_SIZE); //Read answer from server _!check!_ if(buf[j]=='B'){ j++; memcpy(&temp,(unsigned int *)&buf[j],sizeof(unsigned int)); j+=4; mpz_import(B,temp,1,1,0,0,&buf[j]); mpz_powm_sec(S,B,a,p); // B^a mod p = S } if(VISIBLE){ printf("\nS:\n"); mpz_out_str(NULL,10,S); printf("\n"); } tempkey = (char *)mpz_export(NULL,&count,1,1,0,0,S); //Fyllar sedan nyckeln med detta för det är mer random // Fyller riktig nyckel och nonce for(i=0;i<knum;i++){ k[i] = tempkey[i]; } itemp = i; for(;i<nnum+itemp;i++){ n[i-itemp] = tempkey[i]; } if(VISIBLE){ printf("\n\n****** Diffie-Hellman end ******\n\n"); } return 1; }
void dhe_compute_shared_secret(mpz_t shared_secret, mpz_t secret_key, mpz_t other_party_secret, mpz_t prime) { mpz_powm_sec(shared_secret, other_party_secret, secret_key, prime); }
void dhe_compute_party_secret(mpz_t party_secret, mpz_t secret_key, mpz_t generator, mpz_t prime) { mpz_powm_sec(party_secret, generator, secret_key, prime); }
int main() { unsigned int i,j,a,*SV; unsigned char logpi; int k,S,r,s1,s2,s,NS,logm,ptr,threshold,epri; long M,la,lptr; qsieve=gmpinit(-36,0); if(initv()<0) return 0; hmod=2*mlf+1; mpz_set_si(TA, hmod); while(!mpz_probab_prime_p(TA, qsieve->NTRY)) mpz_sub_ui(TA, TA, 2); //TT=不大于TT的素数 hmod=qsieve_getsize(TA); hmod2=hmod-2; for(k=0;k<hmod;k++) hash[k]=(-1); M=50*(long)mm; NS=(int)(M/SSIZE); if(M%SSIZE!=0) NS++; M=SSIZE*(long)NS; // M为不小于50*mm的SSIZE的倍数中最小的 from 以上四行 logm=0; la=M; while((la/=2)>0) logm++; // 以2为底 rp[0]=logp[0]=0; for(k=1;k<=mm;k++) //求k*N在每个素数下的二次剩余解,与每个素数的ln(pi) { r=mpz_tdiv_q_ui(TA, D, epr[k]); rp[k]=qsieve_sqrmp(r,epr[k]); logp[k]=0; r=epr[k]; while((r/=2)>0) logp[k]++; } r=mpz_tdiv_q_ui(TA, D, 8); if(r==5) logp[1]++; if(r==1) logp[1]+=2; threshold=logm+mpz_sizeinbase(R, 2)-2*logp[mm]; jj=0; nlp=0; mpz_mul_si(DG, D, 2); mpz_root(DG, DG, 2); mpz_set_si(TA, M); qsieve_divide(DG,TA,DG); mpz_root(DG, DG, 2); if(mpz_tdiv_q_ui(TA, DG, 2)==0) mpz_add_ui(DG, DG, 1); if(mpz_tdiv_q_ui(TA, DG, 4)==1) mpz_add_ui(DG, DG, 2); // 令DG等于大于等于DG的数中模4余3的最小的数 printf(" 0%"); while(1) //不断尝试新的多项式,可以并行计算 { r=qsieve->NTRY; qsieve->NTRY=1; do { do { mpz_add_ui(DG, DG, 4); } while(!(mpz_probab_prime_p(DG, qsieve->NTRY) ? TRUE : FALSE)); mpz_sub_ui(TA, DG, 1); mpz_tdiv_q_ui(TA, TA, 2); mpz_powm_sec(TA, D, TA, DG); } while(qsieve_getsize(TA)!=1); //直到DD是二次剩余 qsieve->NTRY=r; mpz_add_ui(TA, DG, 1); mpz_tdiv_q_ui(TA, TA, 4); mpz_powm_sec(B, D, TA, DG); mpz_neg(TA, D); qsieve_muladddiv(B,B,TA,DG,TA,TA); mpz_neg(TA, TA); mpz_mul_si(A, B, 2); qsieve_extgcd(A,DG,A,A,A); qsieve_muladddiv(A,TA,TA,DG,DG,A); mpz_mul(TA, A, DG); mpz_add(B, B, TA); mpz_mul(A, DG, DG); qsieve_extgcd(DG,D,IG,IG,IG); r1[0]=r2[0]=0; for(k=1;k<=mm;k++) //s1和s2是两个解 { s=mpz_tdiv_q_ui(TA, B, epr[k]); r=mpz_tdiv_q_ui(TA, A, epr[k]); r=qsieve_getinvers(r,epr[k]); s1=(epr[k]-s+rp[k]); s2=(epr[k]-s+epr[k]-rp[k]); if(s1 > s2) { int t = s1; s1 = s2; s2 = t; } r1[k]=(int)((((long long)s1)*((long long)r)) % ((long long)epr[k])); r2[k]=(int)((((long long)s2)*((long long)r)) % ((long long)epr[k])); } for(ptr=(-NS);ptr<NS;ptr++) { la=(long)ptr*SSIZE; SV=(unsigned int *)sieve; for(i=0; i<SSIZE/sizeof(int); i++) *SV++=0; for(k=1; k<=mm; k++) { epri=epr[k]; logpi=logp[k]; r=(int)(la%epri); s1=(r1[k]-r)%epri; if(s1<0) s1+=epri; s2=(r2[k]-r)%epri; if(s2<0) s2+=epri; /* 这部分是筛法的主要部分,数组下标表示多项式P(x)的参数x s1与s2是两个P(x)=0(mod p)的解 */ for(j=s1;j<SSIZE;j+=epri) sieve[j]+=logpi; if(s1==s2) continue; for(j=s2;j<SSIZE;j+=epri) sieve[j]+=logpi; } for(a=0;a<SSIZE;a++) //找那些没有被筛掉的数 { if(sieve[a]<threshold) continue; lptr=la+a; mpz_set_si(TA, lptr); S=0; mpz_mul(TA, A, TA); mpz_add(TA, TA, B); qsieve_muladddiv(TA,IG,TA,D,D,P); if(qsieve_getsize(P)<0) mpz_add(P, P, D); qsieve_muladddiv(P,P,P,D,D,V); mpz_abs(TA, TA); if(qsieve_compare(TA,R)<0) S=1; if(S==1) mpz_sub(V, D, V); if(V!=TA) mpz_set(TA, V); e[0]=S; for(k=1;k<=mm;k++) e[k]=0; if(!factored(lptr,TA)) continue; if(gotcha()) { mpz_gcd(P, TA, N); qsieve_getsize(P); printf("\b\b\b\b100%\nFactors are\n"); qsieve_outnum(P,stdout); qsieve_divide(N,P,N); qsieve_outnum(N,stdout); return 0; } } } } return 0; }
char gotcha(void) // 进gotcha前提一定是factored返回true了 { int r,j,i,k,n,rb,had,hp; unsigned int t; char found; found=TRUE; if(partial) // 检查部分分解 { had=lp%hmod; while(1) // 哈希大素数 { hp=hash[had]; if(hp<0) { found=FALSE; break; } if(pr[hp]==lp) break; had=(had+(hmod2-lp%hmod2))%hmod; } if(!found && nlp>=mlf) return FALSE; } if(P!=X) mpz_set(X, P); mpz_set_si(Y, 1); for(k=1;k<=mm;k++) // 把Y乘出来 { if(e[k]<2) continue; r=e[k]/2; // 开个根 e[k]%=2; // 弄成0和1用来解异或方程组 mpz_ui_pow_ui(TA, epr[k], r); mpz_mul(Y, TA, Y); //Y=Y*epr[k]^r } if(partial) { if(!found) { hash[had]=nlp; pr[nlp]=lp; if(X!=z[nlp]) mpz_set(z[nlp], X); if(Y!=w[nlp]) mpz_set(w[nlp], Y); for(n=0,rb=0,j=0;j<=mm;j++) { G[nlp][n]|=((e[j]&1)<<rb); //压位 if(++rb==nbts) n++,rb=0; // 压32位 } nlp++; } if(found) { qsieve_muladddiv(X,z[hp],X,N,N,X); qsieve_muladddiv(Y,w[hp],Y,N,N,Y); for(n=0,rb=0,j=0;j<=mm;j++) { t=(G[hp][n]>>rb); e[j]+=(t&1); if(e[j]==2) { mpz_mul_si(Y, Y, epr[j]); qsieve_divide(Y,N,N); // Y%=N e[j]=0; } if(++rb==nbts) n++,rb=0; } mpz_mul_si(Y, Y, lp); qsieve_divide(Y,N,N);// Y%=N } } if(found) { for(k=mm;k>=0;k--) { if(e[k]%2==0) continue; if(b[k]<0) { found=FALSE; break; } i=b[k]; qsieve_muladddiv(X,x[i],X,N,N,X); qsieve_muladddiv(Y,y[i],Y,N,N,Y); for(n=0,rb=0,j=0;j<=mm;j++) //高斯消元 { t=(EE[i][n]>>rb); e[j]+=(t&1); if(++rb==nbts) n++,rb=0; } } for(j=0;j<=mm;j++) // 更新Y { if(e[j]<2) continue; mpz_set_si(TA, epr[j]); mpz_set_si(TB, e[j]/2); mpz_powm_sec(TA, TA, TB, N); qsieve_muladddiv(Y,TA,Y,N,N,Y); } if(!found) //把结果扔进EE,X,Y继续用 { b[k]=jj; if(X!=x[jj]) mpz_set(x[jj], X); if(Y!=y[jj]) mpz_set(y[jj], Y); for(n=0,rb=0,j=0;j<=mm;j++) { EE[jj][n]|=((e[j]&1)<<rb); if(++rb==nbts) n++,rb=0; } jj++; printf("\b\b\b\b%3d%%",100*jj/mm); fflush(stdout); } } if(found) { mpz_add(TA, X, Y); if(qsieve_compare(X,Y)==0 || qsieve_compare(TA,N)==0) found=FALSE; if(!found) { printf("\b\b\b\b%3d%%",100*jj/mm); fflush(stdout); } } return found; }