公鑰密碼體制是近現代的乙個偉大發明,相對於傳統的密碼體制而言,公鑰密碼體制有許多的優點,他能夠使得使用者能夠在公共通道上安全的進行金鑰交換,而不必擔心由於金鑰在公共通道上傳輸時受到攻擊而導致的金鑰洩露。
以下部分將介紹公鑰密碼中的elgamal密碼體制,並有c語言函式實現。
2023年,elgamal提出了一種基於離散對數的公開金鑰體制,他的金鑰產生基於乙個公開的素數,利用離散對數計算上的困難性保證安全。
首先是生成金鑰對的過程:
1 隨機生成整數x,使得1 < x < q - 1(q 是使用者共同選擇的素數)
2 計算 y = ax mod q (a 是素數q的本原根)
3 a 的私鑰是x,公鑰是
其他的使用者可以通過上面的公鑰加密資訊:
1 將資訊表示為乙個整數m,其中1 <= m <= q - 1,以分組密碼序列的方式來傳送訊息
2 選擇任意整數k,使得1 <= k <= q - 1
3 計算一次金鑰k = (y)k mod q
4 將m加密成明文對(c1,c2),其中c1 = a k mod q;c2 = km mod q
這樣只要我們知道私鑰就可以恢復明文:
1 計算金鑰k = (c1)x mod q 恢復金鑰
2 計算m = (c2k-1) mod q
下面來看看我們如何實現加密:
#include
#include
#include
/* * 全域性引數
* p:生成的大整數
* g:p的素根
* y:g^d次方
* d:私鑰
*/mpz_t p,g,y,d;
/* * c1,c2 密文的兩部分
* m 明文
*/mpz_t c1, c2;
mpz_t m;
/* * 使用了gmp庫,這裡是一些函式介紹
* 素數判斷:
* int mpz_probab_prime_p (mpz_t n, int reps)
* 判斷 n 是否為素數,若 n 確定是素數則返回 2,如果 n 是概率素數 (不能完全
* 確定) 那麼返回 1,或者如果 n 確定是合數那麼返回 0。
* 這個函式首先做一些試除,然後再作 miller-rabin 概率素性判別。reps 控制這
* 樣的判別做多少次,5 到 10 是較合理的數值,更多次的判別可以減小合數被返
* 回為概率素數的可能。
* 呼叫 miller-rabin 判別和其他相似的判別組成的復合判別可能更為合理。判別
* 失敗的數可以知道是合數,但是通過判別的數可以是素數也可能是合數。只有
* 極少數的合數可以通過判別,因此通過判別的數一般都被認為是素數。
* * 隨機數函式:
* void mpz_urandomb(mpz_t rop,gmp_randstate_t state,unsigned long int n) [函式]
* 產生乙個均勻分布在 0 到 2^n − 1(包含) 範圍內的隨機整數。
* 在啟用這個函式之前必須先呼叫某個 gmp_randinit 函式對變數 state 進行初始化。
* * 隨機狀態初始化:
* void gmp_randinit_default (gmp_randstate_t state) [函式]
* 用預設演算法初始化 state。這是速度與隨機性之間的權衡,建議沒有特殊要求的
* 應用使用它。
* * 輸入:bits
* 輸出:生成乙個範圍在0~2^n - 1 的隨機素數
*/void random_prime(unsigned
long
int bits)
return;}/*
* 求本原根的演算法
* int mpz_init_set_str (mpz_t rop, char *str, int base) 賦值
* void mpz_add (mpz_t rop, mpz_t op1, mpz_t op2) rop = op1 + op2
* 輸入:p
* 輸出:p的素根
*/void root_nums()
int i,templength;//templength = 0;// temp陣列中有意義的值的數量
while(1)
}if(i == templength)else
break;
}if(templength == tempnum)
}mpz_add(a,a,b);
}}/* * bits是生成的隨機數的位數,2^bits
* p是生成的隨機素數
* g是素數p的素根
* y是素根g^d次方
* 則d是私鑰, (p,g,y)是公鑰
* 輸入:bits
* 輸出:公鑰(p,g,y),私鑰(d)
*/void elgamal_keygen(unsigned
long
int bits)
/* * m:資訊
* p,g,y:公鑰
* 輸入:資訊(m),公鑰(p,g,y)
* 輸出:資訊(m)的密文(c1,c2)
*/void elgamal_encrypt()
/* * 輸入:密文(c1,c2),私鑰(d),共同選擇的素數(p)
* 輸出:明文(m)
*/void elgamal_decrypty()
int main()
// 第一位加上5,避免第一位是0
temp[0] += 5;
message[i + 1] = '\0';
temp[j + 1] = '\0';
mpz_init_set_str(m,temp,10);
elgamal_keygen(128);
elgamal_encrypt();
gmp_printf("加密的結果是:(%zd,%zd)\n",c1,c2);
elgamal_decrypty();
char* r = mpz_get_str(temp,10,m);
// 前面加了5,這裡要去除
temp[0] -= 5;
for(i = 0,j = 0 ; i < 12 && j < len ; i++)
message[len + 1] = '\0';
printf("解密的結果是:%s\n",message);
} free(message);
free(temp);
mpz_clear(p);
mpz_clear(g);
mpz_clear(y);
mpz_clear(d);
mpz_clear(c1);
mpz_clear(c2);
mpz_clear(m);
return
0;}
**的過程很詳細了,就不一一解釋了,安全越來越重要,需要我們特別注意。 Elgamal 加密演算法
elgamal演算法是由tather elgamal在1985年提出的,它是一種基於離散對數難題的加密體系,與ras演算法一樣,既能用於資料加密,也能用於數字簽名。elgamal演算法是基於因數分解,而elgamal演算法是基於離散對數問題。與rsa演算法相比,elgamal演算法哪怕是使用相同的私...
對稱加密 利用mcrypt實現加密解密 2
加密解密類 也是對稱加密 aes 模式,和 我之前寫的 利用mcrypt實現加密解密 1 的區別是 這個生成的秘鑰是唯一的,之前的是多個秘鑰解密的值是一樣的 注意 php版本在 7.1.9以上的不贊成使用 mcrypt module open 函式 貼上即用 class cryptaes funct...
編譯原理利用Flex Bison實現簡單計算器
編譯原理利用flex bison實現簡單計算器 一 實驗目的 1 掌握 yacc 的基本用法,並能夠根據語言給出語法規則的定義,最後生成語言的解析器 2 使用使用 yacc 實現乙個高階計算器程式 二 實驗內容 實現乙個簡單的表示式計算器,要求能進行加 減 乘 除 冪運算,注意優先順序。寫出詳細的步...