SHA256 (RFC 4634) 中 "Length_Low" 和 "Length_High" 的含义?
Meaning of "Length_Low" and "Length_High" in SHA256 (RFC 4634)?
今天在学习SHA2,到了代码中看不懂的地方
RFC 4634(定义SHA2的地方)在sha.h
文件中定义了两个变量,Length_Low
和Length_High
:
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
例如,在 sha224-256.c
文件中,变量 Length_Low
在两个地方被主动更改。这里:
/*
* add "length" to the length
*/
static uint32_t addTemp;
#define SHA1AddLength(context, length) \
(addTemp = (context)->Length_Low, \
(context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
这里:
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low);
我了解 RFC 4634 和 SHA2 的原理。然而,作为 C 语言的初学者,我只能理解论文中 99% 的代码。我附上的代码片段属于这剩下的1%。
能否请您解释一下,Length_Low
和 Length_High
变量在 SHA2 的实现中起什么作用?它们在代码层面的含义是什么?
其次,代码片段中发生了什么?我可以识别复合运算符和移位,但代码的难度让我不知所措,尤其是在第二个片段中,取消引用、递增、定义等发生在同一行代码中。
Meta:stackexchange,尤其是 Whosebug,政策不是 post 'code' 的图像,被广泛定义为包括配置文件和日志或错误消息之类的东西,因为它们很难在移动设备上阅读,视障人士无法阅读,不可剪切和粘贴,不可搜索。再加上你的,根据你的 IDE 重新格式化和着色,在我看来非常丑陋。幸运的是,所有 RFC 都是以文本形式发布的,我可以很容易地替换它。
此外,SHA-256 和 SHA-224(以及之前的 SHA-1 和 MD5)的输入块大小为 64 octets 或 512 位,而不是64位,反正和长度字段无关。长度字段确实是 64 位,在代码中实现为两个 32 位变量,用于高半部分和低半部分。
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
是相当棘手的代码,用于将一段输入数据的长度(实际上始终使用 8 表示完整的八位字节或 1-7 表示剩余位)到 2x32 位长度字段。首先它把传入的Length_Low
存入addTemp
,然后,从里到外:
(context)->Length_Low += (length) // call this CODE1
将length
的值添加到结构中的Length_Low
字段;因为这在 C 中使用无符号算术,如果结果(数学上)溢出,它会被环绕(取模 232)。因此,当且仅当 overflow/wraparound 发生时,总和(Length_low
中的新值)小于 addTemp
中的原始值。这是经过测试的,在这种情况下 Length_High
字段会增加:
( CODE1 < addTemp) && (++(context)->Length_High == 0) // call this CODE2
如果在增加高半部分后为零,这意味着它也overflowed/wrapped-around,这意味着真正的消息长度由于规范要求,太大而无法放入 64 位字段,因此这被认为是错误并存储在 Corrupted
字段中,稍后将对其进行测试以报告哈希操作失败:
(addTemp=..., (context)->Corrupted = CODE2 ? 1 : 0)
应该注意 ? 1 : 0
在技术上是不必要的; C 中的 &&
和 ||
运算符(以及像 <
和 ==
这样的 comparison/equality 运算符)被定义为 return 一个表示真和已经为 false 为零(尽管 tests 像 if(x)
和 while(x)
accept 任何非零值作为 true)。然而,有些人觉得把它写出来更清晰,并且在 RFC 中这种动机特别强烈,它发布给包括那些(比如你!)对 C 知之甚少的受众。
事实上,将它写成一个(非常小的)函数而不是一个宏可能会更好,这将允许使用更明显的语句而不是复杂的嵌套表达式,并且 2006 年任何像样的编译器(现在少得多)会内联并折叠以生成与宏相同的代码。但世界并不完美。
相比之下,您的第三个块非常简单。它只是取 2x32 位长度字段并将其存储为当前 Message_Block
.
的最后 8 个元素中的 8 个 8 位单元的大端序列
今天在学习SHA2,到了代码中看不懂的地方
RFC 4634(定义SHA2的地方)在sha.h
文件中定义了两个变量,Length_Low
和Length_High
:
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
例如,在 sha224-256.c
文件中,变量 Length_Low
在两个地方被主动更改。这里:
/*
* add "length" to the length
*/
static uint32_t addTemp;
#define SHA1AddLength(context, length) \
(addTemp = (context)->Length_Low, \
(context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
这里:
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low);
我了解 RFC 4634 和 SHA2 的原理。然而,作为 C 语言的初学者,我只能理解论文中 99% 的代码。我附上的代码片段属于这剩下的1%。
能否请您解释一下,Length_Low
和 Length_High
变量在 SHA2 的实现中起什么作用?它们在代码层面的含义是什么?
其次,代码片段中发生了什么?我可以识别复合运算符和移位,但代码的难度让我不知所措,尤其是在第二个片段中,取消引用、递增、定义等发生在同一行代码中。
Meta:stackexchange,尤其是 Whosebug,政策不是 post 'code' 的图像,被广泛定义为包括配置文件和日志或错误消息之类的东西,因为它们很难在移动设备上阅读,视障人士无法阅读,不可剪切和粘贴,不可搜索。再加上你的,根据你的 IDE 重新格式化和着色,在我看来非常丑陋。幸运的是,所有 RFC 都是以文本形式发布的,我可以很容易地替换它。
此外,SHA-256 和 SHA-224(以及之前的 SHA-1 和 MD5)的输入块大小为 64 octets 或 512 位,而不是64位,反正和长度字段无关。长度字段确实是 64 位,在代码中实现为两个 32 位变量,用于高半部分和低半部分。
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
是相当棘手的代码,用于将一段输入数据的长度(实际上始终使用 8 表示完整的八位字节或 1-7 表示剩余位)到 2x32 位长度字段。首先它把传入的Length_Low
存入addTemp
,然后,从里到外:
(context)->Length_Low += (length) // call this CODE1
将length
的值添加到结构中的Length_Low
字段;因为这在 C 中使用无符号算术,如果结果(数学上)溢出,它会被环绕(取模 232)。因此,当且仅当 overflow/wraparound 发生时,总和(Length_low
中的新值)小于 addTemp
中的原始值。这是经过测试的,在这种情况下 Length_High
字段会增加:
( CODE1 < addTemp) && (++(context)->Length_High == 0) // call this CODE2
如果在增加高半部分后为零,这意味着它也overflowed/wrapped-around,这意味着真正的消息长度由于规范要求,太大而无法放入 64 位字段,因此这被认为是错误并存储在 Corrupted
字段中,稍后将对其进行测试以报告哈希操作失败:
(addTemp=..., (context)->Corrupted = CODE2 ? 1 : 0)
应该注意 ? 1 : 0
在技术上是不必要的; C 中的 &&
和 ||
运算符(以及像 <
和 ==
这样的 comparison/equality 运算符)被定义为 return 一个表示真和已经为 false 为零(尽管 tests 像 if(x)
和 while(x)
accept 任何非零值作为 true)。然而,有些人觉得把它写出来更清晰,并且在 RFC 中这种动机特别强烈,它发布给包括那些(比如你!)对 C 知之甚少的受众。
事实上,将它写成一个(非常小的)函数而不是一个宏可能会更好,这将允许使用更明显的语句而不是复杂的嵌套表达式,并且 2006 年任何像样的编译器(现在少得多)会内联并折叠以生成与宏相同的代码。但世界并不完美。
相比之下,您的第三个块非常简单。它只是取 2x32 位长度字段并将其存储为当前 Message_Block
.