将十六进制字符串转换为字节数组的预处理器宏
Pre-processor macro to convert an hex string to a byte array
我在我的 IDE 中定义了一个 AES-128 密钥作为构建符号,因此它可以这样调用 GCC:
arm-none-eabi-gcc -D"AES_KEY=3B7116E69E222295163FF1CAA1681FAC" ...
(相当于#define AES_KEY 3B7116E69E222295163FF1CAA1681FAC
)
优点是相同的符号也可以作为参数自动传递给 post-build CLI 脚本,该脚本使用此密钥加密编译代码(例如,用于安全固件更新)...
但是如何将这个键存储为一个字节数组
我的代码?
我想定义一个进行转换的预处理器宏:
uint8_t aes_key[] = { SPLIT_MACRO(AES_KEY) };
到
uint8_t aes_key[] = {0x3B, 0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, ...};
换句话说,GCC 预处理器能否将密钥字符串拆分为 2 个字符的块并在它们之间添加“, 0x
”?
有点笨拙,但如果你事先知道密钥的长度,你可以按如下方式处理它:
- 定义一个将十六进制数字转换为数字的宏
HEXTONIBBLE
- 定义一个宏
HEXTOBYTE
,它使用HEXTONIBBLE
从十六进制中获取一个字节
- 使用
HEXTOBYTE
正确参数化 初始化您的数组
如果您的 KEY
不是字符串形式,即用双引号引起来,则使用 stringify-operator #
(使用可变参数宏来扩展用作参数或另一个时的宏):
// 01234567890123456789012345678901
#define K 3B7116E69E222295163FF1CAA1681FAC
#define STRINGIFY_HELPER(A) #A
#define STRINGIFY(...) STRINGIFY_HELPER(__VA_ARGS__)
#define KEY STRINGIFY(K)
#define HEXTONIBBLE(c) (*(c) >= 'A' ? (*(c) - 'A')+10 : (*(c)-'0'))
#define HEXTOBYTE(c) (HEXTONIBBLE(c)*16 + HEXTONIBBLE(c+1))
uint8_t aes_key[] = {
HEXTOBYTE(KEY+0),
HEXTOBYTE(KEY+2),
HEXTOBYTE(KEY+4),
HEXTOBYTE(KEY+6),
HEXTOBYTE(KEY+8),
HEXTOBYTE(KEY+10),
HEXTOBYTE(KEY+12),
HEXTOBYTE(KEY+14),
HEXTOBYTE(KEY+16),
HEXTOBYTE(KEY+18),
HEXTOBYTE(KEY+20),
HEXTOBYTE(KEY+22),
HEXTOBYTE(KEY+24),
HEXTOBYTE(KEY+26),
HEXTOBYTE(KEY+28),
HEXTOBYTE(KEY+30)
};
int main() {
for (int i=0; i<sizeof(aes_key); i++) {
printf("%02X ", aes_key[i]);
}
return 0;
}
输出:
3B 71 16 E6 9E 22 22 95 16 3F F1 CA A1 68 1F AC
这并没有回答原来的问题,但如果密钥可以用这种格式写成:
#define AES_KEY 3B,71,16,E6,9E,22,22,95,16,3F,F1,CA,A1,68,1F,AC
即使在 GCC 下,以下宏也可以工作:
#define BA(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) {0x##a,0x##b,0x##c,0x##d,\
0x##e,0x##f,0x##g,0x##h,0x##i,0x##j,0x##k,0x##l,0x##m,0x##n,0x##o,0x##p}
#define TO_BYTEARRAY(...) BA(__VA_ARGS__)
uint8_t aes_key[] = TO_BYTEARRAY(AES_KEY);
我在我的 IDE 中定义了一个 AES-128 密钥作为构建符号,因此它可以这样调用 GCC:
arm-none-eabi-gcc -D"AES_KEY=3B7116E69E222295163FF1CAA1681FAC" ...
(相当于#define AES_KEY 3B7116E69E222295163FF1CAA1681FAC
)
优点是相同的符号也可以作为参数自动传递给 post-build CLI 脚本,该脚本使用此密钥加密编译代码(例如,用于安全固件更新)...
但是如何将这个键存储为一个字节数组 我的代码? 我想定义一个进行转换的预处理器宏:
uint8_t aes_key[] = { SPLIT_MACRO(AES_KEY) };
到
uint8_t aes_key[] = {0x3B, 0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, ...};
换句话说,GCC 预处理器能否将密钥字符串拆分为 2 个字符的块并在它们之间添加“, 0x
”?
有点笨拙,但如果你事先知道密钥的长度,你可以按如下方式处理它:
- 定义一个将十六进制数字转换为数字的宏
HEXTONIBBLE
- 定义一个宏
HEXTOBYTE
,它使用HEXTONIBBLE
从十六进制中获取一个字节 - 使用
HEXTOBYTE
正确参数化 初始化您的数组
如果您的 KEY
不是字符串形式,即用双引号引起来,则使用 stringify-operator #
(使用可变参数宏来扩展用作参数或另一个时的宏):
// 01234567890123456789012345678901
#define K 3B7116E69E222295163FF1CAA1681FAC
#define STRINGIFY_HELPER(A) #A
#define STRINGIFY(...) STRINGIFY_HELPER(__VA_ARGS__)
#define KEY STRINGIFY(K)
#define HEXTONIBBLE(c) (*(c) >= 'A' ? (*(c) - 'A')+10 : (*(c)-'0'))
#define HEXTOBYTE(c) (HEXTONIBBLE(c)*16 + HEXTONIBBLE(c+1))
uint8_t aes_key[] = {
HEXTOBYTE(KEY+0),
HEXTOBYTE(KEY+2),
HEXTOBYTE(KEY+4),
HEXTOBYTE(KEY+6),
HEXTOBYTE(KEY+8),
HEXTOBYTE(KEY+10),
HEXTOBYTE(KEY+12),
HEXTOBYTE(KEY+14),
HEXTOBYTE(KEY+16),
HEXTOBYTE(KEY+18),
HEXTOBYTE(KEY+20),
HEXTOBYTE(KEY+22),
HEXTOBYTE(KEY+24),
HEXTOBYTE(KEY+26),
HEXTOBYTE(KEY+28),
HEXTOBYTE(KEY+30)
};
int main() {
for (int i=0; i<sizeof(aes_key); i++) {
printf("%02X ", aes_key[i]);
}
return 0;
}
输出:
3B 71 16 E6 9E 22 22 95 16 3F F1 CA A1 68 1F AC
这并没有回答原来的问题,但如果密钥可以用这种格式写成:
#define AES_KEY 3B,71,16,E6,9E,22,22,95,16,3F,F1,CA,A1,68,1F,AC
即使在 GCC 下,以下宏也可以工作:
#define BA(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) {0x##a,0x##b,0x##c,0x##d,\
0x##e,0x##f,0x##g,0x##h,0x##i,0x##j,0x##k,0x##l,0x##m,0x##n,0x##o,0x##p}
#define TO_BYTEARRAY(...) BA(__VA_ARGS__)
uint8_t aes_key[] = TO_BYTEARRAY(AES_KEY);