What is it, naokirin?

エルガマル暗号のプログラム

エルガマル暗号をプログラムにしてみた。

素数とか原始元の計算は抜きにしたので、現実で使えるかと言われればダメ。
あんまりしっかりとやっていないので間違いもあり得るし、おそらく入力に対して何かしらのエラーを吐く可能性も無きにしも非ず。

まあ、参考程度ですね。


まず鍵の作成

大きな素数prime、原始根root、有限体の要素skeyを定める。
次に
pkey≡root^skey (mod prime)
を計算し、skeyを秘密鍵、prime, root, pkeyを公開鍵とする。


暗号化

送りたい平文をmessageとする。

乱数randomを生成し、
c1=root^random (mod prime)
c2=message*pkey^random (mod prime)
の二つのペア(c1, c2)が暗号文となる。


最後に復号化

秘密鍵skeyを使い、次のように計算すると暗号文を復号化できる。
c1*c2^(p-1-s) (mod prime)


以下プログラム。

/* 
 * エルガマル暗号の暗号化関数
 * 
 * stdio.h、stdlib.h、time.hのインクルードが必要
 * message:平文 prime:素数 root:原始根 pkey:公開鍵 *a、*bはできあがる暗号文を返すためのもの
 */
void encode(int message, int prime, int root, int pkey, int *a, int *b)
{
    /* 
     * 素数より入力の平文が大きいときは暗号化できないので失敗
     * ふつうは平文を区切ったりするらしい
     * 
     * TODO:入力が大きくてもできるように変える
     */
    if(pkey<message){
        printf("This encode is FAILURE");
        exit(EXIT_FAILURE);
    }
    else{
        srand((unsigned)time(NULL));
        
        /* 1以上INDEX_MAX以下の乱数を生成 */
        int k = rand()%INDEX_MAX+1;

        /* 暗号文を生成 */
        *a = mod(intPow(root, k),prime);
        *b = mod(intPow(pkey,k)*message, prime);
    }    
}

/* 
 * エルガマル暗号の復号化関数 
 *
 * a,b:暗号文 prime:素数 skey:秘密鍵
 */
int decode(int a, int b,int prime, int skey)
{
    return mod(intPow(a, prime-1-skey)*b, prime);
}

/* 
 * エルガマル暗号の鍵の生成
 * 
 * prime:素数 root:原始根 skey:秘密鍵
 */
int publicKey(int prime, int root, int skey)
{
    return mod(intPow(root, skey),prime);
}

/* 
 * int型のint型の累乗の計算を行う関数
 * 
 * おそらくもっと高速に動くアルゴリズムが存在する
 * TODO:もっと高速な計算ができるようにする
 */
int</span> intPow(int a, int b)
{
    if(b<0)
        return 0;
    int result=1;

    for(int i=0; i<b; i++)
        result = result*a;

    return result;
}

/* モジュラ演算を行う関数 */
int mod(int a, int b)
{
    return a%b<0 ? a%b+b:a%b;
}