【密码学】一文读懂白盒AES(Chow方案)(二)

简介: 本文主要参考了文献^[1], 代码参考了^[2], 这里感谢文献作者和代码作者,如果有能力的大佬,可以自行查看原文献,个人水平有限,有哪里写的不对的地方,也欢迎读者指正。

白盒AES的实现


经过前面知识的铺垫,接下来到了重点,本文只介绍Chow的白盒的实现方法,首先来看一下上面的那个查表有什么问题,考虑到Tboxes/TyiTables是存有密钥的,根据文献当中的image.png

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, 然后得到一个新的表:

image.png

如果是要保护两个表,比如R和T, 那么可以找三个双射函数, f、h、g, 然后按照如下构造:

image.png

混合双射

这里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的白盒方案,相比于黑盒加密,这个方式即使攻击者可以追踪算法的任意流程,也无法在有效时间内提取出来密钥, 不过本文介绍的方案实际上也是存在可以提取出来密钥的,这一块就不在本文进行描述了,有兴趣的大佬可以自行查阅相关资料。

相关文章
|
存储 Rust 并行计算
【密码学】一文读懂XTS模式
这篇文章的灵感来源于我偶然翻到的一个某U盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
5107 0
【密码学】一文读懂XTS模式
【密码学】一文读懂SHAMIR门限方案
【密码学】一文读懂SHAMIR门限方案
1370 0
【密码学】一文读懂SHAMIR门限方案
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1265 0
【密码学】一文读懂XTEA加密
|
存储 算法 数据安全/隐私保护
【密码学】一文读懂白盒AES(Chow方案)(一)
本文主要参考了文献^[1], 代码参考了^[2], 这里感谢文献作者和代码作者,如果有能力的大佬,可以自行查看原文献,个人水平有限,有哪里写的不对的地方,也欢迎读者指正。
3586 0
【密码学】一文读懂白盒AES(Chow方案)(一)
|
2月前
|
存储 安全 数据库
双重防护,无懈可击!Python AES+RSA加密方案,构建最强数据安全堡垒
【9月更文挑战第11天】在数字时代,数据安全至关重要。AES与RSA加密技术相结合,构成了一道坚固防线。AES以其高效性保障数据加密,而RSA则确保密钥安全传输,二者相辅相成,提供双重保护。本文通过Python代码示例展示了这一加密方案的魅力,强调了其在实际应用中的重要性和安全性。使用HTTPS等安全协议传输加密密钥和密文,确保数据在数字世界中自由流通而无忧。
60 1
|
4月前
|
搜索推荐 安全 网络安全
AES 加密解密技术原理模式和实践
AES (Advanced Encryption Standard), aka Rijndael, is a symmetric encryption algorithm offering high security and speed over DES.
|
6月前
|
存储 算法 安全
软件体系结构 - 对称加密算法
软件体系结构 - 对称加密算法
40 0
|
6月前
|
安全 算法 网络安全
软件体系结构 - 非对称加密算法
软件体系结构 - 非对称加密算法
57 0
|
算法 安全 Java
常用密码学算法及其工程实践
在工程实践中,加解密算法、单向散列函数、消息认证码、数字签名等密码学内容经常出现。由于我之前对密码学一知半解,经常有摸不着头脑的情况。 比如我遇到过以下两种情况,我相信很多对密码学不熟悉的同学可能也有跟我一样的疑惑: 情况一,同样的明文,同样的密钥,每次加密生成的密文居然不一样?不一样的密文为什么能解密为同样的明文?我在开发友盟+数擎一体机时,在加密数据库中发现了这样的情况,当时非常不理解。
625 0
常用密码学算法及其工程实践
|
定位技术
【密码学】一文读懂零知识证明
本文来聊一聊零知识证明的一点知识, 本文的例子纯属虚构,故事素材来源于网络和论文,以及我的瞎编, 如有雷同, 纯属巧合。
【密码学】一文读懂零知识证明