CryptoHack详细题解 覆盖RSA AES 以及三道交互题~

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跑一下

image-20230914205239843

成功得到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盒的内容是从0x000xff

所以针对当前状态 找到对应值转换为字节即可

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密文

参考图片进行解密流程:

image-20230915165929950

在列表数据中对数据的传输有些模糊 写了一个小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

image-20230915180244694

crypto{bl0**********57_!}

Passwords as Keys

首先获得密文

ciphertext“c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66”

想要获得flag 还需要知道password_hash

根据题目提示我们可以访问拿到密码本

image-20230915191849547

复制粘贴到本地

本来想直接在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里面就不行

image-20230916002323235

image-20230916002344069

所以直接本地调用网站的解密方法

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加密模式:

image-20230915215856395

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

我是哈皮!祝您每天嗨皮,我们下期再见~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值