1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| from typing import List
sbox = [75, 203, 236, 186, 19, 102, 179, 172, 92, 254, 54, 41, 124, 49, 195, 32, 191, 103, 157, 2, 128, 3, 156, 58, 159, 169, 189, 71, 168, 127, 109, 18, 232, 144, 40, 164, 192, 182, 181, 14, 204, 56, 226, 43, 206, 74, 129, 248, 11, 53, 72, 210, 33, 215, 250, 91, 161, 183, 239, 143, 167, 63, 152, 126, 48, 84, 146, 76, 234, 180, 107, 227, 142, 65, 147, 209, 89, 188, 225, 110, 116, 24, 150, 216, 45, 115, 95, 135, 36, 101, 138, 199, 69, 55, 86, 241, 59, 16, 83, 114, 39, 200, 151, 125, 8, 177, 198, 145, 247, 237, 171, 21, 136, 184, 185, 117, 242, 111, 119, 174, 28, 96, 246, 131, 10, 231, 130, 46, 104, 208, 38, 187, 218, 122, 139, 80, 79, 235, 64, 47, 238, 99, 140, 163, 90, 30, 252, 93, 173, 31, 249, 7, 9, 155, 230, 42, 82, 205, 57, 148, 240, 133, 0, 178, 165, 17, 213, 20, 222, 50, 221, 97, 137, 176, 243, 25, 113, 175, 220, 224, 118, 12, 166, 141, 202, 51, 61, 193, 158, 245, 134, 123, 211, 196, 1, 4, 244, 253, 22, 108, 201, 223, 73, 228, 212, 27, 78, 60, 153, 207, 219, 85, 88, 197, 121, 120, 70, 6, 233, 162, 105, 100, 112, 229, 214, 81, 23, 44, 13, 67, 15, 98, 37, 170, 149, 62, 132, 190, 251, 34, 217, 87, 29, 35, 68, 194, 5, 255, 52, 160, 66, 94, 26, 154, 77, 106]
inv_sbox = [0]*256 for i,v in enumerate(sbox): inv_sbox[v]=i
def xor_bytes(a: bytes, b: bytes) -> List[int]: return [x^y for x,y in zip(a,b)]
def generate_ks(key: bytes): ks = [key[:4], key[4:8], key[8:12], key[12:]] for i in range(16*4): nk = 0 for j in range(4): nk = int.from_bytes(ks[i+j],'big') ^ (3377808869 * nk % (1<<32)) ks.append(nk.to_bytes(4,'little')) return ks
def build_mix_matrix(): b = [10, 13, 3, 11, 7, 9, 0, 15, 5, 12, 8, 4, 6, 14, 2, 1] M = [[0]*16 for _ in range(16)] for i in range(4): for j in range(4): for k in range(4): row = 4*i + j col = j + 4*k M[row][col] = (M[row][col] + b[4*i+k]) % 256 return M
def mat_vec_mul(M, v): return [sum((M[i][j]*v[j] for j in range(16)))%256 for i in range(16)]
def mat_inv_mod256(M): n = len(M) A = [[M[i][j] % 256 for j in range(n)] + [1 if i==j else 0 for j in range(n)] for i in range(n)] def egcd(a,b): if b==0: return (a,1,0) g,x1,y1 = egcd(b, a%b) return (g, y1, x1 - (a//b)*y1) for col in range(n): pivot = None for r in range(col, n): if A[r][col] % 2 == 1: pivot = r break if pivot is None: raise ValueError("Matrix not invertible mod 256") if pivot != col: A[col], A[pivot] = A[pivot], A[col] inv = pow(A[col][col], -1, 256) for j in range(2*n): A[col][j] = (A[col][j] * inv) % 256 for r in range(n): if r==col: continue factor = A[r][col] if factor: for j in range(col, 2*n): A[r][j] = (A[r][j] - factor * A[col][j]) % 256 invM = [[A[i][j+n] for j in range(n)] for i in range(n)] return invM
M = build_mix_matrix() M_inv = mat_inv_mod256(M)
def invert_bit_permutation(word_bytes: bytes, i_index: int) -> bytes: d = i_index + 3 out_int = int.from_bytes(word_bytes, 'big') c = bin(out_int)[2:].zfill(32) c1, c2 = 32//d, 32%d b_parts = ['']*d pos = 0 for j in range(c1+1): for k in range(d): if len(b_parts[k]) < (c1+1 if k < c2 else c1): b_parts[k] += c[pos] pos += 1 a = ''.join(b_parts) orig_int = int(a,2) orig_bytes = orig_int.to_bytes(4, 'little') return orig_bytes
def decrypt_block(cipher_block: bytes, ks, iv_prev: bytes): m = list(cipher_block) for loop in reversed(range(16)): round_key = b''.join(ks[4*(loop+1):4*(loop+2)]) m = xor_bytes(bytes(m), round_key) if loop < 15: m = mat_vec_mul(M_inv, m) newm = [0]*16 for i in range(4): word_out = bytes(m[4*i:4*i+4]) orig = invert_bit_permutation(word_out, i) for j in range(4): newm[4*i+j] = orig[j] m = newm m = [inv_sbox[byte] for byte in m] m = xor_bytes(bytes(m), b''.join(ks[:4])) m = xor_bytes(bytes(m), iv_prev) return bytes(m)
what = b'www.bilibili.com/video/BV1ox4y1e71S' key, iv = what[:16], what[-16:] cipher_hex = "aa624dc4a26a879cbdc61585e1c92650d5d84c9195508d73172008e3bf1cf6edfa5eb1d1590b0de1424a563c91aeb5d8" cipher = bytes.fromhex(cipher_hex)
ks = generate_ks(key)
plain = b'' block_count = len(cipher)//16 prev_iv = iv for i in range(block_count): cblock = cipher[16*i:16*(i+1)] dec = decrypt_block(cblock, ks, prev_iv) plain += dec prev_iv = cblock
print("decrypted (raw):", plain)
pad_len = plain[-1] print("pad_len:", pad_len) print("plaintext:", plain[:-pad_len])
|