仿射密碼-fanfie--affine
⭐仿射密碼
仿射密碼 是一種專情密碼,一對一替換 ~~
加密函式是
e(x) = ax + b (mod m)
其中a和m 互質,m是字母的數目。解碼函式是
d(x) = a^-1(x - b) (mod m)
(打不出來湊合一下 a^-1 乘法逆元)
⭐仿射例題
【攻防世界】 - - fanfie
先上題,該題來源於 BITSCTF 。 【題目連結】
下載附件,得到如下的字串。 長度不長,大寫字母和數字組成。 很容易讓人想到 Base64/32 解密。
MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI
先簡單提一下 詳細介紹可以看一下網上大佬的這篇
關於base系列的加密解密
- Base64 : 由
0-9、a-z、A-Z、+、/
及字尾 “=” 組成 將任意位元組序列資料編碼成ASCII字串- Base32 : 用32個可列印字元
A-Z、2-7
對任意位元組資料進行編碼
然而通過Base64解碼並沒有發現什麼。(這題腦洞是真的大!!怪不得叫“ fanfie”-幻想)
通過百度大佬 題解 才知:
-
[ ] 將
BITSCTF
進行Base32加密 附 Base32加密網站IJEVIU2DKRDA====
-
[ ] 得到的這串密文與題目給出的字串進行比對
MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI IJEVIU2DKRDA====
發現上面相同的字母對應的下面的字母也一致。(如 M - I 、L - D)既然如此,那便有跡可循。
因為是Base32編碼。那麼對A-Z、2-7 進行編碼:
A | B | C | D | E | F | G | H |
---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
I | J | K | L | M | N | O | P |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Q | R | S | T | U | V | W | X |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
Y | Z | 2 | 3 | 4 | 5 | 6 | 7 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
由此更直觀可見,字母對應關係
3 ->11 4 ->24 8 ->12 20 ->8 21->21 25->9 26->22
這種一個字母替換一個字母的替換密碼就是 仿射密碼
加密函式是
e(x) = ax + b (mod m)
其中a和m 互質,m是字母的數目。解碼函式是
d(x) = a^-1(x - b) (mod m)
(打不出來湊合一下 a^-1 乘法逆元)
如何進行仿射解密呢? 我們有倆種方法:
- 進行肉眼勘測和手動計算
- python指令碼自動跑
先來看第一種: 由上述所有條件,我們可以自豪的斷定: 仿射密碼的 a = 13 b = 4
經過仿射解密 可得 :
MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI --> IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU
第二種,上指令碼:借鑑大佬 仿射加密解密指令碼 歐幾里得演算法求解乘法逆元
已知 加密仿射的 a:13 b:4 模:32 第一步先求解 13關於模32的逆元
# 歐幾里德演算法求最大公約數
def get_gcd(a, b):
k = a // b
remainder = a % b
while remainder != 0:
a = b
b = remainder
k = a // b
remainder = a % b
return b
# 改進歐幾里得演算法求線性方程的x與y
def get_(a, b):
if b == 0:
return 1, 0
else:
k = a // b
remainder = a % b
x1, y1 = get_(b, remainder)
x, y = y1, x1 - k * y1
return x, y
a = input('a:')
b = input('b:')
a, b = int(a), int(b)
# 將初始b的絕對值進行儲存
if b < 0:
m = abs(b)
else:
m = b
flag = get_gcd(a, b)
# 判斷最大公約數是否為1,若不是則沒有逆元
if flag == 1:
x, y = get_(a, b)
x0 = x % m # 對於Python '%'就是求模運算,因此不需要'+m'
print("所求的逆元:", x0) # x0就是所求的逆元
else:
print("Do not have!")
k1:仿射加密函式中的a
k2:仿射加密函式中的b
k3:13關於 模32 的逆元
輸入到下面java程式碼中
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
char[] form = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7'};
Scanner sc = new Scanner(System.in);
System.out.println("請輸入待加密的明文:");
String MingWen = sc.nextLine();
MingWen=MingWen.toUpperCase();
final int K1 = 13; //仿射加密函式中的a
final int K2 = 4; //仿射加密函式中的b
final int K3 = 5; // 13關於 模32 的逆元
int [] cipherNum=new int[MingWen.length()];//用來儲存數字化的密文
encryption(MingWen,form,K1,K2,K3,cipherNum);
}
public static void encryption(String MingWen,char[] form,int K1,int K2,int k3,int[] cipherNum){
char[] pla=new char[MingWen.length()];
for (int i = 0; i <MingWen.length() ; i++) {
pla[i]=MingWen.charAt(i);
}
int[] MingWenNumber=new int[pla.length];
for (int i = 0; i <pla.length ; i++) {
for (int j = 0; j <form.length ; j++) {
if (form[j]==pla[i]) {
MingWenNumber[i] = j;
}
}
}
//通過腳標將明文全部轉化為數字
char[] cipher = new char[MingWen.length()];
char[] JieMI = new char[MingWen.length()];
int len = MingWen.length();//cipher密碼陣列 用來儲存密文
for (int i = 0; i <MingWen.length() ; i++) {
int a= Math.floorMod((K1*MingWenNumber[i]+K2),32);
cipherNum[i]=a;
cipher[i]=form[a];
//計算密文並存入陣列中
}
System.out.println("加密結果是:");
System.out.println(cipher);
for (int i =0;i<len;i++){
JieMI[i]=form[Math.floorMod(k3*(MingWenNumber[i]-K2),32)];
}
System.out.println("解密結果是:");
System.out.println(JieMI);
}
}
IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU
最後一步啦~ 對指令碼跑出的程式碼進行 Base32 解碼 。網站同上。
BITSCTF{S2VyY2tob2Zm}
再來一簡單題!
【bugkuCtf】 -- affine
題目連結 請戳這裡
u1s1,該題目就非常實誠。直接給出 a / b 以及 密文 並且 affine 直接明示 這是 仿射解密 。
- E(x) = (ax + b) (mod m) a=17 b = -8
szzyfimhyzd
話不多說,我們可以繼續使用上面的指令碼 也可以使用下面一種更快的指令碼 搬自這位大佬
def get(a, b):
if b == 0:
return 1, 0
else:
k = a //b
remainder = a % b
x1, y1 = get(b, remainder)
x, y =y1, x1 - k * y1
return x, y
s = input("請輸入解密字元:").upper()
a = int(input("請輸入a:"))
b = int(input("請輸入b:"))
#求a關於26的乘法逆元
x, y = get(a, 26)
a1 = x % 26
l= len(s)
for i in range(l):
cipher = a1 * (ord(s[i])- 65 - b) % 26
res=chr(cipher + 65)
print(res, end='')
因為題目已經明確給出 ,所以直接進行解析就好。
preflag = "szzyfimhyzd"
flags = []
for i in preflag:
flags.append(ord(i)-97)
flag = ""
for i in flags:
for j in range(0,26):
a = (17 * j - 8) % 26
if(a == i):
flag += chr(j+97)
print(flag)
那最後的flag就是:
affineshift
⭐結語
最後:其實我蠻驚奇的。 fanfie && affine 取名上十分巧妙。
( 前一題是不是有暗示的意味在呢~~手動狗頭 )
寶藏軟體推薦
【強烈安利】 無意間知道了這個神仙軟體 captfencoder (點選下載哦~)
裡面聚合編碼轉換古典密碼密碼學其他編碼實用工具!!
還是老規矩 :關於以上鍊接引用【侵權刪】
若有錯誤之處,還請多多指正~~
【轉載請放連結】 https://www.cnblogs.com/Jlay/p/RSA_Environment.html