int main() { bi_initialize(); int k = 2; bigint f1 = int_to_bi(1), f2 = int_to_bi(1), f3, tmp; bigint zeros = int_to_bi(1000000000); while (1) { k++; f3 = bi_add(f1, bi_copy(f2)); int mod = bi_int_mod(bi_copy(f3), 1000000000); if (mod >= 100000000) { if (is_pandigital(mod)) { tmp = bi_copy(f3); while (bi_compare(bi_copy(tmp), bi_copy(zeros)) > 0) { tmp = bi_int_divide(tmp, 10); } if (is_pandigital(bi_to_int(tmp))) { break; } } } f1 = f2; f2 = f3; } bi_free(f2); bi_free(f3); bi_free(zeros); printf("%d\n", k); bi_terminate(); return 0; }
/** * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts. * * @param ctx [in] The bigint session context. * @param bi [in] The bigint to perform the exp/mod. * @param dP [in] CRT's dP bigint * @param dQ [in] CRT's dQ bigint * @param p [in] CRT's p bigint * @param q [in] CRT's q bigint * @param qInv [in] CRT's qInv bigint * @return The result of the CRT operation */ bigint * ICACHE_FLASH_ATTR bi_crt(BI_CTX *ctx, bigint *bi, bigint *dP, bigint *dQ, bigint *p, bigint *q, bigint *qInv) { bigint *m1, *m2, *h; /* Montgomery has a condition the 0 < x, y < m and these products violate * that condition. So disable Montgomery when using CRT */ #if defined(CONFIG_BIGINT_MONTGOMERY) ctx->use_classical = 1; #endif ctx->mod_offset = BIGINT_P_OFFSET; m1 = bi_mod_power(ctx, bi_copy(bi), dP); ctx->mod_offset = BIGINT_Q_OFFSET; m2 = bi_mod_power(ctx, bi, dQ); h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL); h = bi_multiply(ctx, h, qInv); ctx->mod_offset = BIGINT_P_OFFSET; h = bi_residue(ctx, h); #if defined(CONFIG_BIGINT_MONTGOMERY) ctx->use_classical = 0; /* reset for any further operation */ #endif return bi_add(ctx, m2, bi_multiply(ctx, q, h)); }
/** * Use the Chinese Remainder Theorem to quickly perform RSA decrypts. * This should really be in bigint.c (and was at one stage), but needs * access to the RSA_CTX context... */ static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi) { BI_CTX *ctx = rsa->bi_ctx; bigint *m1, *m2, *h; /* Montgomery has a condition the 0 < x, y < m and these products violate * that condition. So disable Montgomery when using CRT */ #if defined(CONFIG_BIGINT_MONTGOMERY) ctx->use_classical = 1; #endif ctx->mod_offset = BIGINT_P_OFFSET; m1 = bi_mod_power(ctx, bi_copy(bi), rsa->dP); ctx->mod_offset = BIGINT_Q_OFFSET; m2 = bi_mod_power(ctx, bi, rsa->dQ); h = bi_subtract(ctx, bi_add(ctx, m1, rsa->p), bi_copy(m2), NULL); h = bi_multiply(ctx, h, rsa->qInv); ctx->mod_offset = BIGINT_P_OFFSET; h = bi_residue(ctx, h); #if defined(CONFIG_BIGINT_MONTGOMERY) ctx->use_classical = 0; /* reset for any further operation */ #endif return bi_add(ctx, m2, bi_multiply(ctx, rsa->q, h)); }
/************************************************************************** * RSA tests * * Use the results from openssl to verify PKCS1 etc **************************************************************************/ static int RSA_test(void) { int res = 1; const char *plaintext = /* 128 byte hex number */ "1234567890abbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee2" "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeee2\012"; uint8_t enc_data[128], dec_data[128]; RSA_CTX *rsa_ctx = NULL; BI_CTX *bi_ctx; bigint *plaintext_bi; bigint *enc_data_bi, *dec_data_bi; uint8_t enc_data2[128], dec_data2[128]; int len; uint8_t *buf; /* extract the private key elements */ len = get_file("./axTLS.key_1024", &buf); if (asn1_get_private_key(buf, len, &rsa_ctx) < 0) { goto end; } free(buf); dump_frame("original data",(char *)plaintext, strlen(plaintext)); bi_ctx = rsa_ctx->bi_ctx; plaintext_bi = bi_import(bi_ctx, (const uint8_t *)plaintext, strlen(plaintext)); /* basic rsa encrypt */ enc_data_bi = RSA_public(rsa_ctx, plaintext_bi); bi_export(bi_ctx, bi_copy(enc_data_bi), enc_data, sizeof(enc_data)); dump_frame("encrypt data",(char *)enc_data, sizeof(enc_data)); /* basic rsa decrypt */ dec_data_bi = RSA_private(rsa_ctx, enc_data_bi); bi_export(bi_ctx, dec_data_bi, dec_data, sizeof(dec_data)); dump_frame("decrypt data",(char *)dec_data, sizeof(dec_data)); if (memcmp(dec_data, plaintext, strlen(plaintext))) { printf("Error: DECRYPT #1 failed\n"); goto end; } RSA_encrypt(rsa_ctx, (const uint8_t *)"abc", 3, enc_data2, 0); RSA_decrypt(rsa_ctx, enc_data2, dec_data2, 1); if (memcmp("abc", dec_data2, 3)) { printf("Error: ENCRYPT/DECRYPT #2 failed\n"); goto end; } RSA_free(rsa_ctx); res = 0; printf("All RSA tests passed\n"); end: return res; }
/* * Karatsuba improves on regular multiplication due to only 3 multiplications * being done instead of 4. The additional additions/subtractions are O(N) * rather than O(N^2) and so for big numbers it saves on a few operations */ static bigint * ICACHE_FLASH_ATTR karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square) { bigint *x0, *x1; bigint *p0, *p1, *p2; int m; if (is_square) { m = (bia->size + 1)/2; } else { m = (max(bia->size, bib->size) + 1)/2; } x0 = bi_clone(ctx, bia); x0->size = m; x1 = bi_clone(ctx, bia); comp_right_shift(x1, m); bi_free(ctx, bia); /* work out the 3 partial products */ if (is_square) { p0 = bi_square(ctx, bi_copy(x0)); p2 = bi_square(ctx, bi_copy(x1)); p1 = bi_square(ctx, bi_add(ctx, x0, x1)); } else /* normal multiply */ { bigint *y0, *y1; y0 = bi_clone(ctx, bib); y0->size = m; y1 = bi_clone(ctx, bib); comp_right_shift(y1, m); bi_free(ctx, bib); p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0)); p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1)); p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1)); } p1 = bi_subtract(ctx, bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL); comp_left_shift(p1, m); comp_left_shift(p2, 2*m); return bi_add(ctx, p1, bi_add(ctx, p0, p2)); }
int main() { bi_initialize(); int a, b, n; int max_number, prod; for (a = -999; a < 1000; ++a) { for (b = -999; b < 1000; ++b) { n = 0; for (;;) { bigint a_ = int_to_bi(a); bigint b_ = int_to_bi(b); bigint n_ = int_to_bi(n); bigint n2 = bi_multiply( bi_copy( n_ ), bi_copy( n_ ) ); bigint an = bi_multiply(bi_copy(a_),bi_copy(n_)); bigint num = bi_add(bi_copy(n2), bi_copy(an)); bigint num2 = bi_add(bi_copy(num), bi_copy(b_)); int should_break = 0; if (bi_is_probable_prime(bi_copy(num2), 99)) { ++n; } else { if (n > max_number) { max_number = n; prod = a * b; } should_break = 1; } bi_free(num); bi_free(num2); bi_free(a_); bi_free(b_); bi_free(n_); bi_free(n2); bi_free(an); if (should_break) break; } } } printf("%d\n", prod); bi_terminate(); return 0; }
int main() { bi_initialize(); bigint sum = int_to_bi(1); bigint last = int_to_bi(1); int i, j; for (i = 1; i <= (SIZE-1)/2; ++i) { for (j = 0; j < 4; ++j) { last = bi_add(last, bi_int_multiply(int_to_bi(i), 2)); sum = bi_add(sum, bi_copy(last)); } } bi_print(stdout, sum); printf("\n"); bi_free(last); bi_terminate(); return 0; }
/* * Work out g1, g3, g5, g7... etc for the sliding-window algorithm */ static void ICACHE_FLASH_ATTR precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) { int k = 1, i; bigint *g2; for (i = 0; i < window - 1; i++) { /* compute 2^(window-1) */ k <<= 1; } ctx->g = (bigint **)os_malloc(k * sizeof(bigint *)); ctx->g[0] = bi_clone(ctx, g1); bi_permanent(ctx->g[0]); g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */ for (i = 1; i < k; i++) { ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i - 1], bi_copy(g2))); bi_permanent(ctx->g[i]); } bi_free(ctx, g2); ctx->window = k; }
int main() { bi_initialize(); bigint last = int_to_bi(1); int i, j; int number_of_primes = 0; for (i = 1;; ++i) { for (j = 0; j < 4; ++j) { last = bi_add(last, bi_int_multiply(int_to_bi(i), 2)); if (j != 3 && bi_is_probable_prime(bi_copy(last), 4)) { ++number_of_primes; } } if ((double)number_of_primes / (4*i+1) < 0.1) { printf("%d\n", i*2+1); break; } #ifdef DEBUG printf("%d/%d on iteration %d ~%f\n", number_of_primes, (4*i+1), i, (float)number_of_primes/(4*i+1)); #endif } bi_free(last); bi_terminate(); return 0; }
/** * @brief Does both division and modulo calculations. * * Used extensively when doing classical reduction. * @param ctx [in] The bigint session context. * @param u [in] A bigint which is the numerator. * @param v [in] Either the denominator or the modulus depending on the mode. * @param is_mod [n] Determines if this is a normal division (0) or a reduction * (1). * @return The result of the division/reduction. */ bigint * ICACHE_FLASH_ATTR bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) { int n = v->size, m = u->size-n; int j = 0, orig_u_size = u->size; uint8_t mod_offset = ctx->mod_offset; comp d; bigint *quotient, *tmp_u; comp q_dash; check(u); check(v); /* if doing reduction and we are < mod, then return mod */ if (is_mod && bi_compare(v, u) > 0) { bi_free(ctx, v); return u; } quotient = alloc(ctx, m+1); tmp_u = alloc(ctx, n+1); v = trim(v); /* make sure we have no leading 0's */ d = (comp)((long_comp)COMP_RADIX/(V1+1)); /* clear things to start with */ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE)); /* normalise */ if (d > 1) { u = bi_int_multiply(ctx, u, d); if (is_mod) { v = ctx->bi_normalised_mod[mod_offset]; } else { v = bi_int_multiply(ctx, v, d); } } if (orig_u_size == u->size) /* new digit position u0 */ { more_comps(u, orig_u_size + 1); } do { /* get a temporary short version of u */ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE); /* calculate q' */ if (U(0) == V1) { q_dash = COMP_RADIX-1; } else { q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); if (v->size > 1 && V2) { /* we are implementing the following: if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - q_dash*V1)*COMP_RADIX) + U(2))) ... */ comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - (long_comp)q_dash*V1); if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) { q_dash--; } } } /* multiply and subtract */ if (q_dash) { int is_negative; tmp_u = bi_subtract(ctx, tmp_u, bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative); more_comps(tmp_u, n+1); Q(j) = q_dash; /* add back */ if (is_negative) { Q(j)--; tmp_u = bi_add(ctx, tmp_u, bi_copy(v)); /* lop off the carry */ tmp_u->size--; v->size--; } } else { Q(j) = 0; } /* copy back to u */ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE); } while (++j <= m); bi_free(ctx, tmp_u); bi_free(ctx, v); if (is_mod) /* get the remainder */ { bi_free(ctx, quotient); return bi_int_divide(ctx, trim(u), d); } else /* get the quotient */ { bi_free(ctx, u); return trim(quotient); } }
int main(int argc, char *argv[]) { #ifdef CONFIG_SSL_CERT_VERIFICATION RSA_CTX *rsa_ctx = NULL; BI_CTX *ctx; bigint *bi_data, *bi_res; float diff; int res = 1; struct timeval tv_old, tv_new; const char *plaintext; uint8_t compare[MAX_KEY_BYTE_SIZE]; int i, max_biggie = 10; /* really crank performance */ int len; uint8_t *buf; /** * 512 bit key */ plaintext = /* 64 byte number */ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"; len = get_file("../ssl/test/axTLS.key_512", &buf); asn1_get_private_key(buf, len, &rsa_ctx); ctx = rsa_ctx->bi_ctx; bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext)); bi_res = RSA_public(rsa_ctx, bi_data); bi_data = bi_res; /* reuse again */ gettimeofday(&tv_old, NULL); for (i = 0; i < max_biggie; i++) { bi_res = RSA_private(rsa_ctx, bi_copy(bi_data)); if (i < max_biggie-1) { bi_free(ctx, bi_res); } } gettimeofday(&tv_new, NULL); bi_free(ctx, bi_data); diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 + (tv_new.tv_usec-tv_old.tv_usec)/1000; printf("512 bit decrypt time: %.2fms\n", diff/max_biggie); TTY_FLUSH(); bi_export(ctx, bi_res, compare, 64); RSA_free(rsa_ctx); free(buf); if (memcmp(plaintext, compare, 64) != 0) goto end; /** * 1024 bit key */ plaintext = /* 128 byte number */ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"; len = get_file("../ssl/test/axTLS.key_1024", &buf); rsa_ctx = NULL; asn1_get_private_key(buf, len, &rsa_ctx); ctx = rsa_ctx->bi_ctx; bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext)); bi_res = RSA_public(rsa_ctx, bi_data); bi_data = bi_res; /* reuse again */ gettimeofday(&tv_old, NULL); for (i = 0; i < max_biggie; i++) { bi_res = RSA_private(rsa_ctx, bi_copy(bi_data)); if (i < max_biggie-1) { bi_free(ctx, bi_res); } } gettimeofday(&tv_new, NULL); bi_free(ctx, bi_data); diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 + (tv_new.tv_usec-tv_old.tv_usec)/1000; printf("1024 bit decrypt time: %.2fms\n", diff/max_biggie); TTY_FLUSH(); bi_export(ctx, bi_res, compare, 128); RSA_free(rsa_ctx); free(buf); if (memcmp(plaintext, compare, 128) != 0) goto end; /** * 2048 bit key */ plaintext = /* 256 byte number */ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"; len = get_file("../ssl/test/axTLS.key_2048", &buf); rsa_ctx = NULL; asn1_get_private_key(buf, len, &rsa_ctx); ctx = rsa_ctx->bi_ctx; bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext)); bi_res = RSA_public(rsa_ctx, bi_data); bi_data = bi_res; /* reuse again */ gettimeofday(&tv_old, NULL); for (i = 0; i < max_biggie; i++) { bi_res = RSA_private(rsa_ctx, bi_copy(bi_data)); if (i < max_biggie-1) { bi_free(ctx, bi_res); } } gettimeofday(&tv_new, NULL); bi_free(ctx, bi_data); diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 + (tv_new.tv_usec-tv_old.tv_usec)/1000; printf("2048 bit decrypt time: %.2fms\n", diff/max_biggie); TTY_FLUSH(); bi_export(ctx, bi_res, compare, 256); RSA_free(rsa_ctx); free(buf); if (memcmp(plaintext, compare, 256) != 0) goto end; /** * 4096 bit key */ plaintext = /* 512 byte number */ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^" "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"; len = get_file("../ssl/test/axTLS.key_4096", &buf); rsa_ctx = NULL; asn1_get_private_key(buf, len, &rsa_ctx); ctx = rsa_ctx->bi_ctx; bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext)); gettimeofday(&tv_old, NULL); bi_res = RSA_public(rsa_ctx, bi_data); gettimeofday(&tv_new, NULL); diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 + (tv_new.tv_usec-tv_old.tv_usec)/1000; printf("4096 bit encrypt time: %.2fms\n", diff); TTY_FLUSH(); bi_data = bi_res; /* reuse again */ gettimeofday(&tv_old, NULL); for (i = 0; i < max_biggie; i++) { bi_res = RSA_private(rsa_ctx, bi_copy(bi_data)); if (i < max_biggie-1) { bi_free(ctx, bi_res); } } gettimeofday(&tv_new, NULL); bi_free(ctx, bi_data); diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 + (tv_new.tv_usec-tv_old.tv_usec)/1000; printf("4096 bit decrypt time: %.2fms\n", diff/max_biggie); TTY_FLUSH(); bi_export(ctx, bi_res, compare, 512); RSA_free(rsa_ctx); free(buf); if (memcmp(plaintext, compare, 512) != 0) goto end; /* done */ printf("Bigint performance testing complete\n"); res = 0; end: return res; #else return 0; #endif }
int main() { bi_initialize(); bigint sum = int_to_bi(0); int a,b,c,d,e,f,g,h,i,j; int n; for (a=9;a>0;--a) { for (b=9;b>=0;--b) { if (b==a) continue; for (c=9;c>=0;--c) { if (c==a||c==b) continue; for (d=9;d>=0;--d) { if (d==a||d==b||d==c) continue; for (e=9;e>=0;--e) { if (e==a||e==b||e==c||e==d) continue; for (f=9;f>=0;--f) { if (f==a||f==b||f==c||f==d||f==e) continue; for (g=9;g>=0;--g) { if (g==a||g==b||g==c||g==d||g==e||g==f) continue; for (h=9;h>=0;--h) { if (h==a||h==b||h==c||h==d||h==e||h==f||h==g) continue; for (i=9;i>=0;--i) { if (i==a||i==b||i==c||i==d||i==e||i==f||i==g||i==h) continue; for (j=9;j>=0;--j) { if (j==a||j==b||j==c||j==d||j==e||j==f||j==g||j==h||j==i) continue; if ((b * 100 + c * 10 + d) % 2 == 0) if ((c * 100 + d * 10 + e) % 3 == 0) if ((d * 100 + e * 10 + f) % 5 == 0) if ((e * 100 + f * 10 + g) % 7 == 0) if ((f * 100 + g * 10 + h) % 11 == 0) if ((g * 100 + h * 10 + i) % 13 == 0) if ((h * 100 + i * 10 + j) % 17 == 0) { n = b * 100000000 + c * 10000000 + d * 1000000 + e * 100000 + f * 10000 + g * 1000 + h * 100 + i * 10 + j * 1; sum = bi_add(sum, int_to_bi(n)); sum = bi_add(sum, bi_int_multiply(int_to_bi(1000000000), a)); #ifdef DEBUG printf("%d%d%d%d%d%d%d%d%d%d\n", a,b,c,d,e,f,g,h,i,j); bi_print(stdout,bi_copy(sum)); printf("\n"); #endif } } } } } } } } } } } bi_print(stdout,sum); printf("\n"); bi_terminate(); return 0; }