Cryptohack
文章目录
RSA
RSA1
python直接跑:
print(pow(101,17,22663))
#19906
RSA2
考察rsa加密
m=12
e=65537
p=17
q=23
n = p*q
print(pow(m,e,n))
#301
RSA3
求n的totient of N
求欧拉函数:
p = 857504083339712752489993810777
q = 1029224947942998075080348647219
n = p*q
print((p-1)*(q-1))
#882564595536224140639625987657529300394956519977044270821168
RSA4
求私钥d
p = 857504083339712752489993810777
q = 1029224947942998075080348647219
e = 65537
phi = (p-1) * (q-1)
import gmpy2
d = gmpy2.invert(e,phi)
print(d)
#121832886702415731577073962957377780195510499965398469843281
RSA5
首先分解N 因为N比较小 直接yafu跑一下
成功得到p和q
p = 857504083339712752489993810777
q = 1029224947942998075080348647219
e = 65537
c = 77578995801157823671636298847186723593814843845525223303932
N = p*q
phi = (p-1) * (q-1)
import gmpy2
d = gmpy2.invert(e,phi)
print(pow(c,d,N))
#13371337
RSA6
题目意图 给出你的私钥和N,然后需要利用私钥对明文进行sha256生成消息验证码
from Crypto.Util.number import *
N = 15216583654836731327639981224133918855895948374072384050848479908982286890731769486609085918857664046075375253168955058743185664390273058074450390236774324903305663479046566232967297765731625328029814055635316002591227570271271445226094919864475407884459980489638001092788574811554149774028950310695112688723853763743238753349782508121985338746755237819373178699343135091783992299561827389745132880022259873387524273298850340648779897909381979714026837172003953221052431217940632552930880000919436507245150726543040714721553361063311954285289857582079880295199632757829525723874753306371990452491305564061051059885803
d = 11175901210643014262548222473449533091378848269490518850474399681690547281665059317155831692300453197335735728459259392366823302405685389586883670043744683993709123180805154631088513521456979317628012721881537154107239389466063136007337120599915456659758559300673444689263854921332185562706707573660658164991098457874495054854491474065039621922972671588299315846306069845169959451250821044417886630346229021305410340100401530146135418806544340908355106582089082980533651095594192031411679866134256418292249592135441145384466261279428795408721990564658703903787956958168449841491667690491585550160457893350536334242689
import hashlib
def sha256_encrypt(string):
# 对要加密的字符串进行编码
string = string.encode()
# 使用 hashlib 库的 sha256 函数进行加密 最后注意是digest摘要
encrypted_string = hashlib.sha256(string).digest()
return encrypted_string
m = sha256_encrypt("crypto{Immut4ble_m3ssag1ng}")
print(m)
m = bytes_to_long(m)
print(pow(m,d,N))
#1348073840459009080333983164923845437618318974497068312990976607887770658328242268671054521727579737670967235889423155033500797498345840862025847872977564781887661007290302123557392330007010366694053404764490047577331868258577269815561745147744844119815071042081899534723592111181206865678299816806496096545171949107256905763670119042976004719326188609286202411848782645276651353386073472412422830515891422525048839967364573288207757525266246186097288977111259490688444145435595948292528399253992571342413200976872138982884890709977204083638385652460500894290708349038310975740694054086697823747168629666168583908347513480738404590090803339831649238454376183189744970683129909766078877706583282422686710545217275797376709672358894231550335007974983458408620258478729775647818876610072903021235573923300070103666940534047644900475773318682585772698155617451477448441198150710420818995347235921111812068656782998168064960965451719491072569057636701190429760047193261886092862024118487826452766513533860734724124228305158914225250488399673645732882077575252662461860972889771112594906884441454355959482925283992539925713424132009768721389828848907099772040836383856524605008942907083490383109757406940540866978237471686296661685839083475
HOW AES WORKS
Keyed Permutations
Q:What is the mathematical term for a one-to-one correspondence?
一一对应的数学数语是什么 双射 ==> bijection
Resisting Bruteforce
Q:What is the name for the best single-key attack against AES?
最好的单密钥攻击AES的名字是什么 ==>
biclique
参考链接:https://en.wikipedia.org/wiki/Biclique_attack
Structure of AES
题目要求:""" Converts a 4x4 matrix into a 16-byte array. """
补充这段代码 把矩阵中的数据提取转换为byte array 字节数组
def bytes2matrix(text):
""" Converts a 16-byte array into a 4x4 matrix. """
return [list(text[i:i+4]) for i in range(0, len(text), 4)]
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
rows = len(matrix)
columns = len(matrix[0]) #取第一行的元素取长度
str = []
for i in range(rows):
for j in range(columns):
str.append(matrix[i][j])
return bytes(str)
matrix = [
[99, 114, 121, 112],
[116, 111, 123, 105],
[110, 109, 97, 116],
[114, 105, 120, 125],
]
print(matrix2bytes(matrix))
#b'crypto{i********ix}'
Round Keys
The *AddRoundKey* step is straightforward: it XORs the current state with the current round key.
根据题目描述 得知需要生成的矩阵的方法 当前状态值和当前轮密钥的异或
得到矩阵后借用上一题的函数输出结果
state = [
[206, 243, 61, 34],
[171, 11, 93, 31],
[16, 200, 91, 108],
[150, 3, 194, 51],
]
round_key = [
[173, 129, 68, 82],
[223, 100, 38, 109],
[32, 189, 53, 8],
[253, 48, 187, 78],
]
def add_round_key(s, k):
#明确我们要返回的是一个新状态的矩阵
rows = len(s)
columns = len(s[0]) #取第一行的元素取长度
new = [[0]*columns for i in range(rows)]
print(new)
for i in range(rows):
for j in range(columns):
new[i][j]=s[i][j]^k[i][j]
return new
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
rows = len(matrix)
columns = len(matrix[0]) #取第一行的元素取长度
str = []
for i in range(rows):
for j in range(columns):
str.append(matrix[i][j])
return bytes(str)
print(add_round_key(state, round_key))
print(matrix2bytes(add_round_key(state,round_key)))
#b'crypto{r****3y}'
Confusion through Substitution
根据题目得知在2**8 即256的有限域内
还提到s盒的内容是从0x00
到0xff
所以针对当前状态 找到对应值转换为字节即可
s_box = (
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
)
inv_s_box = (
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
)
state = [
[251, 64, 182, 81],
[146, 168, 33, 80],
[199, 159, 195, 24],
[64, 80, 182, 255],
]
def sub_bytes(s, sbox=s_box):
str = ""
for i in range(4):
for j in range(4):
str += chr(sbox[s[i][j]])
return str
print(sub_bytes(state, sbox=inv_s_box))
#crypto{}
Diffusion through Substitution
首先是对行移位进行逆运算
直接按照本来的行移位反向等就ok
def shift_rows(s):
s[0][1], s[1][1], s[2][1], s[3][1] = s[1][1], s[2][1], s[3][1], s[0][1]
s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2]
s[0][3], s[1][3], s[2][3], s[3][3] = s[3][3], s[0][3], s[1][3], s[2][3]
def inv_shift_rows(s):
#翻转
s[1][1], s[2][1], s[3][1], s[0][1] = s[0][1], s[1][1], s[2][1], s[3][1]
s[2][2], s[3][2], s[0][2], s[1][2] = s[0][2], s[1][2], s[2][2], s[3][2]
s[3][3], s[0][3], s[1][3], s[2][3] = s[0][3], s[1][3], s[2][3], s[3][3]
# learned from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def mix_single_column(a):
# see Sec 4.1.2 in The Design of Rijndael
t = a[0] ^ a[1] ^ a[2] ^ a[3]
u = a[0]
a[0] ^= t ^ xtime(a[0] ^ a[1])
a[1] ^= t ^ xtime(a[1] ^ a[2])
a[2] ^= t ^ xtime(a[2] ^ a[3])
a[3] ^= t ^ xtime(a[3] ^ u)
def mix_columns(s):
for i in range(4):
mix_single_column(s[i])
def inv_mix_columns(s):
# see Sec 4.1.3 in The Design of Rijndael
for i in range(4):
u = xtime(xtime(s[i][0] ^ s[i][2]))
v = xtime(xtime(s[i][1] ^ s[i][3]))
s[i][0] ^= u
s[i][1] ^= v
s[i][2] ^= u
s[i][3] ^= v
mix_columns(s)
state = [
[108, 106, 71, 86],
[96, 62, 38, 72],
[42, 184, 92, 209],
[94, 79, 8, 54],
]
inv_mix_columns(state)
inv_shift_rows(state)
#调用第一题的板子
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
rows = len(matrix)
columns = len(matrix[0]) #取第一行的元素取长度
str = []
for i in range(rows):
for j in range(columns):
str.append(matrix[i][j])
return bytes(str)
print(matrix2bytes(state))
Bring It All Together
根据前面分模块对AES加密体系的练习进行整合,形成完整的AES解密算法
题目给出了key和ciphertext密文
参考图片进行解密流程:
在列表数据中对数据的传输有些模糊 写了一个小demo测试一下
def test(s):
s[0][0] = 0
def sameTest():
a = [[12,13,14],[1,2,3]]
test(a)
print(a)
sameTest()
#[[0, 13, 14], [1, 2, 3]]
也就证明对一个矩阵的操作直接调用就行 会相应改变其值 而且与形参的名字没关系
- get all keys
#该函数题目给出
def expand_key(master_key):
...
round_keys = expand_key(key)
- AddRoundkey
#AddRoundKey: XORs the current state with the current round key.
#according to the N_ROUNDS = 10, we can know the k = keys[10]
def add_round_key(s, k):
#明确我们要返回的是一个新状态的矩阵
rows = len(s)
columns = len(s[0]) #取第一行的元素取长度
new = [[0]*columns for i in range(rows)]
print(new)
for i in range(rows):
for j in range(columns):
new[i][j]=s[i][j]^k[i][j]
return new
cipher = add_round_key(cipher,round_keys[10])
进行九轮的操作
- InvShiftRows
def inv_shift_rows(s):
#翻转
s[1][1], s[2][1], s[3][1], s[0][1] = s[0][1], s[1][1], s[2][1], s[3][1]
s[2][2], s[3][2], s[0][2], s[1][2] = s[0][2], s[1][2], s[2][2], s[3][2]
s[3][3], s[0][3], s[1][3], s[2][3] = s[0][3], s[1][3], s[2][3], s[3][3]
inv_shift_rows(cipher)
- InvSubBytes
inv_s_box = (
...
)
def inv_sub_bytes(s):
for i in range(4):
for j in range(4):
s[i][j] = chr(inv_s_box[s[i][j]])
invs_sub_bytes(cipher)
- AddRoundKey
同上
- InvMixColumns(题目给出)
# learned from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def inv_mix_columns(s):
# see Sec 4.1.3 in The Design of Rijndael
for i in range(4):
u = xtime(xtime(s[i][0] ^ s[i][2]))
v = xtime(xtime(s[i][1] ^ s[i][3]))
s[i][0] ^= u
s[i][1] ^= v
s[i][2] ^= u
s[i][3] ^= v
mix_columns(s)
最后一次复原注意没有MixColumns
执行一遍出结果
完成exp:(中间打了一些断点 因为和前面的有些数据类型不同)
N_ROUNDS = 10
key = b'\xc3,\\\xa6\xb5\x80^\x0c\xdb\x8d\xa5z*\xb6\xfe\\'
ciphertext = b'\xd1O\x14j\xa4+O\xb6\xa1\xc4\x08B)\x8f\x12\xdd'
s_box = (
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
)
def add_round_key(s, k):
#明确我们要返回的是一个新状态的矩阵
print(s)
# rows = len(s)
# columns = len(s[0]) #取第一行的元素取长度
# print(rows)
# print(s)
for i in range(4):
for j in range(4):
# new[i][j]=s[i][j] ^ k[i][j]
# print(s[i][j])
s[i][j] ^= k[i][j]
#逆s盒
inv_s_box = (
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
)
#逆字节替换
def inv_sub_bytes(s):
for i in range(4):
for j in range(4):
s[i][j] = inv_s_box[s[i][j]]
#2.行移位
# def shift_rows(s):
# s[0][1], s[1][1], s[2][1], s[3][1] = s[1][1], s[2][1], s[3][1], s[0][1]
# s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2]
# s[0][3], s[1][3], s[2][3], s[3][3] = s[3][3], s[0][3], s[1][3], s[2][3]
#逆行移位
def inv_shift_rows(s):
#翻转
s[1][1], s[2][1], s[3][1], s[0][1] = s[0][1], s[1][1], s[2][1], s[3][1]
s[2][2], s[3][2], s[0][2], s[1][2] = s[0][2], s[1][2], s[2][2], s[3][2]
s[3][3], s[0][3], s[1][3], s[2][3] = s[0][3], s[1][3], s[2][3], s[3][3]
#3.列混合
def mix_single_column(a):
# see Sec 4.1.2 in The Design of Rijndael
t = a[0] ^ a[1] ^ a[2] ^ a[3]
u = a[0]
a[0] ^= t ^ xtime(a[0] ^ a[1])
a[1] ^= t ^ xtime(a[1] ^ a[2])
a[2] ^= t ^ xtime(a[2] ^ a[3])
a[3] ^= t ^ xtime(a[3] ^ u)
def mix_columns(s):
for i in range(4):
mix_single_column(s[i])
#逆列混合
# learned from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def inv_mix_columns(s):
# see Sec 4.1.3 in The Design of Rijndael
for i in range(4):
u = xtime(xtime(s[i][0] ^ s[i][2]))
v = xtime(xtime(s[i][1] ^ s[i][3]))
s[i][0] ^= u
s[i][1] ^= v
s[i][2] ^= u
s[i][3] ^= v
mix_columns(s)
def bytes2matrix(text):
""" Converts a 16-byte array into a 4x4 matrix. """
print([list(text[i:i+4]) for i in range(0, len(text), 4)])
return [list(text[i:i+4]) for i in range(0, len(text), 4)]
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
# rows = len(matrix)
# columns = len(matrix[0]) #取第一行的元素取长度
str = ""
print(333,matrix)
for i in range(4):
for j in range(4):
str += chr(matrix[i][j])
return str
#原文
def expand_key(master_key):
"""
Expands and returns a list of key matrices for the given master_key.
"""
# Round constants https://en.wikipedia.org/wiki/AES_key_schedule#Round_constants
r_con = (
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
)
# Initialize round keys with raw key material.
key_columns = bytes2matrix(master_key)
iteration_size = len(master_key) // 4
# Each iteration has exactly as many columns as the key material.
i = 1
while len(key_columns) < (N_ROUNDS + 1) * 4:
# Copy previous word.
word = list(key_columns[-1])
# Perform schedule_core once every "row".
if len(key_columns) % iteration_size == 0:
# Circular shift.
word.append(word.pop(0))
# Map to S-BOX.
word = [s_box[b] for b in word]
# XOR with first byte of R-CON, since the others bytes of R-CON are 0.
word[0] ^= r_con[i]
i += 1
elif len(master_key) == 32 and len(key_columns) % iteration_size == 4:
# Run word through S-box in the fourth iteration when using a
# 256-bit key.
word = [s_box[b] for b in word]
# XOR with equivalent word from previous iteration.
word = bytes(i^j for i, j in zip(word, key_columns[-iteration_size]))
key_columns.append(word)
# Group key words in 4x4 byte matrices.
return [key_columns[4*i : 4*(i+1)] for i in range(len(key_columns) // 4)]
def decrypt(key, ciphertext):
round_keys = expand_key(key) # Remember to start from the last round key and work backwards through them when decrypting
# Convert ciphertext to state matrix
cipher = bytes2matrix(ciphertext)
print(cipher)
# Initial add round key step
#传入当前状态和当前轮密钥
#因为N_ROUNDS = 10 当前轮次是10 取keys[10]
add_round_key(cipher,round_keys[10])
print(1)
for i in range(N_ROUNDS - 1, 0, -1):
#每一轮的解密 除了最后一轮
inv_shift_rows(cipher)
print(111,cipher)
inv_sub_bytes(cipher)
print(222,cipher)
add_round_key(cipher,round_keys[i])
inv_mix_columns(cipher)
# Run final round (skips the InvMixColumns step)
inv_shift_rows(cipher)
inv_sub_bytes(cipher)
add_round_key(cipher,round_keys[0])
# Convert state matrix to plaintext
plaintext = matrix2bytes(cipher)
return plaintext
print(decrypt(key, ciphertext))
#crypto{M*********8}
SYMMETERIC STARTER
Modes of Operation Starter
首先访问代码中提供的接口获得密文
https://aes.cryptohack.org//block_cipher_starter/encrypt_flag/
访问另一个api 得到plaintext
ciphertext | “24e49b0a571db106b3392b0dc7b422b6d284081583603de51865f289806d855a” |
---|---|
plaintext | “63727970746f7b626c30636b5f633170683372355f3472335f663435375f217d” |
因为明文输出有hex加密 直接用界面的解一下OK
crypto{bl0**********57_!}
Passwords as Keys
首先获得密文
ciphertext | “c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66” |
---|
想要获得flag 还需要知道password_hash
根据题目提示我们可以访问拿到密码本
复制粘贴到本地
本来想直接在python中请求
from Crypto.Cipher import AES
import hashlib
import random
import requests #request函数库
#相对路径读文件
with open("Cryptohack/password.txt") as f:
words = [w.strip() for w in f.readlines()]
def re(KEY):
url = "https://aes.cryptohack.org/passwords_as_keys/decrypt"
ciphertext = "c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66"
url+="/"
url+=ciphertext
url+="/"
url+=KEY.hex()
print(url)
r=requests.get(url)#post传递,若是get就get传递
print(url)
if b"cry" in r.json():
print("\n[*] result:\n"+r.json()) #输出结果
for i in words:
print(i)
KEY = hashlib.md5(i.encode()).digest()
print(KEY)
re(KEY)
print(6)
但是不知道为什么没跑出来 我直接访问生成的url是可以访问成功的 但是在python里面就不行
所以直接本地调用网站的解密方法
from Crypto.Cipher import AES
import hashlib
import random
import requests #request函数库
#相对路径读文件
with open("Cryptohack/password.txt") as f:
words = [w.strip() for w in f.readlines()]
ciphertext = "c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66"
# @chal.route('/passwords_as_keys/decrypt/<ciphertext>/<password_hash>/')
def decrypt(ciphertext, password_hash):
ciphertext = bytes.fromhex(ciphertext)
key = password_hash
cipher = AES.new(key, AES.MODE_ECB)
try:
decrypted = cipher.decrypt(ciphertext)
except ValueError as e:
return {"error": str(e)}
return decrypted
for i in words:
#对密码本的每个数据进行爆破
KEY = hashlib.md5(i.encode()).digest()
str = decrypt(ciphertext,KEY)
if b"crypto{" in str:
print(str)
#b'crypto{*********}'
BLOCK CIPHERS
Flipping Cookie
题目目标:生成amdin=True的cookie 以及其iv
仔细分析一下cookie的组成
def get_cookie():
expires_at = (datetime.today() + timedelta(days=1)).strftime("%s")
cookie = f"admin=False;expiry={expires_at}".encode()
iv = os.urandom(16)
padded = pad(cookie, 16) #填充长度为16的整数倍
cipher = AES.new(KEY, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(padded)
ciphertext = iv.hex() + encrypted.hex() #iv长度是16 enc中的16位包括admin=False;expi正好16位 后面的随意
return {"cookie": ciphertext}
CBC加密模式:
P1 = d(C1) ^ IV
P2 = d(C2) ^ C1
P3 = d(C3) ^ C2
感觉思路还是很闭塞 这个问题的突破点应该在有AES中CBC的加密解密模式吧
在网上找到一篇好文:https://www.packetmania.net/2020/12/01/AES-CBC-PaddingOracleAttack/
所以进行操作
主要目的是让其最后解密的时候存在admin=True
构建当前值16位
补充伪造值16位
通过异或算法 实现最终解密的传输
exp:
from Crypto.Util.number import *
cookie = "26f375f84ae4439ff698ba001dcc2e97a67973306c5c1085ce0764b3826e0ae34d74677f40fd84f2d527164b6a979edd"
cookie = bytes.fromhex(cookie)
def xor(a, b):
return long_to_bytes(bytes_to_long(a) ^ bytes_to_long(b))
#密文块
origin = b'admin=False;expi'
goal = b'admin=True;expi\x01' #用于填充字符到16位 填充1位 所以用\x01
#因为缺少5位数 所以用\x05填充b'admin=True;\x05\x05\x05\x05\x05'
iv = cookie[:16]
#enc中的16位包括admin=False;expi正好16位 对应的密文
block1 = cookie[16:32]
cipher = xor(origin,goal)
new_iv = xor(cipher, iv)
print(block1.hex(), new_iv.hex()) #整个的异或流程 此时block1作为密文 new_iv作为初始向量
#经过CBC会对该块进行异或 block1 ^ new_iv = block1 ^ orign ^ goal ^ iv 其中orign与iv异或得到block1 block1与自身异或抵消 剩下的只有goal!
#a67973306c5c1085ce0764b3826e0ae3 26f375f84ae4518cef8ee45e00c437ff
我是哈皮!祝您每天嗨皮,我们下期再见~