预处理器宏将十六进制字符串转换为字节数组

时间:2017-08-23 20:36:14

标签: c gcc macros c-preprocessor preprocessor

我在IDE中定义了一个AES-128密钥作为构建符号,因此它会像这样调用GCC:

arm-none-eabi-gcc -D"AES_KEY=3B7116E69E222295163FF1CAA1681FAC" ...

(相当于#define AES_KEY 3B7116E69E222295163FF1CAA1681FAC

优点是相同的符号也可以作为参数自动传递给构建后的CLI脚本,该脚本使用此密钥加密编译的代码(例如,用于安全的固件更新)...

但是如何将此密钥存储为字节数组  我的代码? 我想定义一个执行转换的预处理器宏:

uint8_t aes_key[] = { SPLIT_MACRO(AES_KEY) };

uint8_t aes_key[] = {0x3B, 0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, ...};

换句话说,GCC预处理器是否可以在2-char块中拆分密钥字符串并在它们之间添加“, 0x”?

2 个答案:

答案 0 :(得分:5)

有点笨拙,但如果您事先知道密钥的长度,可以按如下方式处理:

  1. 定义将十六进制数字转换为数字
  2. 的宏HEXTONIBBLE
  3. 定义一个宏HEXTOBYTE,使用HEXTONIBBLE从十六进制中获取字节
  4. 使用HEXTOBYTE参数化的correctrly
  5. 初始化您的数组

    如果你的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 
    

答案 1 :(得分:1)

这不能回答原始问题,但是如果密钥可以用这种格式编写:

#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);

请参阅ConcatenationArgument PrescanVariadic Macros