0

我正在深入sha1.c研究md5.c作者 Christophe Devine,以便在 WWW 上实现 AES 加密。大概测试服务器和客户端上的文件是相同的。但是,即使用于生成密钥的信息相同,我们生成的密钥也是不同的。

这两种方法的计算核心都在xxx_process(...). 两者都有一些宏观魔术。我想如果有人要努力编写宏,那么它应该做点什么。如果有人花时间编写一个宏函数,该函数的表达式用作另一个宏的输入,那么我认为它应该评估为某个确定性值。这不是我在调用中看到的P(a,b,c,d,e,x),什么时候R(t)传入 for x。我读错了吗?或者不R(t)计算为以下调用中的表达式?

P( B, C, D, E, A, R(19) );

#define P(a,b,c,d,e,x)                                  \
{                                                       \
    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
}

#define R(t)                                            \
(                                                       \
    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
    ( W[t & 0x0F] = S(temp,1) )                         \
)
4

1 回答 1

2

这些宏是不好的编程风格,但基本上扩展的结果R是一个表达式,是的。但是由于这个表达式依赖于W它不是一个常量表达式,如果那是你正在寻找的。

更合适的实现将同时使用和inline的函数。例如对于PRR

inline
tType R(tType t, WType W[]) {
  tType temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^
           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F];
  W[t & 0x0F] = S(temp,1);
}

在现代平台上,这应该会产生相同甚至更好的目标代码。它还具有易于调试的优点。

使用宏做这些事情的原因可能是它应该由具有较少优化功能的旧编译器编译。

的实现P非常糟糕,与是否为旧编译器编译无关:

  • 它用不是表达式或语句的东西替换了调用之类的函数,do { ... } while(0)应该用于此
  • 它计算算术表达式中的宏参数而不用包围它们,()如果将其他表达式传递给宏,可能会导致令人惊讶的扩展。
于 2013-06-05T08:50:57.390 回答