コード例 #1
0
ファイル: main.c プロジェクト: seppo0010/Euler
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;
}
コード例 #2
0
ファイル: ssl_bigint.c プロジェクト: lvjh/esp32-devkit
/**
 * @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));
}
コード例 #3
0
ファイル: rsa.c プロジェクト: tomatoXu/syslinux-rsa-test
/**
 * 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));
}
コード例 #4
0
ファイル: main.c プロジェクト: kennywj/rsatest
/**************************************************************************
 * 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;
}
コード例 #5
0
ファイル: ssl_bigint.c プロジェクト: lvjh/esp32-devkit
/*
 * 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));
}
コード例 #6
0
ファイル: main.c プロジェクト: seppo0010/Euler
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;
}
コード例 #7
0
ファイル: main.c プロジェクト: seppo0010/Euler
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;
}
コード例 #8
0
ファイル: ssl_bigint.c プロジェクト: Itachihi/esp8266_car
/*
 * 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;
}
コード例 #9
0
ファイル: main.c プロジェクト: seppo0010/Euler
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;
}
コード例 #10
0
ファイル: ssl_bigint.c プロジェクト: lvjh/esp32-devkit
/**
 * @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);
    }
}
コード例 #11
0
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
}
コード例 #12
0
ファイル: main.c プロジェクト: seppo0010/Euler
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;
}