白盒AES的实现
经过前面知识的铺垫,接下来到了重点,本文只介绍Chow的白盒的实现方法,首先来看一下上面的那个查表有什么问题,考虑到Tboxes/TyiTables是存有密钥的,根据文献当中的。
fn attack_table(n: u32, i: usize) -> u8 { let ty: [[[u8; 4]; 256]; 4] = calculate_ty(); let v0 = (n >> 24 & 0xFF) as u8; let v1 = (n >> 16 & 0xFF) as u8; let v2 = (n >> 8 & 0xFF) as u8; let v3 = (n >> 0 & 0xFF) as u8; let state = [v0, v1, v2, v3]; for x in 0..=255 { if state[i] == ty[i][x][i] { let inv = x; return INV_SBOX[((inv >> 4) & 0xF) as usize][(inv & 0xF) as usize] as u8; } } return 0; } // test code fn test_attack() { let key = [43, 126, 21, 22, 40, 174, 210, 166, 171, 247, 21, 136, 9, 207, 79, 60]; let w = expend_keys(&key, 4, 10); let t_boxes = calculate_t_boxes(&w); for i in 0..16 { let inv = t_boxes[0][i][0]; let result = INV_SBOX[((inv >> 4) & 0xF) as usize][(inv & 0xF) as usize] as u8; print!("{:?}, ", result); } print!("\n"); let (ty_boxes, _) = calculate_ty_boxes(&w); let mut result = [0u8; 16]; for i in 0..16 { let x = ty_boxes[0][i][0]; let key = attack_table(x, i % 4); result[i] = key; } println!("{:?}", result); }
Encodings
因为原始的TyTboxes是不安全的,从上面的方法可以直接拿到密钥,因此Chow的方案当中对于TyTboxes进行了一次输入和输出编码。为了保护T表,可以选择两个双射函数f和g, 然后得到一个新的表:
如果是要保护两个表,比如R和T, 那么可以找三个双射函数, f、h、g, 然后按照如下构造:
混合双射
这里Chow的方案采用了一个可逆的线性变换,这个被称作混合双射, 通俗点说,这个选择一个GF(2)上面的一个可逆的随机矩阵,这个变换对于第2到第9轮都是一致的,具体过程如下:
- 对于第2到第9轮,选择16个 8bit -> 8bit的 混合双射,这个作为T盒的输入编码
- 对于第1到第9轮,选择4个 32bit -> 32bit的混合双射,这个作为Ty table的输出编码。
至于为什么需要这么做,其实也比较好理解,观察上面的Encoding函数,如果第一轮也做一个输入编码,那么相比于原始的输入就多了一次变换,如果最后一轮如果做混合双射之后,那么最后的结果也就变了。
由于rust没有找到比较好用的GF(2)上面运算的库,然后我使用rust调用c++的ntl的时候搞失败了,蓝瘦香菇,所以还是采用我所参考的代码https://github.com/balena/aes-whitebox当中的方案,直接也用c++来跟着实现一下,这里我简化了一下上面参考代码的逻辑,核心代码和参考代码基本一致,在这里再次感谢一下这个代码的作者。如果有大佬用rust调用ntl成功了,欢迎和我讨论交流。
代码实现
#include <iostream> #include <NTL/mat_GF2.h> #include "log.h" constexpr uint8_t SBOX[16][16] = { {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} }; constexpr int SHIFT_ROWS_TAB[16] = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11, }; constexpr int InvShiftRowsTab[16] = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3, }; template<typename T> inline NTL::vec_GF2 from_scalar(T in); template<> inline NTL::vec_GF2 from_scalar(uint8_t in) { NTL::vec_GF2 result; result.SetLength(8); for (int i = 0; i < 8; i++) { result[7 - i] = ((in >> i) & 1); } return result; } template<> inline NTL::vec_GF2 from_scalar(uint32_t in) { NTL::vec_GF2 result; result.SetLength(32); for (int i = 0; i < 32; i++) { result[31 - i] = ((in >> i) & 1); } return result; } template<typename T> inline T to_scalar(const NTL::vec_GF2 &in); template<> inline uint8_t to_scalar(const NTL::vec_GF2 &in) { uint8_t result = 0; for (int i = 0; i < 2; i++) { long i0 = NTL::rep(in[i * 4 + 0]), i1 = NTL::rep(in[i * 4 + 1]), i2 = NTL::rep(in[i * 4 + 2]), i3 = NTL::rep(in[i * 4 + 3]); result = (result << 4) | (i0 << 3) | (i1 << 2) | (i2 << 1) | (i3 << 0); } return result; } template<> inline uint32_t to_scalar(const NTL::vec_GF2 &in) { uint32_t result = 0; for (int i = 0; i < 8; i++) { long i0 = NTL::rep(in[i * 4 + 0]), i1 = NTL::rep(in[i * 4 + 1]), i2 = NTL::rep(in[i * 4 + 2]), i3 = NTL::rep(in[i * 4 + 3]); result = (result << 4) | (i0 << 3) | (i1 << 2) | (i2 << 1) | (i3 << 0); } return result; } template<typename T> inline T mul(const NTL::mat_GF2 &mat, T x) { return to_scalar<T>(mat * from_scalar<T>(x)); } NTL::mat_GF2 GenerateGF2RandomMatrix(int dimension) { NTL::mat_GF2 mat(NTL::INIT_SIZE, dimension, dimension); for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { mat[i][j] = NTL::random_GF2(); } } return mat; } NTL::mat_GF2 GenerateRandomGF2InvertibleMatrix(int dimension) { for (;;) { NTL::mat_GF2 result = GenerateGF2RandomMatrix(dimension); if (NTL::determinant(result) != 0) return result; } } inline void add_round_key(uint8_t state[16], const uint32_t round_key[4]) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { state[i * 4 + j] ^= round_key[i] >> ((3 - j) * 8); } } void add_round_key_after_shift(uint8_t state[16], const uint32_t round_key[4]) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[i * 4 + j] ^= round_key[(j + i) % 4] >> ((3 - j) * 8); } } } void sub_bytes(uint8_t state[16]) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[i * 4 + j] = SBOX[state[i * 4 + j] >> 4][state[i * 4 + j] & 0x0F]; } } } void shift_rows(uint8_t state[16]) { uint8_t shifts[16] = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11, }; const uint8_t in[16] = { state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7], state[8], state[9], state[10], state[11], state[12], state[13], state[14], state[15], }; for (int i = 0; i < 16; i++) { state[i] = in[shifts[i]]; } } void calculate_t_boxes(const uint32_t round_key[44], uint8_t t_boxes[10][16][256]) { for (int r = 0; r < 10; ++r) { for (int x = 0; x < 256; ++x) { uint8_t state[16] = { (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x, (uint8_t) x }; add_round_key_after_shift(state, &round_key[4 * r]); sub_bytes(state); if (r == 9) { add_round_key(state, &round_key[40]); } for (int i = 0; i < 16; ++i) { t_boxes[r][i][x] = state[i]; } } } } uint8_t gmul(uint8_t ap, uint8_t bp) { uint8_t a = ap, b = bp, p = 0; while (a != 0 && b != 0) { if (b & 1) { p ^= a; } if (a & 0x80) { a = (a << 1) ^ 0x11b; } else { a = a << 1; } b >>= 1; } return p; } void calculate_ty(uint8_t ty[4][256][4]) { for (int x = 0; x < 256; ++x) { ty[0][x][0] = gmul(x, 2); ty[0][x][1] = gmul(x, 3); ty[0][x][2] = x; ty[0][x][3] = x; ty[1][x][0] = x; ty[1][x][1] = gmul(x, 2); ty[1][x][2] = gmul(x, 3); ty[1][x][3] = x; ty[2][x][0] = x; ty[2][x][1] = x; ty[2][x][2] = gmul(x, 2); ty[2][x][3] = gmul(x, 3); ty[3][x][0] = gmul(x, 3); ty[3][x][1] = x; ty[3][x][2] = x; ty[3][x][3] = gmul(x, 2); } } void calculate_ty_boxes(uint32_t round_key[44], uint32_t ty_boxes[10][16][256], uint8_t t_boxes_last[16][256], uint32_t MBL[10][16][256]) { uint8_t t_boxes[10][16][256]; uint8_t ty[4][256][4]; calculate_t_boxes(round_key, t_boxes); calculate_ty(ty); for (int r = 0; r < 9; ++r) { for (int x = 0; x < 256; ++x) { for (int j = 0; j < 4; ++j) { for (int i = 0; i < 4; ++i) { uint32_t v0 = ty[0][t_boxes[r][j * 4 + i][x]][i], v1 = ty[1][t_boxes[r][j * 4 + i][x]][i], v2 = ty[2][t_boxes[r][j * 4 + i][x]][i], v3 = ty[3][t_boxes[r][j * 4 + i][x]][i]; ty_boxes[r][j * 4 + i][x] = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; MBL[r][j * 4 + i][x] = x << ((3 - i) << 3); } } } } for (int x = 0; x < 256; ++x) { for (int i = 0; i < 16; ++i) { t_boxes_last[i][x] = t_boxes[9][i][x]; } } // region MBL NTL::mat_GF2 MB[9][4]; for (auto &r : MB) { for (auto &i : r) { i = GenerateRandomGF2InvertibleMatrix(32); } } for (int r = 0; r < 9; r++) { for (int x = 0; x < 256; x++) { for (int i = 0; i < 16; i++) { ty_boxes[r][i][x] = mul<uint32_t>(MB[r][i >> 2], ty_boxes[r][i][x]); MBL[r][i][x] = mul<uint32_t>(NTL::inv(MB[r][i >> 2]), MBL[r][i][x]); } } } NTL::mat_GF2 L[9][16]; for (auto &r: L) { for (auto &i: r) { i = GenerateRandomGF2InvertibleMatrix(8); } } for (int r = 0; r < 9; ++r) { if (r > 0) { for (int i = 0; i < 16; ++i) { uint32_t copy_ty_boxes[256]; for (int x = 0; x < 256; ++x) { copy_ty_boxes[x] = ty_boxes[r][i][x]; } for (int x = 0; x < 256; ++x) { ty_boxes[r][i][x] = copy_ty_boxes[mul<uint8_t>(NTL::inv(L[r - 1][i]), x)]; } } } for (int j = 0; j < 4; ++j) { for (int x = 0; x < 256; ++x) { uint32_t out0 = MBL[r][j * 4 + 0][x]; uint32_t out1 = MBL[r][j * 4 + 1][x]; uint32_t out2 = MBL[r][j * 4 + 2][x]; uint32_t out3 = MBL[r][j * 4 + 3][x]; MBL[r][j * 4 + 0][x] = (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 0]], out0 >> 24) << 24) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 1]], out0 >> 16) << 16) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 2]], out0 >> 8) << 8) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 3]], out0 >> 0) << 0); MBL[r][j * 4 + 1][x] = (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 0]], out1 >> 24) << 24) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 1]], out1 >> 16) << 16) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 2]], out1 >> 8) << 8) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 3]], out1 >> 0) << 0); MBL[r][j * 4 + 2][x] = (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 0]], out2 >> 24) << 24) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 1]], out2 >> 16) << 16) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 2]], out2 >> 8) << 8) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 3]], out2 >> 0) << 0); MBL[r][j * 4 + 3][x] = (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 0]], out3 >> 24) << 24) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 1]], out3 >> 16) << 16) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 2]], out3 >> 8) << 8) | (mul<uint8_t>(L[r][InvShiftRowsTab[j * 4 + 3]], out3 >> 0) << 0); } } } for (int i = 0; i < 16; i++) { uint8_t copy_ty_boxes_last[256]; for (int x = 0; x < 256; x++) { copy_ty_boxes_last[x] = t_boxes_last[i][x]; } for (int x = 0; x < 256; x++) { t_boxes_last[i][x] = copy_ty_boxes_last[mul<uint8_t>(NTL::inv(L[8][i]), x)]; } } // endregion } void calculate_xor_table(uint8_t xor_tab[9][96][16][16]) { for (int r = 0; r < 9; ++r) { for (int n = 0; n < 96; ++n) { for (int i = 0; i < 16; ++i) { for (int j = 0; j < 16; ++j) { xor_tab[r][n][i][j] = i ^ j; } } } } } // 这里只是加密一个分组, 链接模式也不实现了 void encrypt( uint8_t in[16], uint8_t xor_table[9][96][16][16], uint32_t ty_boxes[10][16][256], uint8_t t_boxes_last[16][256], uint32_t MBL[10][16][256] ) { for (int r = 0; r < 9; r++) { shift_rows(in); for (int j = 0; j < 4; ++j) { uint8_t n0, n1, n2, n3; uint32_t aa, bb, cc, dd; aa = ty_boxes[r][j * 4 + 0][in[j * 4 + 0]], bb = ty_boxes[r][j * 4 + 1][in[j * 4 + 1]], cc = ty_boxes[r][j * 4 + 2][in[j * 4 + 2]], dd = ty_boxes[r][j * 4 + 3][in[j * 4 + 3]]; n0 = xor_table[r][j * 24 + 0][(aa >> 28) & 0xf][(bb >> 28) & 0xf]; n1 = xor_table[r][j * 24 + 1][(cc >> 28) & 0xf][(dd >> 28) & 0xf]; n2 = xor_table[r][j * 24 + 2][(aa >> 24) & 0xf][(bb >> 24) & 0xf]; n3 = xor_table[r][j * 24 + 3][(cc >> 24) & 0xf][(dd >> 24) & 0xf]; in[j * 4 + 0] = (xor_table[r][j * 24 + 4][n0][n1] << 4) | xor_table[r][j * 24 + 5][n2][n3]; n0 = xor_table[r][j * 24 + 6][(aa >> 20) & 0xf][(bb >> 20) & 0xf]; n1 = xor_table[r][j * 24 + 7][(cc >> 20) & 0xf][(dd >> 20) & 0xf]; n2 = xor_table[r][j * 24 + 8][(aa >> 16) & 0xf][(bb >> 16) & 0xf]; n3 = xor_table[r][j * 24 + 9][(cc >> 16) & 0xf][(dd >> 16) & 0xf]; in[j * 4 + 1] = (xor_table[r][j * 24 + 10][n0][n1] << 4) | xor_table[r][j * 24 + 11][n2][n3]; n0 = xor_table[r][j * 24 + 12][(aa >> 12) & 0xf][(bb >> 12) & 0xf]; n1 = xor_table[r][j * 24 + 13][(cc >> 12) & 0xf][(dd >> 12) & 0xf]; n2 = xor_table[r][j * 24 + 14][(aa >> 8) & 0xf][(bb >> 8) & 0xf]; n3 = xor_table[r][j * 24 + 15][(cc >> 8) & 0xf][(dd >> 8) & 0xf]; in[j * 4 + 2] = (xor_table[r][j * 24 + 16][n0][n1] << 4) | xor_table[r][j * 24 + 17][n2][n3]; n0 = xor_table[r][j * 24 + 18][(aa >> 4) & 0xf][(bb >> 4) & 0xf]; n1 = xor_table[r][j * 24 + 19][(cc >> 4) & 0xf][(dd >> 4) & 0xf]; n2 = xor_table[r][j * 24 + 20][(aa >> 0) & 0xf][(bb >> 0) & 0xf]; n3 = xor_table[r][j * 24 + 21][(cc >> 0) & 0xf][(dd >> 0) & 0xf]; in[j * 4 + 3] = (xor_table[r][j * 24 + 22][n0][n1] << 4) | xor_table[r][j * 24 + 23][n2][n3]; aa = MBL[r][j * 4 + 0][in[j * 4 + 0]]; bb = MBL[r][j * 4 + 1][in[j * 4 + 1]]; cc = MBL[r][j * 4 + 2][in[j * 4 + 2]]; dd = MBL[r][j * 4 + 3][in[j * 4 + 3]]; n0 = xor_table[r][j * 24 + 0][(aa >> 28) & 0xf][(bb >> 28) & 0xf]; n1 = xor_table[r][j * 24 + 1][(cc >> 28) & 0xf][(dd >> 28) & 0xf]; n2 = xor_table[r][j * 24 + 2][(aa >> 24) & 0xf][(bb >> 24) & 0xf]; n3 = xor_table[r][j * 24 + 3][(cc >> 24) & 0xf][(dd >> 24) & 0xf]; in[j * 4 + 0] = (xor_table[r][j * 24 + 4][n0][n1] << 4) | xor_table[r][j * 24 + 5][n2][n3]; n0 = xor_table[r][j * 24 + 6][(aa >> 20) & 0xf][(bb >> 20) & 0xf]; n1 = xor_table[r][j * 24 + 7][(cc >> 20) & 0xf][(dd >> 20) & 0xf]; n2 = xor_table[r][j * 24 + 8][(aa >> 16) & 0xf][(bb >> 16) & 0xf]; n3 = xor_table[r][j * 24 + 9][(cc >> 16) & 0xf][(dd >> 16) & 0xf]; in[j * 4 + 1] = (xor_table[r][j * 24 + 10][n0][n1] << 4) | xor_table[r][j * 24 + 11][n2][n3]; n0 = xor_table[r][j * 24 + 12][(aa >> 12) & 0xf][(bb >> 12) & 0xf]; n1 = xor_table[r][j * 24 + 13][(cc >> 12) & 0xf][(dd >> 12) & 0xf]; n2 = xor_table[r][j * 24 + 14][(aa >> 8) & 0xf][(bb >> 8) & 0xf]; n3 = xor_table[r][j * 24 + 15][(cc >> 8) & 0xf][(dd >> 8) & 0xf]; in[j * 4 + 2] = (xor_table[r][j * 24 + 16][n0][n1] << 4) | xor_table[r][j * 24 + 17][n2][n3]; n0 = xor_table[r][j * 24 + 18][(aa >> 4) & 0xf][(bb >> 4) & 0xf]; n1 = xor_table[r][j * 24 + 19][(cc >> 4) & 0xf][(dd >> 4) & 0xf]; n2 = xor_table[r][j * 24 + 20][(aa >> 0) & 0xf][(bb >> 0) & 0xf]; n3 = xor_table[r][j * 24 + 21][(cc >> 0) & 0xf][(dd >> 0) & 0xf]; in[j * 4 + 3] = (xor_table[r][j * 24 + 22][n0][n1] << 4) | xor_table[r][j * 24 + 23][n2][n3]; } } shift_rows(in); for (int i = 0; i < 16; i++) { in[i] = t_boxes_last[i][in[i]]; } } int main() { // 这里密钥固定了,不实现密钥扩展算法了,只保留最核心的功能 uint32_t w[44] = { 729683222, 682545830, 2885096840, 164581180, 2700803607, 2287217841, 597899577, 711751173, 4072838642, 2056698179, 1496678522, 1935275647, 1031817085, 1192689214, 505642564, 1836746811, 4014253377, 2823969663, 3060868411, 3674975488, 3570517752, 2089000327, 3404904636, 301536700, 1837671290, 285949693, 3690563137, 3389035517, 1314191118, 1600113139, 2225491890, 1319558223, 3939660577, 3045964498, 824964448, 2139957551, 2893506291, 435870753, 684796225, 1465647214, 3491035560, 3387827593, 3779005640, 3059944614 }; uint8_t xor_table[9][96][16][16]; uint32_t ty_boxes[10][16][256]; uint8_t t_boxes_last[16][256]; uint32_t MBL[10][16][256]; calculate_xor_table(xor_table); calculate_ty_boxes(w, ty_boxes, t_boxes_last, MBL); uint8_t in[16] = {50, 67, 246, 168, 136, 90, 48, 141, 49, 49, 152, 162, 224, 55, 7, 52}; encrypt(in, xor_table, ty_boxes, t_boxes_last, MBL); PRINT_ARRAY("%x,", in, 16); return 0; }
总结
本文简单介绍了一下Chow的白盒方案,相比于黑盒加密,这个方式即使攻击者可以追踪算法的任意流程,也无法在有效时间内提取出来密钥, 不过本文介绍的方案实际上也是存在可以提取出来密钥的,这一块就不在本文进行描述了,有兴趣的大佬可以自行查阅相关资料。