密码学学习记录|hash sha256 算法

密码学学习记录 7 / 18

维基百科

SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,由美国国家标准与技术研究院(NIST)在2001年发布。属于SHA算法之一,是SHA-1的后继者。

参考资料

  • 1、rfc6234
  • 2、sha2 wikipedia
  • 3、文内关于 sha2 的部分描述,皆是来自网上博客文章

SHA-2 是个大家族,有多种算法标准(SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256),本文主要分析 SHA-256 常用算法标准

SHA-256 算法流程分析(根据 rfc6234 文档描述)

消息填充(预处理)

  • 1、数据填充(与 md5 sha1 填充规则相同,规则如下)

sha-256 算法是按照分组进行处理的,512bit 为一组,大部分的明文长度不会刚好是 512bit 的整倍数,所以需要进行填充
填充规则如下:在明文后先补一个 1,然后全部补 0 至满足(length + padLength % 512 = 448)。总共最少要补一位,最多补 512 位。

  • 2、长度填充(与 sha1 相同)

在最后补充 64bit 大小的明文长度,注:大端序

计算常量

  • 1、八个计算常量

计算规则:前 8 个质数平方根的小数部分,取高 32 位(类型:无符号 int32),转成 hex

  • 2、K数组 64 个计算常量

计算规则:前 64 个质数立方根的小数部分,取高 32 位(类型:无符号 int32),转成 hex

计算函数

  • 1、数据分组函数(一共 64步,前 16步,与 sha1 相同)
0 - 15 步
for i from 0 to 15: 
    w[i] := (input[w1 * 4]) leftshift 24
    w[i] :|= (input[w1 * 4 + 1]) leftshift 16
    w[i] :|= (input[w1 * 4 + 2]) leftshift 8
    w[i] :|= (input[w1 * 4 + 3]) leftshift 0

16 - 63 步
for i from 16 to 63
    s0 := (w[i - 15] rightrotate 7) xor (w[i - 15] rightrotate 18) xor(w[i - 15] rightshift 3)
    s1 := (w[i - 2] rightrotate 17) xor (w[i - 2] rightrotate 19) xor(w[i - 2] rightshift 10)
    w[i] := w[i - 16] + s0 + w[i - 7] + s1
  • 2、主逻辑(64 步)
for i from 0 to 63
    s0 := (a rightrotate 2) xor (a rightrotate 13) xor(a rightrotate 22)
    maj := (a and b) xor (a and c) xor(b and c)
    t2 := s0 + maj
    s1 := (e rightrotate 6) xor (e rightrotate 11) xor(e rightrotate 25)
    ch := (e and f) xor ((not e) and g)
    t1 := h + s1 + ch + k[i] + w[i]
    h := g
    g := f
    f := e
    e := d + t1
    d := c
    c := b
    b := a
    a := t1 + t2
  • 3、循环计算结束
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h

python sha-256 代码实现

  • 1、计算常量
import math

CONST = list(filter(lambda x: not [x % i for i in range(2, int(math.sqrt(x)) + 1) if x % i == 0], range(2, 312)))
HH = [int(abs(pow(i, 0.5)) * 4294967296) % (2 ** 32) for i in CONST[:8]]
KK = [int(abs(pow(i, 1.0 / 3)) * 4294967296) % (2 ** 32) for i in CONST]
  • 2、数据填充
def padding(input_str):
    input_str_bit_len = len(input_str) * 8
    input_str_len = input_str_bit_len % (2 ** 32)
    input_str += b'\x80'
    pad_leg = ((448 - (input_str_len + 8) % 512) % 512) // 8
    input_str = input_str + b'\x00' * pad_leg + input_str_len.to_bytes(8, byteorder='big')
    return input_str
  • 3、计算函数(包含数据分组)

参考上述资料自行编写

最后

pythoncyberchef 计算结果相同,代码没啥问题

全部代码

您需要先支付 29.9元 才能查看此处内容!立即支付

注意该订单不支持退款,如有问题可联系博主

暂无评论
本文作者:
本文链接: https://www.qinless.com/?p=1290
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

发表评论

返回顶部