Deprecated:  The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
/*
 * $Id: rsa-2.c,v 1.4 2005/02/19 16:01:53 68user Exp $
 *
 * OpenSSL を使った RSA の実装 (2)
 *   素数生成はライブラリまかせ。RSA 鍵生成・暗号化・復号化は自前で版。
 *
 * written by 68user  http://X68000.q-e-d.net~68user/
 */
#include 
#include 
#include 
#include 
#define BN_PUT(bn) { printf(#bn "=%s (0x%s)\n", BN_bn2dec(bn), BN_bn2hex(bn)); }
#define KEYBIT_LEN  128
int
main(){
    unsigned char plain_buf[]="abcdefghijklmnopqrstuvwxyz1234";
    ERR_load_crypto_strings();
    BIGNUM *bn_e = BN_new(); BN_set_word(bn_e, 65537);
    BIGNUM *bn_n = BN_new();
    BIGNUM *bn_d = BN_new();
    BN_CTX *bn_ctx_tmp = BN_CTX_new();
    {
        /* 素数生成 */
        BIGNUM *bn_p = BN_new();	/* 素数 p */
        BIGNUM *bn_q = BN_new();	/* 素数 q */
        BN_generate_prime(bn_p, KEYBIT_LEN/2, 1, NULL, NULL, NULL, NULL);
        BN_generate_prime(bn_q, KEYBIT_LEN/2, 1, NULL, NULL, NULL, NULL);
        /* n = p*q
         * pm = p-1
         * qm = q-1
         * pmqm = (p-1)*(q-1)
         * gcd_pmqm = (p-1) と (q-1) の最大公約数
         * L = (p-1) と (q-1) の最小公倍数 = (p-1)*(q-1)/gcd(p-1,q-1)
         */
        BIGNUM *bn_pm = BN_new();	/* p-1 (p minus 1) */
        BIGNUM *bn_qm = BN_new();	/* q-1 (q minus 1) */
        BIGNUM *bn_pmqm = BN_new();	/* (p-1)*(q-1) */
        BIGNUM *bn_gcd_pmqm = BN_new(); /* (p-1) と (q-1) の最小公倍数 */
        BIGNUM *bn_L = BN_new();	/* L。(p-1) と (q-1) の最小公倍数 */
        BIGNUM *bn_one = BN_new();	/* 1 */
        BN_one(bn_one);
        BN_mul(bn_n, bn_p, bn_q, bn_ctx_tmp);
        BN_sub(bn_pm, bn_p, bn_one);
        BN_sub(bn_qm, bn_q, bn_one);
        BN_mul(bn_pmqm, bn_pm, bn_qm, bn_ctx_tmp);
        BN_gcd(bn_gcd_pmqm, bn_pm, bn_qm, bn_ctx_tmp);
        BN_div(bn_L, NULL, bn_pmqm, bn_gcd_pmqm, bn_ctx_tmp);
        BN_PUT(bn_p); BN_PUT(bn_q); BN_PUT(bn_n); BN_PUT(bn_pm);
        BN_PUT(bn_qm); BN_PUT(bn_pmqm); BN_PUT(bn_gcd_pmqm); BN_PUT(bn_L);
        /* a*x + b*y = 1 を満たす x と y (y>0) を見付ける。この y が d となる
         * ここでは a は L、b は e。e に大きい数を指定した場合は、逆にすべきかも。*/
        {
            /* (x1, y1, z1) ← (1, 0, a) ここでの a は L
             * (x2, y2, z2) ← (0, 1, b) ここでの b は e
             */
            BIGNUM *bn_x1   = BN_new(); BN_one(bn_x1);
            BIGNUM *bn_y1   = BN_new(); BN_zero(bn_y1);
            BIGNUM *bn_z1   = BN_new(); BN_copy(bn_z1, bn_L);
            BIGNUM *bn_x2   = BN_new(); BN_zero(bn_x2);
            BIGNUM *bn_y2   = BN_new(); BN_one(bn_y2);
            BIGNUM *bn_z2   = BN_new(); BN_copy(bn_z2, bn_e);
            BIGNUM *bn_x3   = BN_new();
            BIGNUM *bn_y3   = BN_new();
            BIGNUM *bn_z3   = BN_new();
            BIGNUM *bn_q    = BN_new();
            BIGNUM *bn_tmp  = BN_new();
            BIGNUM *bn_zero = BN_new(); BN_zero(bn_zero);
            /* z2 が 0 になったらループ終了 */
            while ( ! BN_is_zero(bn_z2) ){
                /* q ← z1 を z2 で割った商
                 * (x3, y3, z3) ← (x1, y1, z1) - q * (x2, y2, z2)
                 * (x1, y1, z1) ← (x2, y2, z2)
                 * (x2, y2, z2) ← (x3, y3, z3)
                 */
                BN_div(bn_q, NULL, bn_z1, bn_z2, bn_ctx_tmp);
                BN_mul(bn_tmp, bn_q, bn_x2, bn_ctx_tmp);
                BN_sub(bn_x3, bn_x1, bn_tmp);
                BN_mul(bn_tmp, bn_q, bn_y2, bn_ctx_tmp);
                BN_sub(bn_y3, bn_y1, bn_tmp);
                BN_mul(bn_tmp, bn_q, bn_z2, bn_ctx_tmp);
                BN_sub(bn_z3, bn_z1, bn_tmp);
                BN_copy(bn_x1, bn_x2); BN_copy(bn_y1, bn_y2); BN_copy(bn_z1, bn_z2);
                BN_copy(bn_x2, bn_x3); BN_copy(bn_y2, bn_y3); BN_copy(bn_z2, bn_z3);
            }
            /* ここで y1 が求めたい d である。ただし d が負なら L を足して、次の候補に補正 */
            BN_copy(bn_d, bn_y1);
            if ( BN_cmp(bn_d, bn_zero) == -1 ){
                BN_add(bn_d, bn_d, bn_L);
            }
            BN_PUT(bn_e);
            BN_PUT(bn_d);
            BN_free(bn_x1); BN_free(bn_y1); BN_free(bn_z1);
            BN_free(bn_x2); BN_free(bn_y2); BN_free(bn_z2);
            BN_free(bn_x3); BN_free(bn_y3); BN_free(bn_z3);
            BN_free(bn_q); BN_free(bn_tmp); BN_free(bn_zero);
        }
        BN_free(bn_p); BN_free(bn_q); BN_free(bn_pm); BN_free(bn_qm);
        BN_free(bn_pmqm); BN_free(bn_gcd_pmqm); BN_free(bn_L);  BN_free(bn_one);
    }
    char *p = plain_buf;
    int finished = 0;
    while ( ! finished && *p != '\0' ){
        int i;
        BIGNUM *bn_chunk = BN_new();
        BN_init(bn_chunk);
        /* 平文を鍵長のバイト数に区切る */
        printf("平文: [");
        for ( i=0 ; i