【密码学】一文读懂白盒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盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
4920 0
【密码学】一文读懂XTS模式
【密码学】一文读懂SHAMIR门限方案
【密码学】一文读懂SHAMIR门限方案
1338 0
【密码学】一文读懂SHAMIR门限方案
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1240 0
【密码学】一文读懂XTEA加密
|
存储 算法 数据安全/隐私保护
【密码学】一文读懂白盒AES(Chow方案)(一)
本文主要参考了文献^[1], 代码参考了^[2], 这里感谢文献作者和代码作者,如果有能力的大佬,可以自行查看原文献,个人水平有限,有哪里写的不对的地方,也欢迎读者指正。
3468 0
【密码学】一文读懂白盒AES(Chow方案)(一)
|
1月前
|
存储 安全 数据库
双重防护,无懈可击!Python AES+RSA加密方案,构建最强数据安全堡垒
【9月更文挑战第11天】在数字时代,数据安全至关重要。AES与RSA加密技术相结合,构成了一道坚固防线。AES以其高效性保障数据加密,而RSA则确保密钥安全传输,二者相辅相成,提供双重保护。本文通过Python代码示例展示了这一加密方案的魅力,强调了其在实际应用中的重要性和安全性。使用HTTPS等安全协议传输加密密钥和密文,确保数据在数字世界中自由流通而无忧。
54 1
|
3月前
|
搜索推荐 安全 网络安全
AES 加密解密技术原理模式和实践
AES (Advanced Encryption Standard), aka Rijndael, is a symmetric encryption algorithm offering high security and speed over DES.
|
5月前
|
算法 安全 量子技术
构建未来:量子计算机在加密破解中的应用展望
【5月更文挑战第17天】 随着量子计算的不断进步,其对传统加密技术构成的潜在威胁已成为信息安全领域关注的焦点。本文将深入探讨量子计算机如何利用其独特的计算优势破解现有加密算法,同时概述了抗量子密码学的发展趋势和挑战,旨在为未来的加密技术提供前瞻性的安全策略。
|
5月前
|
存储 算法 安全
软件体系结构 - 对称加密算法
软件体系结构 - 对称加密算法
37 0
|
5月前
|
安全 算法 网络安全
软件体系结构 - 非对称加密算法
软件体系结构 - 非对称加密算法
50 0
|
算法 安全 数据安全/隐私保护
【密码学】 一篇文章讲透数字签名
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。数字签名可以识别消息是否被篡改, 并验证消息的可靠性, 也可以防止否认。
704 0
【密码学】 一篇文章讲透数字签名