玩CTF學密碼學4:

第一題:冪數加密

在這裏插入圖片描述
查看附件:
在這裏插入圖片描述ios

第一題分析:

他說答案是八位的大寫字母,大寫字母要麼是ASCII表上的65-90,要麼就0-25(或1-26)也是能夠表示。可是既然說明是八位,那這個八位確定要體現出來,也就是說這個附件要可以搞出八個數碼來表明大寫字母。咱們先獲得這個字符串的長度:34,這不能被8整除,那是否有別的字符能標識8段呢?
因而我寫了這樣一個程序:算法

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
	map<char, int> mp;
	string str = "8842101220480224404014224202480122";
	for (int i = 0; i < (int)str.length(); ++i)
		mp[str[i]]++;
	for (map<char, int>::iterator it = mp.begin(); mp.end() != it; ++it)
		cout << it->first << ' ' << it->second << endl;
	return 0;
}

結果以下:
在這裏插入圖片描述
首先咱們知道,要把一段序列分紅8段,就必須某個字符要出現7次,這裏出現7次的惟獨’0’這個字符,那咱們就不妨以0爲分界線來劃分出8個數字碼:
在這裏插入圖片描述
合起來就是:
WELLDONE(翻譯就是幹得漂亮?作得很好?)以爲還像那麼回事,因而提交!果真AC!markdown

第二題:easy_RSA

在這裏插入圖片描述
下載附件:
在這裏插入圖片描述
說實話,我喜歡作這種題,由於我自己是作公鑰密碼學大類的(如今密碼學研究都是公鑰密碼甚至是同態密碼,前幾道對稱密碼我不太瞭解……)ide

講講RSA算法:

首先拿到素數p和q,而後計算n = p * q,phi(n) = (p - 1) * (q - 1)(歐拉函數,不曉得請自行了解),而後已知公鑰e = 17,能夠計算私鑰d = e^(-1) mod( phi(n) )
也就是說,公鑰和私鑰互爲逆元,這裏要咱們求私鑰d,至關於求逆元!如何求逆元?函數

求逆元的簡單方法:

能夠用快速冪求逆元,固然也能夠用拓展歐幾里得算法求逆元,咱們就講一種比較簡單的方法求逆元。已知逆元的定義:
a * b mod p = 1
咱們就說:a和b互爲模p意義下的逆元
由費馬小定理獲得:a^(p - 1) mod p = 1,那也就是說a * a^(p - 2) modp = 1,也就是說求a在模p意義下的逆元,就是求 a ^(p - 2)atom

可是這個方法的使用是有條件的!那就是p是素數,且a < p,而我們這個題,p是素數嗎?模數不是素數,其實在RSA算法中,模數都不會是素數,由於p和q是不相同的素數,素數惟一的偶數是2,而p和q之中至少有一個不是2,則是奇數,那麼p(或者q) - 1 就必定是偶數,偶數乘以任何數都是偶數,則必然模數不是質數!!加密

求逆元的通用方法:拓展歐幾里得算法

爲何能夠用擴展歐幾里得算法呢?
先來看一個方程:
ax + by = 1
若是兩邊同時對b取模,則:ax mod b = 1
那麼a和x就是模b意義下的逆元,而咱們告知a和b,求出x至關於求方程的解,由此能夠得出用拓展歐幾里得算法求逆元!spa

代碼以下:翻譯

#include <iostream>
#define LL long long
using namespace std;

void extendGcd(LL a, LL b, LL& x, LL& y)
{
	if (0 == b)
	{
		x = 1, y = 0;
		return;
	}
	extendGcd(b, a % b, x, y);
	LL Temp = x;
	x = y;
	y = Temp - (a / b) * y;
}

int main()
{
	LL p = 473398607161, q = 4511491, e = 17;
	LL phi = (p - 1) * (q - 1);
	LL x, y;
	extendGcd(e, phi, x, y);
	cout << x;
	return 0;
}

結果展現:
在這裏插入圖片描述3d

寫在後面:

擴展歐幾里得算法和費馬小定理求逆元,是兩種最多見的求逆元方法,此外還有篩法、遞推等等辦法,不過基本上,用拓展歐幾里得就差很少能夠搞定所有了!求逆元是數論、密碼學中常見的計算需求!

相關文章
相關標籤/搜索