【密码学】一文读懂白盒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盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
5325 0
【密码学】一文读懂XTS模式
【密码学】一文读懂SHAMIR门限方案
【密码学】一文读懂SHAMIR门限方案
1409 0
【密码学】一文读懂SHAMIR门限方案
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1290 0
【密码学】一文读懂XTEA加密
|
存储 算法 数据安全/隐私保护
【密码学】一文读懂白盒AES(Chow方案)(一)
本文主要参考了文献^[1], 代码参考了^[2], 这里感谢文献作者和代码作者,如果有能力的大佬,可以自行查看原文献,个人水平有限,有哪里写的不对的地方,也欢迎读者指正。
3669 0
【密码学】一文读懂白盒AES(Chow方案)(一)
|
3月前
|
安全 算法 数据安全/隐私保护
深度揭秘!Python加密技术的背后,AES与RSA如何守护你的数据安全
【9月更文挑战第10天】随着数字化时代的到来,数据安全成为企业和个人面临的重大挑战。Python 作为功能强大的编程语言,在数据加密领域扮演着重要角色。AES 和 RSA 是两种主流加密算法,分别以对称和非对称加密方式保障数据安全。AES(Advanced Encryption Standard)因其高效性和安全性,在数据加密中广泛应用;而 RSA 则利用公钥和私钥机制,在密钥交换和数字签名方面表现卓越。
88 3
|
算法 安全 Go
【密码学】一文读懂HKDF
我这又来水一篇文章,来聊一下HKDF(基于HMAC的密钥导出函数)。密钥派生函数是密钥管理的组成部分,他的目标是通过一些初始的数据派生出来密码学安全的随机密钥。
3142 1
【密码学】一文读懂HKDF
|
7月前
|
算法 安全 量子技术
构建未来:量子计算机在加密破解中的应用展望
【5月更文挑战第17天】 随着量子计算的不断进步,其对传统加密技术构成的潜在威胁已成为信息安全领域关注的焦点。本文将深入探讨量子计算机如何利用其独特的计算优势破解现有加密算法,同时概述了抗量子密码学的发展趋势和挑战,旨在为未来的加密技术提供前瞻性的安全策略。
|
7月前
|
安全 算法 网络安全
构建未来:量子计算在加密破解中的应用展望
随着量子信息科学的迅猛发展,量子计算技术已逐渐从理论走向实践。本文旨在探讨量子计算对传统加密算法的冲击及其在未来加密破解领域的应用潜力。通过分析量子计算的基本原理和目前的技术进展,我们着重讨论了量子计算机如何处理复杂的数学问题,以及它如何能够在理论上破解广泛使用的公钥加密体系。文章还提出了针对量子计算威胁下的加密策略调整建议,为未来的信息安全布局提供参考。
255 1
|
7月前
|
存储 算法 安全
软件体系结构 - 对称加密算法
软件体系结构 - 对称加密算法
45 0
|
算法 安全 Java
常用密码学算法及其工程实践
在工程实践中,加解密算法、单向散列函数、消息认证码、数字签名等密码学内容经常出现。由于我之前对密码学一知半解,经常有摸不着头脑的情况。 比如我遇到过以下两种情况,我相信很多对密码学不熟悉的同学可能也有跟我一样的疑惑: 情况一,同样的明文,同样的密钥,每次加密生成的密文居然不一样?不一样的密文为什么能解密为同样的明文?我在开发友盟+数擎一体机时,在加密数据库中发现了这样的情况,当时非常不理解。
645 0
常用密码学算法及其工程实践