Skip to content

Commit 606510a

Browse files
committed
correct build instructions, missing files, squashed bugs, faster prime sampling
1 parent 9b43b74 commit 606510a

21 files changed

+1289
-236
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2017 Alan Szepieniec
3+
Copyright (c) 2017-2019 Alan Szepieniec
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ Ansi C library for basic algebra routines for prime finite fields, for instance
1313

1414
# How To
1515
* compile:
16-
* standard unit tests: `gcc -o test_algebra test_algebra.c algebra.c gfp.c csprng.c Keccak-readable-and-compact-c89.c gf*x.c -ansi -Wpedantic`
17-
* big field unit tests: `gcc -o test_algebra test_algebra.c algebra.c bi.c gfbi.c Keccak-readable-and-compact-c89.c csprng.c gf*x.c -DBIG -ansi -Wpedantic`
16+
* standard unit tests: `gcc -o test_algebra test_algebra.c gfp.c csprng.c Keccak-readable-and-compact-c89.c gf*x.c gfpm.c hqs.c -ansi -Wpedantic`
17+
* big field unit tests: `gcc -o test_algebra test_algebra.c gfbi.c bi.c csprng.c Keccak-readable-and-compact-c89.c gf*x.c gfpm.c hqs.c -DBIG -ansi -Wpedantic`
1818
* big number arithmetic: `gcc -o test_bi test_bi.c bi.c csprng.c Keccak-readable-and-compact-c89.c -ansi -Wpedantic`
1919
* prime sampling benchmark: `gcc -o benchmark_primality benchmark_primality.c bi.c csprng.c Keccak-readable-and-compact-c89.c -ansi -Wpedantic -O3`
2020

benchmark_primality.c

+1-6
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,13 @@ int main( int argc, char ** argv )
5353
csprng_generate(&rng, sizeof(unsigned long int) * num_limbs, (unsigned char*)randomness);
5454
bi_random(&p, bitsize, (unsigned char *)randomness);
5555
bi_setbit(&p, 0, 1);
56-
printf("testing candidate number "); bi_print(p); printf(" for primality ...\n");
5756
}
5857
while( bi_is_prime(p, random_ints, certainty) == 0 );
58+
printf("got prime number: "); bi_print(p); printf("\n");
5959
}
6060

6161
printf("done.\n");
6262

63-
if( num_trials == 1 )
64-
{
65-
printf("p = int('"); bi_print_bitstring(p); printf("', 2)\n");
66-
}
67-
6863
bi_destroy(p);
6964
free(randomness);
7065

bi.c

+69-77
Original file line numberDiff line numberDiff line change
@@ -787,11 +787,12 @@ int bi_multiply( bi * res, bi lhs, bi rhs )
787787
bi_increase(&product, curr);
788788
}
789789

790-
res->sign = lhs.sign * rhs.sign;
790+
product.sign = lhs.sign * rhs.sign;
791791

792792
bi_destroy(curr);
793793
bi_destroy(*res);
794794
res->data = product.data;
795+
res->sign = product.sign;
795796
for( res->num_limbs = product.num_limbs ; res->num_limbs > 0 ; --res->num_limbs )
796797
{
797798
if( res->data[res->num_limbs-1] != 0 )
@@ -873,14 +874,13 @@ int bi_divide( bi * quo, bi * rem, bi numerator, bi denominator )
873874
bi_negate(&negative_quotient);
874875
bi_copy(quo, negative_quotient);
875876

876-
bi_negate(&negative_remainder);
877-
bi_add(rem, negative_remainder, denominator);
878-
879877
one = bi_init(0);
880878
bi_one(&one);
881879
temp = bi_init(0);
882880
bi_copy(&temp, *quo);
883881
bi_subtract(quo, temp, one);
882+
bi_multiply(&temp, *quo, denominator);
883+
bi_subtract(rem, numerator, temp);
884884
bi_destroy(temp);
885885
bi_destroy(one);
886886

@@ -1389,23 +1389,9 @@ int bi_xgcd( bi * x, bi * y, bi * g, bi a, bi b )
13891389
{
13901390
bi_divide(&quotient, &remainder, old_r, r);
13911391

1392-
/*
1393-
printf("numerator: "); bi_print_bitstring(old_r); printf("\n");
1394-
printf("divisor: "); bi_print_bitstring(r); printf("\n");
1395-
printf("quotient: "); bi_print_bitstring(quotient); printf("\n");
1396-
printf("remainder: "); bi_print_bitstring(remainder); printf("\n");
1397-
getchar();
1398-
*/
1399-
14001392
/**/
14011393
bi_copy(&old_r, r);
14021394
bi_copy(&r, remainder);
1403-
/*/
1404-
bi_copy(&temp2, old_r);
1405-
bi_copy(&old_r, r);
1406-
bi_multiply(&temp, quotient, r);
1407-
bi_subtract(&r, temp2, temp);
1408-
*/
14091395

14101396
bi_copy(&temp2, old_s);
14111397
bi_copy(&old_s, s);
@@ -1509,16 +1495,19 @@ int bi_naf( bi * respos, bi * resneg, bi source )
15091495
}
15101496

15111497
/**
1512-
* bi_modexp
1513-
* Raise the base to the given power but compute only the residue of
1514-
* that function modulo the modulus. Uses the square-and-multiply
1515-
* routine.
1498+
* bi_modexp_naf
1499+
* Perform modular exponentiation except first transforms the power into NAF.
1500+
* This sparsity transformation leads to fewer multiplications and
1501+
* the tradeoff is positive when the integers are large (sortof
1502+
* bigger than 250 bits).
15161503
*/
1517-
int bi_modexp( bi * res, bi base, bi power, bi modulus )
1504+
int bi_modexp_naf( bi * res, bi base, bi power, bi modulus )
15181505
{
15191506
int bitsize;
1507+
int negones_bitsize;
15201508
int i;
15211509
bi temp, temp2;
1510+
bi posones, negones;
15221511
bi inverse;
15231512

15241513
if( base.sign == -1 )
@@ -1545,46 +1534,63 @@ int bi_modexp( bi * res, bi base, bi power, bi modulus )
15451534
return 1;
15461535
}
15471536

1548-
if( bi_bitsize(power) > 20 && bi_bitsize(modulus) > 250 )
1549-
{
1550-
return bi_modexp_naf(res, base, power, modulus);
1551-
}
1552-
15531537
temp = bi_init(0);
1538+
posones = bi_init(power.num_limbs * sizeof(unsigned long int) * 8);
1539+
negones = bi_init(power.num_limbs * sizeof(unsigned long int) * 8);
1540+
bi_naf(&posones, &negones, power);
1541+
negones_bitsize = bi_bitsize(negones);
15541542

1543+
inverse = bi_init(0);
1544+
bi_modinverse(&inverse, base, modulus);
15551545
bi_one(res);
15561546

15571547
bitsize = bi_bitsize(power);
1558-
for( i = bitsize ; i >= 0 ; --i )
1548+
for( i = bitsize ; i >= negones_bitsize ; --i )
15591549
{
15601550
bi_multiply(&temp, *res, *res);
15611551

1562-
if( bi_getbit(power, i) == 1 )
1552+
if( bi_getbit(posones, i) == 1 )
1553+
{
1554+
bi_multiply(&temp, temp, base);
1555+
}
1556+
1557+
bi_modulo(res, temp, modulus);
1558+
}
1559+
for( ; i >= 0 ; --i )
1560+
{
1561+
bi_multiply(&temp, *res, *res);
1562+
1563+
if( bi_getbit(posones, i) == 1 )
15631564
{
1564-
bi_multiply(&temp, *res, base);
1565+
bi_multiply(&temp, temp, base);
15651566
}
15661567

1568+
if( bi_getbit(negones, i) == 1 )
1569+
{
1570+
bi_multiply(&temp, temp, inverse);
1571+
}
15671572
bi_modulo(res, temp, modulus);
15681573
}
15691574

15701575
bi_destroy(temp);
1576+
bi_destroy(inverse);
1577+
bi_destroy(posones);
1578+
bi_destroy(negones);
15711579

15721580
return 1;
15731581
}
1582+
15741583
/**
1575-
* bi_modexp_naf
1576-
* Does the same thing except first transforms the power into NAF.
1577-
* This sparsity transformation leads to fewer multiplications and
1578-
* the tradeoff is positive when the integers are large (sortof
1579-
* bigger than 250 bits).
1584+
* bi_modexp
1585+
* Raise the base to the given power but compute only the residue of
1586+
* that function modulo the modulus. Uses the square-and-multiply
1587+
* routine.
15801588
*/
1581-
int bi_modexp_naf( bi * res, bi base, bi power, bi modulus )
1589+
int bi_modexp( bi * res, bi base, bi power, bi modulus )
15821590
{
15831591
int bitsize;
1584-
int negones_bitsize;
15851592
int i;
15861593
bi temp, temp2;
1587-
bi posones, negones;
15881594
bi inverse;
15891595

15901596
if( base.sign == -1 )
@@ -1611,48 +1617,30 @@ int bi_modexp_naf( bi * res, bi base, bi power, bi modulus )
16111617
return 1;
16121618
}
16131619

1620+
if( bi_bitsize(power) > 20 && bi_bitsize(modulus) > 250 )
1621+
{
1622+
return bi_modexp_naf(res, base, power, modulus);
1623+
}
1624+
16141625
temp = bi_init(0);
1615-
posones = bi_init(power.num_limbs * sizeof(unsigned long int) * 8);
1616-
negones = bi_init(power.num_limbs * sizeof(unsigned long int) * 8);
1617-
bi_naf(&posones, &negones, power);
1618-
negones_bitsize = bi_bitsize(negones);
16191626

1620-
inverse = bi_init(0);
1621-
bi_modinverse(&inverse, base, modulus);
16221627
bi_one(res);
16231628

16241629
bitsize = bi_bitsize(power);
1625-
for( i = bitsize ; i >= negones_bitsize ; --i )
1630+
for( i = bitsize-1 ; i >= 0 ; --i )
16261631
{
16271632
bi_multiply(&temp, *res, *res);
1633+
bi_modulo(&temp, temp, modulus);
16281634

1629-
if( bi_getbit(posones, i) == 1 )
1630-
{
1631-
bi_multiply(&temp, temp, base);
1632-
}
1633-
1634-
bi_modulo(res, temp, modulus);
1635-
}
1636-
for( ; i >= 0 ; --i )
1637-
{
1638-
bi_multiply(&temp, *res, *res);
1639-
1640-
if( bi_getbit(posones, i) == 1 )
1635+
if( bi_getbit(power, i) == 1 )
16411636
{
16421637
bi_multiply(&temp, temp, base);
16431638
}
16441639

1645-
if( bi_getbit(negones, i) == 1 )
1646-
{
1647-
bi_multiply(&temp, temp, inverse);
1648-
}
16491640
bi_modulo(res, temp, modulus);
16501641
}
16511642

16521643
bi_destroy(temp);
1653-
bi_destroy(inverse);
1654-
bi_destroy(posones);
1655-
bi_destroy(negones);
16561644

16571645
return 1;
16581646
}
@@ -1689,8 +1677,8 @@ int bi_modinverse( bi * res, bi element, bi modulus )
16891677
* Perform a single Miller-Rabin trial of the integer with base as
16901678
* test.
16911679
* @returns
1692-
* * 0 if the integer is definitely composite, 1 if it might be a
1693-
* prime
1680+
* * 0 -- definitely composite; or
1681+
* * 1 -- possibly prime
16941682
*/
16951683
int bi_miller_rabin_trial( bi integer, bi base )
16961684
{
@@ -1745,6 +1733,7 @@ int bi_miller_rabin_trial( bi integer, bi base )
17451733
{
17461734
bi_copy(&temp, x);
17471735
bi_modexp(&x, temp, two, integer);
1736+
17481737
if( bi_is_one(x) )
17491738
{
17501739
bi_destroy(x);
@@ -1753,8 +1742,9 @@ int bi_miller_rabin_trial( bi integer, bi base )
17531742
bi_destroy(one);
17541743
bi_destroy(two);
17551744
bi_destroy(temp);
1756-
return 0;
1745+
return 1;
17571746
}
1747+
17581748
if( bi_compare(x, nm1) == 0 )
17591749
{
17601750
bi_destroy(x);
@@ -1795,7 +1785,7 @@ int bi_miller_rabin_trial( bi integer, bi base )
17951785
*/
17961786
int bi_is_prime( bi integer, unsigned long int * random_ints, int certainty )
17971787
{
1798-
bi base, mod6;
1788+
bi base, mod24;
17991789
int i;
18001790
int composite;
18011791

@@ -1818,17 +1808,20 @@ int bi_is_prime( bi integer, unsigned long int * random_ints, int certainty )
18181808
}
18191809
}
18201810

1821-
/* make sure the integer is 1 or -1 modulo 6 */
1822-
base = bi_cast(6);
1823-
mod6 = bi_init(3);
1824-
bi_modulo(&mod6, integer, base);
1811+
/* make sure the integer raised to 4 is 1 modulo 24 */
1812+
base = bi_cast(24);
1813+
mod24 = bi_init(5);
1814+
bi_modulo(&mod24, integer, base);
1815+
bi_multiply(&mod24, mod24, mod24);
1816+
bi_multiply(&mod24, mod24, mod24);
1817+
bi_modulo(&mod24, mod24, base);
18251818
bi_destroy(base);
1826-
if( mod6.data[0] != 1 && mod6.data[0] != 5 )
1819+
if( mod24.data[0] != 1 )
18271820
{
1828-
bi_destroy(mod6);
1821+
bi_destroy(mod24);
18291822
return 0;
18301823
}
1831-
bi_destroy(mod6);
1824+
bi_destroy(mod24);
18321825

18331826
/* run Miller-Rabin trials */
18341827
composite = 1;
@@ -1865,7 +1858,6 @@ int bi_getbit( bi integer, int bit_index )
18651858
/**
18661859
* bi_print
18671860
* Send the decimal representation of this integer to stdout.
1868-
* TODO: debug
18691861
*/
18701862
int bi_print( bi integer )
18711863
{

gf16777216x.c

-2
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,6 @@ unsigned int gf16777216x_eval( gf16777216x polynomial, unsigned int point )
640640
xi = gf16777216_multiply(xi, point);
641641
}
642642

643-
// printf("evaluating polynomial "); gf16777216x_print(polynomial); printf(" int point %02x; result: %02x\n", point, acc);
644-
645643
return acc;
646644
}
647645

gf256x.c

-2
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,6 @@ unsigned char gf256x_eval( gf256x polynomial, unsigned char point )
517517
xi = gf256_multiply(xi, point);
518518
}
519519

520-
// printf("evaluating polynomial "); gf256x_print(polynomial); printf(" int point %02x; result: %02x\n", point, acc);
521-
522520
return acc;
523521
}
524522

gf256x.h

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ int gf256x_multiply_constant_shift( gf256x* dest, gf256x poly, unsigned char con
2525
int gf256x_divide( gf256x* quo, gf256x* rem, gf256x num, gf256x den );
2626
int gf256x_xgcd( gf256x* a, gf256x* b, gf256x* g, gf256x x, gf256x y );
2727

28+
int gf256x_equals( gf256x lhs, gf256x rhs );
29+
int gf256x_is_zero( gf256x op );
30+
2831
int gf256x_print( gf256x p );
2932

3033
#endif

0 commit comments

Comments
 (0)