精华内容
下载资源
问答
  • sha2算法介绍和源码实现

    千次阅读 2019-12-01 22:55:46
    SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。 SHA-2下又可再分为六个不同的算法标准 包括了:...

    1. SHA256简介

    SHA256是SHA-2下细分出的一种算法

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

    SHA-2下又可再分为六个不同的算法标准

    包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

    这些变体除了生成摘要的长度 、循环运行的次数等一些微小差异外,算法的基本结构是一致的。

    回到SHA256上,说白了,它就是一个哈希函数。

    哈希函数,又称散列算法,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(或哈希值)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。

    对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。

    这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示

    来看一个例子:

    干他100天成为区块链程序员,红军大叔带领着我们,fighting!

    这句话,经过哈希函数SHA256后得到的哈希值为:

    A7FCFC6B5269BDCCE571798D618EA219A68B96CB87A0E21080C2E758D23E4CE9

     

    2. SHA256原理详解

    为了更好的理解SHA256的原理,这里首先将算法中可以单独抽出的模块,包括常量的初始化、信息预处理、使用到的逻辑运算分别进行介绍,甩开这些理解上的障碍后,一起来探索SHA256算法的主体部分,即消息摘要是如何计算的。

    2.1 常量初始化

    SHA256算法中用到了8个哈希初值以及64个哈希常量

    其中,SHA256算法的8个哈希初值如下:

    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19

    这些初值是对自然数中前8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32bit而来

    在SHA256算法中,用到的64个常量如下:

    428a2f98 71374491 b5c0fbcf e9b5dba5
    3956c25b 59f111f1 923f82a4 ab1c5ed5
    d807aa98 12835b01 243185be 550c7dc3
    72be5d74 80deb1fe 9bdc06a7 c19bf174
    e49b69c1 efbe4786 0fc19dc6 240ca1cc
    2de92c6f 4a7484aa 5cb0a9dc 76f988da
    983e5152 a831c66d b00327c8 bf597fc7
    c6e00bf3 d5a79147 06ca6351 14292967
    27b70a85 2e1b2138 4d2c6dfc 53380d13
    650a7354 766a0abb 81c2c92e 92722c85
    a2bfe8a1 a81a664b c24b8b70 c76c51a3
    d192e819 d6990624 f40e3585 106aa070
    19a4c116 1e376c08 2748774c 34b0bcb5
    391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
    748f82ee 78a5636f 84c87814 8cc70208
    90befffa a4506ceb bef9a3f7 c67178f2

    和8个哈希初值类似,这些常量是对自然数中前64个质数(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97…)的立方根的小数部分取前32bit而来。

     

    2.2 信息预处理(pre-processing)

    SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。

    信息的预处理分为两个步骤:附加填充比特和附加长度

    STEP1:附加填充比特

    在报文末尾进行填充,使报文长度在对512取模以后的余数是448

    填充是这样进行的:先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。

    需要注意的是,信息必须进行填充,也就是说,即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512个比特。

    因此,填充是至少补一位,最多补512位。

    例:以信息“abc”为例显示补位的过程。

    a,b,c对应的ASCII码分别是97,98,99

    于是原始信息的二进制编码为:01100001 01100010 01100011

    补位第一步,首先补一个“1” : 0110000101100010 01100011 1

    补位第二步,补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000

    补位完成后的数据如下(为了简介用16进制表示):

    61626380 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000

    为什么是448?

    因为在第一步的预处理后,第二步会再附加上一个64bit的数据,用来表示原始报文的长度信息。而448+64=512,正好拼成了一个完整的结构。

    STEP2:附加长度值

    附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。

    wiki百科中给出的原文是:append length of message (before pre-processing), in bits, as 64-bit big-endian integer

    SHA256用一个64位的数据来表示原始消息的长度。

    因此,通过SHA256计算的消息长度必须要小于$ 2^64 $,当然绝大多数情况这足够大了。

    长度信息的编码方式为64-bit big-endian integer

    关于Big endian的含义,文末给出了补充

    回到刚刚的例子,消息“abc”,3个字符,占用24个bit

    因此,在进行了补长度的操作以后,整个消息就变成下面这样了(16进制格式)

    61626380 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000018

    2.3 逻辑运算

    SHA256散列函数中涉及的操作全部是逻辑的位运算

    包括如下的逻辑函数:

    Ch(x,y,z)=(x∧y)⊕(¬x∧z)

    Ma(x,y,z)=(x∧y)⊕(x∧z)⊕(y∧z)

    Σ 0 (x)=S 2 (x)⊕S 13 (x)⊕S 22 (x)

    Σ 1 (x)=S 6 (x)⊕S 11 (x)⊕S 25 (x)

    σ 0 (x)=S 7 (x)⊕S 18 (x)⊕R 3 (x)

    σ 1 (x)=S 17 (x)⊕S 19 (x)⊕R 10 (x)

     

    2.4 计算消息摘要
     

    现在来介绍SHA256算法的主体部分,即消息摘要是如何计算的。

    首先:将消息分解成512-bit大小的块(break message into 512-bit chunks)

    假设消息M可以被分解为n个块,于是整个算法需要做的就是完成n次迭代,n次迭代的结果就是最终的哈希值,即256bit的数字摘要。

    一个256-bit的摘要的初始值H0,经过第一个数据块进行运算,得到H1,即完成了第一次迭代H1经过第二个数据块得到H2,……,依次处理,最后得到Hn,Hn即为最终的256-bit消息摘要将每次迭代进行的映射用$ Map(H_{i-1}) = H_{i} $表示,于是迭代可以更形象的展示为:

    图中256-bit的Hi被描述8个小块,这是因为SHA256算法中的最小运算单元称为“字”(Word),一个字是32位。此外,第一次迭代中,映射的初值设置为前面介绍的8个哈希初值,如下图所示:

    下面开始介绍每一次迭代的内容,即映射$ Map(H_{i-1}) = H_{i} $的具体算法

    STEP1:构造64个字(word)

    break chunk into sixteen 32-bit big-endian words w[0], …, w[15]

    对于每一块,将块分解为16个32-bit的big-endian的字,记为w[0], …, w[15]

    也就是说,前16个字直接由消息的第i个块分解得到

    其余的字由如下迭代公式得到:

    W t =σ 1 (W t−2 ) W t−7 σ 0 (W t−15 ) W t−16
    ​    
     

    STEP2:进行64次循环

    映射 $ Map(H_{i-1}) = H_{i} $ 包含了64次加密循环

    即进行64次加密循环即可完成一次迭代

    每次加密循环可以由下图描述:

    图中,ABCDEFGH这8个字(word)在按照一定的规则进行更新,其中

    深蓝色方块是事先定义好的非线性逻辑函数,上文已经做过铺垫

    红色田字方块代表 mod $ 2^{32} $ addition,即将两个数字加在一起,如果结果大于$ 2^{32} ,你必须除以,你必须除以 2^{32} $并找到余数。

    ABCDEFGH一开始的初始值分别为$ H_{i-1}(0),H_{i-1}(1),…,H_{i-1}(7) $

    Kt是第t个密钥,对应我们上文提到的64个常量

    Wt是本区块产生第t个word。原消息被切成固定长度512-bit的区块,对每一个区块,产生64个word,通过重复运行循环n次对ABCDEFGH这八个字循环加密。

    最后一次循环所产生的八个字合起来即是第i个块对应到的散列字符串$ H_{i} $

    由此变完成了SHA256算法的所有介绍
     

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define SHA224_DIGEST_SIZE ( 224 / 8)
    #define SHA256_DIGEST_SIZE ( 256 / 8)
    #define SHA384_DIGEST_SIZE ( 384 / 8)
    #define SHA512_DIGEST_SIZE ( 512 / 8)
    
    #define SHA256_BLOCK_SIZE  ( 512 / 8)
    #define SHA512_BLOCK_SIZE  (1024 / 8)
    #define SHA384_BLOCK_SIZE  SHA512_BLOCK_SIZE
    #define SHA224_BLOCK_SIZE  SHA256_BLOCK_SIZE
    
    #ifndef SHA2_TYPES
    #define SHA2_TYPES
    typedef unsigned char uint8;
    typedef unsigned int  uint32;
    typedef unsigned long long uint64;
    #endif
    
    typedef struct {
        unsigned int tot_len;
        unsigned int len;
        unsigned char block[2 * SHA256_BLOCK_SIZE];
        uint32 h[8];
    } sha256_ctx;
    
    typedef struct {
        unsigned int tot_len;
        unsigned int len;
        unsigned char block[2 * SHA512_BLOCK_SIZE];
        uint64 h[8];
    } sha512_ctx;
    
    typedef sha512_ctx sha384_ctx;
    typedef sha256_ctx sha224_ctx;
    
    void sha224_init(sha224_ctx *ctx);
    void sha224_update(sha224_ctx *ctx, const unsigned char *message,
                       unsigned int len);
    void sha224_final(sha224_ctx *ctx, unsigned char *digest);
    void sha224(const unsigned char *message, unsigned int len,
                unsigned char *digest);
    
    void sha256_init(sha256_ctx * ctx);
    void sha256_update(sha256_ctx *ctx, const unsigned char *message,
                       unsigned int len);
    void sha256_final(sha256_ctx *ctx, unsigned char *digest);
    void sha256(const unsigned char *message, unsigned int len,
                unsigned char *digest);
    
    void sha384_init(sha384_ctx *ctx);
    void sha384_update(sha384_ctx *ctx, const unsigned char *message,
                       unsigned int len);
    void sha384_final(sha384_ctx *ctx, unsigned char *digest);
    void sha384(const unsigned char *message, unsigned int len,
                unsigned char *digest);
    
    void sha512_init(sha512_ctx *ctx);
    void sha512_update(sha512_ctx *ctx, const unsigned char *message,
                       unsigned int len);
    void sha512_final(sha512_ctx *ctx, unsigned char *digest);
    void sha512(const unsigned char *message, unsigned int len,
                unsigned char *digest);
    
    #define SHFR(x, n)    (x >> n)
    #define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
    #define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
    #define CH(x, y, z)  ((x & y) ^ (~x & z))
    #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
    
    #define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
    #define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
    #define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
    #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
    
    #define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
    #define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
    #define SHA512_F3(x) (ROTR(x,  1) ^ ROTR(x,  8) ^ SHFR(x,  7))
    #define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x,  6))
    
    #define UNPACK32(x, str)                      \
    {                                             \
        *((str) + 3) = (uint8) ((x)      );       \
        *((str) + 2) = (uint8) ((x) >>  8);       \
        *((str) + 1) = (uint8) ((x) >> 16);       \
        *((str) + 0) = (uint8) ((x) >> 24);       \
    }
    
    #define PACK32(str, x)                        \
    {                                             \
        *(x) =   ((uint32) *((str) + 3)      )    \
               | ((uint32) *((str) + 2) <<  8)    \
               | ((uint32) *((str) + 1) << 16)    \
               | ((uint32) *((str) + 0) << 24);   \
    }
    
    #define UNPACK64(x, str)                      \
    {                                             \
        *((str) + 7) = (uint8) ((x)      );       \
        *((str) + 6) = (uint8) ((x) >>  8);       \
        *((str) + 5) = (uint8) ((x) >> 16);       \
        *((str) + 4) = (uint8) ((x) >> 24);       \
        *((str) + 3) = (uint8) ((x) >> 32);       \
        *((str) + 2) = (uint8) ((x) >> 40);       \
        *((str) + 1) = (uint8) ((x) >> 48);       \
        *((str) + 0) = (uint8) ((x) >> 56);       \
    }
    
    #define PACK64(str, x)                        \
    {                                             \
        *(x) =   ((uint64) *((str) + 7)      )    \
               | ((uint64) *((str) + 6) <<  8)    \
               | ((uint64) *((str) + 5) << 16)    \
               | ((uint64) *((str) + 4) << 24)    \
               | ((uint64) *((str) + 3) << 32)    \
               | ((uint64) *((str) + 2) << 40)    \
               | ((uint64) *((str) + 1) << 48)    \
               | ((uint64) *((str) + 0) << 56);   \
    }
    
    /* Macros used for loops unrolling */
    
    #define SHA256_SCR(i)                         \
    {                                             \
        w[i] =  SHA256_F4(w[i -  2]) + w[i -  7]  \
              + SHA256_F3(w[i - 15]) + w[i - 16]; \
    }
    
    #define SHA512_SCR(i)                         \
    {                                             \
        w[i] =  SHA512_F4(w[i -  2]) + w[i -  7]  \
              + SHA512_F3(w[i - 15]) + w[i - 16]; \
    }
    
    #define SHA256_EXP(a, b, c, d, e, f, g, h, j)               \
    {                                                           \
        t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
             + sha256_k[j] + w[j];                              \
        t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
        wv[d] += t1;                                            \
        wv[h] = t1 + t2;                                        \
    }
    
    #define SHA512_EXP(a, b, c, d, e, f, g ,h, j)               \
    {                                                           \
        t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
             + sha512_k[j] + w[j];                              \
        t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
        wv[d] += t1;                                            \
        wv[h] = t1 + t2;                                        \
    }
    
    uint32 sha224_h0[8] =
                {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
                 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
    
    uint32 sha256_h0[8] =
                {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
                 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
    
    uint64 sha384_h0[8] =
                {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
                 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
                 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
                 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
    
    uint64 sha512_h0[8] =
                {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
                 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
                 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
                 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
    
    uint32 sha256_k[64] =
                {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
                 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
                 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
                 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
                 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
                 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
                 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
                 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
                 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
    
    uint64 sha512_k[80] =
                {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
                 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
                 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
                 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
                 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
                 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
                 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
                 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
                 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
                 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
                 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
                 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
                 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
                 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
                 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
                 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
                 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
                 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
                 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
                 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
                 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
                 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
                 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
                 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
                 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
                 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
                 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
                 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
                 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
                 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
                 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
                 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
                 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
                 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
                 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
                 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
                 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
                 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
                 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
                 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
    
    /* SHA-256 functions */
    
    void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
                       unsigned int block_nb)
    {
        uint32 w[64];
        uint32 wv[8];
        uint32 t1, t2;
        const unsigned char *sub_block;
        int i;
    
    #ifndef UNROLL_LOOPS
        int j;
    #endif
    
        for (i = 0; i < (int) block_nb; i++) {
            sub_block = message + (i << 6);
    
    #ifndef UNROLL_LOOPS
            for (j = 0; j < 16; j++) {
                PACK32(&sub_block[j << 2], &w[j]);
            }
    
            for (j = 16; j < 64; j++) {
                SHA256_SCR(j);
            }
    
            for (j = 0; j < 8; j++) {
                wv[j] = ctx->h[j];
            }
    
            for (j = 0; j < 64; j++) {
                t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
                    + sha256_k[j] + w[j];
                t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
                wv[7] = wv[6];
                wv[6] = wv[5];
                wv[5] = wv[4];
                wv[4] = wv[3] + t1;
                wv[3] = wv[2];
                wv[2] = wv[1];
                wv[1] = wv[0];
                wv[0] = t1 + t2;
            }
    
            for (j = 0; j < 8; j++) {
                ctx->h[j] += wv[j];
            }
    #else
            PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
            PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
            PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
            PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
            PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
            PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
            PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
            PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
    
            SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
            SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
            SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
            SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
            SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
            SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
            SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
            SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
            SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
            SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
            SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
            SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
    
            wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
            wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
            wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
            wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
    
            SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
            SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
            SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
            SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
            SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
            SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
            SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
            SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
            SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
            SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
            SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
            SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
            SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
            SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
            SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
            SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
            SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
            SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
            SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
            SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
            SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
            SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
            SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
            SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
            SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
            SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
            SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
            SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
            SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
            SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
            SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
            SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
    
            ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
            ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
            ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
            ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
    #endif /* !UNROLL_LOOPS */
        }
    }
    
    void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
    {
        sha256_ctx ctx;
    
        sha256_init(&ctx);
        sha256_update(&ctx, message, len);
        sha256_final(&ctx, digest);
    }
    
    void sha256_init(sha256_ctx *ctx)
    {
    #ifndef UNROLL_LOOPS
        int i;
        for (i = 0; i < 8; i++) {
            ctx->h[i] = sha256_h0[i];
        }
    #else
        ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
        ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
        ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
        ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
    #endif /* !UNROLL_LOOPS */
    
        ctx->len = 0;
        ctx->tot_len = 0;
    }
    
    void sha256_update(sha256_ctx *ctx, const unsigned char *message,
                       unsigned int len)
    {
        unsigned int block_nb;
        unsigned int new_len, rem_len, tmp_len;
        const unsigned char *shifted_message;
    
        tmp_len = SHA256_BLOCK_SIZE - ctx->len;
        rem_len = len < tmp_len ? len : tmp_len;
    
        memcpy(&ctx->block[ctx->len], message, rem_len);
    
        if (ctx->len + len < SHA256_BLOCK_SIZE) {
            ctx->len += len;
            return;
        }
    
        new_len = len - rem_len;
        block_nb = new_len / SHA256_BLOCK_SIZE;
    
        shifted_message = message + rem_len;
    
        sha256_transf(ctx, ctx->block, 1);
        sha256_transf(ctx, shifted_message, block_nb);
    
        rem_len = new_len % SHA256_BLOCK_SIZE;
    
        memcpy(ctx->block, &shifted_message[block_nb << 6],
               rem_len);
    
        ctx->len = rem_len;
        ctx->tot_len += (block_nb + 1) << 6;
    }
    
    void sha256_final(sha256_ctx *ctx, unsigned char *digest)
    {
        unsigned int block_nb;
        unsigned int pm_len;
        unsigned int len_b;
    
    #ifndef UNROLL_LOOPS
        int i;
    #endif
    
        block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
                         < (ctx->len % SHA256_BLOCK_SIZE)));
    
        len_b = (ctx->tot_len + ctx->len) << 3;
        pm_len = block_nb << 6;
    
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
        UNPACK32(len_b, ctx->block + pm_len - 4);
    
        sha256_transf(ctx, ctx->block, block_nb);
    
    #ifndef UNROLL_LOOPS
        for (i = 0 ; i < 8; i++) {
            UNPACK32(ctx->h[i], &digest[i << 2]);
        }
    #else
       UNPACK32(ctx->h[0], &digest[ 0]);
       UNPACK32(ctx->h[1], &digest[ 4]);
       UNPACK32(ctx->h[2], &digest[ 8]);
       UNPACK32(ctx->h[3], &digest[12]);
       UNPACK32(ctx->h[4], &digest[16]);
       UNPACK32(ctx->h[5], &digest[20]);
       UNPACK32(ctx->h[6], &digest[24]);
       UNPACK32(ctx->h[7], &digest[28]);
    #endif /* !UNROLL_LOOPS */
    }
    
    /* SHA-512 functions */
    
    void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
                       unsigned int block_nb)
    {
        uint64 w[80];
        uint64 wv[8];
        uint64 t1, t2;
        const unsigned char *sub_block;
        int i, j;
    
        for (i = 0; i < (int) block_nb; i++) {
            sub_block = message + (i << 7);
    
    #ifndef UNROLL_LOOPS
            for (j = 0; j < 16; j++) {
                PACK64(&sub_block[j << 3], &w[j]);
            }
    
            for (j = 16; j < 80; j++) {
                SHA512_SCR(j);
            }
    
            for (j = 0; j < 8; j++) {
                wv[j] = ctx->h[j];
            }
    
            for (j = 0; j < 80; j++) {
                t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
                    + sha512_k[j] + w[j];
                t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
                wv[7] = wv[6];
                wv[6] = wv[5];
                wv[5] = wv[4];
                wv[4] = wv[3] + t1;
                wv[3] = wv[2];
                wv[2] = wv[1];
                wv[1] = wv[0];
                wv[0] = t1 + t2;
            }
    
            for (j = 0; j < 8; j++) {
                ctx->h[j] += wv[j];
            }
    #else
            PACK64(&sub_block[  0], &w[ 0]); PACK64(&sub_block[  8], &w[ 1]);
            PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
            PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
            PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
            PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
            PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
            PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
            PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
    
            SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
            SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
            SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
            SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
            SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
            SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
            SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
            SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
            SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
            SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
            SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
            SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
            SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
            SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
            SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
            SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
    
            wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
            wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
            wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
            wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
    
            j = 0;
    
            do {
                SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
                SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
                SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
                SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
                SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
                SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
                SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
                SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
            } while (j < 80);
    
            ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
            ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
            ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
            ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
    #endif /* !UNROLL_LOOPS */
        }
    }
    
    void sha512(const unsigned char *message, unsigned int len,
                unsigned char *digest)
    {
        sha512_ctx ctx;
    
        sha512_init(&ctx);
        sha512_update(&ctx, message, len);
        sha512_final(&ctx, digest);
    }
    
    void sha512_init(sha512_ctx *ctx)
    {
    #ifndef UNROLL_LOOPS
        int i;
        for (i = 0; i < 8; i++) {
            ctx->h[i] = sha512_h0[i];
        }
    #else
        ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
        ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
        ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
        ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
    #endif /* !UNROLL_LOOPS */
    
        ctx->len = 0;
        ctx->tot_len = 0;
    }
    
    void sha512_update(sha512_ctx *ctx, const unsigned char *message,
                       unsigned int len)
    {
        unsigned int block_nb;
        unsigned int new_len, rem_len, tmp_len;
        const unsigned char *shifted_message;
    
        tmp_len = SHA512_BLOCK_SIZE - ctx->len;
        rem_len = len < tmp_len ? len : tmp_len;
    
        memcpy(&ctx->block[ctx->len], message, rem_len);
    
        if (ctx->len + len < SHA512_BLOCK_SIZE) {
            ctx->len += len;
            return;
        }
    
        new_len = len - rem_len;
        block_nb = new_len / SHA512_BLOCK_SIZE;
    
        shifted_message = message + rem_len;
    
        sha512_transf(ctx, ctx->block, 1);
        sha512_transf(ctx, shifted_message, block_nb);
    
        rem_len = new_len % SHA512_BLOCK_SIZE;
    
        memcpy(ctx->block, &shifted_message[block_nb << 7],
               rem_len);
    
        ctx->len = rem_len;
        ctx->tot_len += (block_nb + 1) << 7;
    }
    
    void sha512_final(sha512_ctx *ctx, unsigned char *digest)
    {
        unsigned int block_nb;
        unsigned int pm_len;
        unsigned int len_b;
    
    #ifndef UNROLL_LOOPS
        int i;
    #endif
    
        block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
                         < (ctx->len % SHA512_BLOCK_SIZE));
    
        len_b = (ctx->tot_len + ctx->len) << 3;
        pm_len = block_nb << 7;
    
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
        UNPACK32(len_b, ctx->block + pm_len - 4);
    
        sha512_transf(ctx, ctx->block, block_nb);
    
    #ifndef UNROLL_LOOPS
        for (i = 0 ; i < 8; i++) {
            UNPACK64(ctx->h[i], &digest[i << 3]);
        }
    #else
        UNPACK64(ctx->h[0], &digest[ 0]);
        UNPACK64(ctx->h[1], &digest[ 8]);
        UNPACK64(ctx->h[2], &digest[16]);
        UNPACK64(ctx->h[3], &digest[24]);
        UNPACK64(ctx->h[4], &digest[32]);
        UNPACK64(ctx->h[5], &digest[40]);
        UNPACK64(ctx->h[6], &digest[48]);
        UNPACK64(ctx->h[7], &digest[56]);
    #endif /* !UNROLL_LOOPS */
    }
    
    /* SHA-384 functions */
    
    void sha384(const unsigned char *message, unsigned int len,
                unsigned char *digest)
    {
        sha384_ctx ctx;
    
        sha384_init(&ctx);
        sha384_update(&ctx, message, len);
        sha384_final(&ctx, digest);
    }
    
    void sha384_init(sha384_ctx *ctx)
    {
    #ifndef UNROLL_LOOPS
        int i;
        for (i = 0; i < 8; i++) {
            ctx->h[i] = sha384_h0[i];
        }
    #else
        ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
        ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
        ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
        ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
    #endif /* !UNROLL_LOOPS */
    
        ctx->len = 0;
        ctx->tot_len = 0;
    }
    
    void sha384_update(sha384_ctx *ctx, const unsigned char *message,
                       unsigned int len)
    {
        unsigned int block_nb;
        unsigned int new_len, rem_len, tmp_len;
        const unsigned char *shifted_message;
    
        tmp_len = SHA384_BLOCK_SIZE - ctx->len;
        rem_len = len < tmp_len ? len : tmp_len;
    
        memcpy(&ctx->block[ctx->len], message, rem_len);
    
        if (ctx->len + len < SHA384_BLOCK_SIZE) {
            ctx->len += len;
            return;
        }
    
        new_len = len - rem_len;
        block_nb = new_len / SHA384_BLOCK_SIZE;
    
        shifted_message = message + rem_len;
    
        sha512_transf(ctx, ctx->block, 1);
        sha512_transf(ctx, shifted_message, block_nb);
    
        rem_len = new_len % SHA384_BLOCK_SIZE;
    
        memcpy(ctx->block, &shifted_message[block_nb << 7],
               rem_len);
    
        ctx->len = rem_len;
        ctx->tot_len += (block_nb + 1) << 7;
    }
    
    void sha384_final(sha384_ctx *ctx, unsigned char *digest)
    {
        unsigned int block_nb;
        unsigned int pm_len;
        unsigned int len_b;
    
    #ifndef UNROLL_LOOPS
        int i;
    #endif
    
        block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
                         < (ctx->len % SHA384_BLOCK_SIZE)));
    
        len_b = (ctx->tot_len + ctx->len) << 3;
        pm_len = block_nb << 7;
    
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
        UNPACK32(len_b, ctx->block + pm_len - 4);
    
        sha512_transf(ctx, ctx->block, block_nb);
    
    #ifndef UNROLL_LOOPS
        for (i = 0 ; i < 6; i++) {
            UNPACK64(ctx->h[i], &digest[i << 3]);
        }
    #else
        UNPACK64(ctx->h[0], &digest[ 0]);
        UNPACK64(ctx->h[1], &digest[ 8]);
        UNPACK64(ctx->h[2], &digest[16]);
        UNPACK64(ctx->h[3], &digest[24]);
        UNPACK64(ctx->h[4], &digest[32]);
        UNPACK64(ctx->h[5], &digest[40]);
    #endif /* !UNROLL_LOOPS */
    }
    
    /* SHA-224 functions */
    
    void sha224(const unsigned char *message, unsigned int len,
                unsigned char *digest)
    {
        sha224_ctx ctx;
    
        sha224_init(&ctx);
        sha224_update(&ctx, message, len);
        sha224_final(&ctx, digest);
    }
    
    void sha224_init(sha224_ctx *ctx)
    {
    #ifndef UNROLL_LOOPS
        int i;
        for (i = 0; i < 8; i++) {
            ctx->h[i] = sha224_h0[i];
        }
    #else
        ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
        ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
        ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
        ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
    #endif /* !UNROLL_LOOPS */
    
        ctx->len = 0;
        ctx->tot_len = 0;
    }
    
    void sha224_update(sha224_ctx *ctx, const unsigned char *message,
                       unsigned int len)
    {
        unsigned int block_nb;
        unsigned int new_len, rem_len, tmp_len;
        const unsigned char *shifted_message;
    
        tmp_len = SHA224_BLOCK_SIZE - ctx->len;
        rem_len = len < tmp_len ? len : tmp_len;
    
        memcpy(&ctx->block[ctx->len], message, rem_len);
    
        if (ctx->len + len < SHA224_BLOCK_SIZE) {
            ctx->len += len;
            return;
        }
    
        new_len = len - rem_len;
        block_nb = new_len / SHA224_BLOCK_SIZE;
    
        shifted_message = message + rem_len;
    
        sha256_transf(ctx, ctx->block, 1);
        sha256_transf(ctx, shifted_message, block_nb);
    
        rem_len = new_len % SHA224_BLOCK_SIZE;
    
        memcpy(ctx->block, &shifted_message[block_nb << 6],
               rem_len);
    
        ctx->len = rem_len;
        ctx->tot_len += (block_nb + 1) << 6;
    }
    
    void sha224_final(sha224_ctx *ctx, unsigned char *digest)
    {
        unsigned int block_nb;
        unsigned int pm_len;
        unsigned int len_b;
    
    #ifndef UNROLL_LOOPS
        int i;
    #endif
    
        block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
                         < (ctx->len % SHA224_BLOCK_SIZE)));
    
        len_b = (ctx->tot_len + ctx->len) << 3;
        pm_len = block_nb << 6;
    
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
        UNPACK32(len_b, ctx->block + pm_len - 4);
    
        sha256_transf(ctx, ctx->block, block_nb);
    
    #ifndef UNROLL_LOOPS
        for (i = 0 ; i < 7; i++) {
            UNPACK32(ctx->h[i], &digest[i << 2]);
        }
    #else
       UNPACK32(ctx->h[0], &digest[ 0]);
       UNPACK32(ctx->h[1], &digest[ 4]);
       UNPACK32(ctx->h[2], &digest[ 8]);
       UNPACK32(ctx->h[3], &digest[12]);
       UNPACK32(ctx->h[4], &digest[16]);
       UNPACK32(ctx->h[5], &digest[20]);
       UNPACK32(ctx->h[6], &digest[24]);
    #endif /* !UNROLL_LOOPS */
    }
    
    void test(const char *vector, unsigned char *digest,
              unsigned int digest_size)
    {
        char output[2 * SHA512_DIGEST_SIZE + 1];
        int i;
    
        output[2 * digest_size] = '\0';
    
        for (i = 0; i < (int) digest_size ; i++) {
           sprintf(output + 2 * i, "%02x", digest[i]);
        }
    
        printf("H: %s\n", output);
        if (strcmp(vector, output)) {
            fprintf(stderr, "Test failed.\n");
            exit(EXIT_FAILURE);
        }
    }
    
    int main()
    {
        static const char *vectors[4][3] =
        {   /* SHA-224 */
            {
            "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
            "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
            "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
            },
            /* SHA-256 */
            {
            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
            "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
            "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
            },
            /* SHA-384 */
            {
            "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
            "8086072ba1e7cc2358baeca134c825a7",
            "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
            "fcc7c71a557e2db966c3e9fa91746039",
            "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
            "07b8b3dc38ecc4ebae97ddd87f3d8985",
            },
            /* SHA-512 */
            {
            "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
            "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
            "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
            "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
            "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
            "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
            }
        };
    
        static const char message1[] = "abc";
        static const char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
                                        "jkijkljklmklmnlmnomnopnopq";
        static const char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
                                        "klfghijklmghijklmnhijklmnoijklmnopjklm"
                                        "nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
        unsigned char *message3;
        unsigned int message3_len = 1000000;
        unsigned char digest[SHA512_DIGEST_SIZE];
    
        message3 = malloc(message3_len);
        if (message3 == NULL) {
            fprintf(stderr, "Can't allocate memory\n");
            return -1;
        }
        memset(message3, 'a', message3_len);
    
        printf("SHA-2 FIPS 180-2 Validation tests\n\n");
        printf("SHA-224 Test vectors\n");
    
        sha224((const unsigned char *) message1, strlen(message1), digest);
        test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
        sha224((const unsigned char *) message2a, strlen(message2a), digest);
        test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
        sha224(message3, message3_len, digest);
        test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
        printf("\n");
    
        printf("SHA-256 Test vectors\n");
    
        sha256((const unsigned char *) message1, strlen(message1), digest);
        test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
        sha256((const unsigned char *) message2a, strlen(message2a), digest);
        test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
        sha256(message3, message3_len, digest);
        test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
        printf("\n");
    
        printf("SHA-384 Test vectors\n");
    
        sha384((const unsigned char *) message1, strlen(message1), digest);
        test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
        sha384((const unsigned char *)message2b, strlen(message2b), digest);
        test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
        sha384(message3, message3_len, digest);
        test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
        printf("\n");
    
        printf("SHA-512 Test vectors\n");
    
        sha512((const unsigned char *) message1, strlen(message1), digest);
        test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
        sha512((const unsigned char *) message2b, strlen(message2b), digest);
        test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
        sha512(message3, message3_len, digest);
        test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
        printf("\n");
    
        printf("All tests passed.\n");
        return 0;
    }
    
    

     

    展开全文
  • 通过哈希函数计算数据存储 insert(key, value) 插入键值对 get(key) 获取值 delete(key) 删除值 ...全域哈希:ha,b(k) = ((a*key+b)mod p) mod m a,b=1,2,…p-1 哈希表应用:集合与字典 字典与集合...

    通过哈希函数计算数据存储

    • insert(key, value) 插入键值对
    • get(key) 获取值
    • delete(key) 删除值

    常见哈希函数

    • 除法哈希:h(k) = k % m
    • 乘法哈希:h(k) = floor(m*(A*key%1))
    • 全域哈希:ha,b(k) = ((a*key+b)mod p) mod m a,b=1,2,…p-1

    哈希表应用:集合与字典

    • 字典与集合都是哈希表来实现的
    • 使用哈希表储存字典,通过哈希函数将字典的建映射为下标
    • 如果发生哈希冲突,则通过拉链法或者开发寻址法解决

    哈希表应用: MD5算法

    • md5曾经 是密码学中常用
    • 利用md5来验证文件下载是否完整
    • 云存储服务商利用他来判断是否已经在云服务器上,就不用重新上传

    哈希表应用: SHA2算法

    • 比MD5安全性更高!性质和md5一样
    • 暴力枚举获得ico币
    展开全文
  • SHA256算法原理详解

    万次阅读 多人点赞 2018-07-03 23:07:30
    SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。 SHA-2下又可再分为六个不同的算法标准 包括了:...

    1. SHA256简介

    SHA256是SHA-2下细分出的一种算法

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

    SHA-2下又可再分为六个不同的算法标准

    包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

    这些变体除了生成摘要的长度 、循环运行的次数等一些微小差异外,算法的基本结构是一致的。

    回到SHA256上,说白了,它就是一个哈希函数。

    哈希函数,又称散列算法,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(或哈希值)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。

    对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。

    这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示

    来看一个例子:

    干他100天成为区块链程序员,红军大叔带领着我们,fighting!

    这句话,经过哈希函数SHA256后得到的哈希值为:

    A7FCFC6B5269BDCCE571798D618EA219A68B96CB87A0E21080C2E758D23E4CE9

    这里找到了一个SHA256在线验证工具,可以用来进行SHA256哈希结果的验证,后面也可以用来检验自己的SHA256代码是否正确。用起来很方便,不妨感受下。


    2. SHA256原理详解

    为了更好的理解SHA256的原理,这里首先将算法中可以单独抽出的模块,包括常量的初始化信息预处理使用到的逻辑运算分别进行介绍,甩开这些理解上的障碍后,一起来探索SHA256算法的主体部分,即消息摘要是如何计算的。

    2.1 常量初始化

    SHA256算法中用到了8个哈希初值以及64个哈希常量

    其中,SHA256算法的8个哈希初值如下:

    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19
    

    这些初值是对自然数中前8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32bit而来

    举个例子来说,$ \sqrt{2} $小数部分约为0.414213562373095048,而
    0.414213562373095048 ≈ 6 ∗ 1 6 − 1 + a ∗ 1 6 − 2 + 0 ∗ 1 6 − 3 + . . . 0.414213562373095048 \approx 6*16^{-1} + a*16^{-2} + 0*16^{-3} + ... 0.4142135623730950486161+a162+0163+...
    于是,质数2的平方根的小数部分取前32bit就对应出了0x6a09e667

    在SHA256算法中,用到的64个常量如下:

    428a2f98 71374491 b5c0fbcf e9b5dba5
    3956c25b 59f111f1 923f82a4 ab1c5ed5
    d807aa98 12835b01 243185be 550c7dc3
    72be5d74 80deb1fe 9bdc06a7 c19bf174
    e49b69c1 efbe4786 0fc19dc6 240ca1cc
    2de92c6f 4a7484aa 5cb0a9dc 76f988da
    983e5152 a831c66d b00327c8 bf597fc7
    c6e00bf3 d5a79147 06ca6351 14292967
    27b70a85 2e1b2138 4d2c6dfc 53380d13
    650a7354 766a0abb 81c2c92e 92722c85
    a2bfe8a1 a81a664b c24b8b70 c76c51a3
    d192e819 d6990624 f40e3585 106aa070
    19a4c116 1e376c08 2748774c 34b0bcb5
    391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
    748f82ee 78a5636f 84c87814 8cc70208
    90befffa a4506ceb bef9a3f7 c67178f2
    

    和8个哈希初值类似,这些常量是对自然数中前64个质数(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97…)的立方根的小数部分取前32bit而来。

    2.2 信息预处理(pre-processing)

    SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。

    信息的预处理分为两个步骤:附加填充比特附加长度

    STEP1:附加填充比特

    在报文末尾进行填充,使报文长度在对512取模以后的余数是448

    填充是这样进行的:先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。

    需要注意的是,信息必须进行填充,也就是说,即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512个比特。

    因此,填充是至少补一位,最多补512位。

    :以信息“abc”为例显示补位的过程。

    a,b,c对应的ASCII码分别是97,98,99

    于是原始信息的二进制编码为:01100001 01100010 01100011

    补位第一步,首先补一个“1” : 0110000101100010 01100011 1

    补位第二步,补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000

    补位完成后的数据如下(为了简介用16进制表示):

    61626380 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000
    

    为什么是448?

    因为在第一步的预处理后,第二步会再附加上一个64bit的数据,用来表示原始报文的长度信息。而448+64=512,正好拼成了一个完整的结构。

    STEP2:附加长度值

    附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。

    wiki百科中给出的原文是:append length of message (before pre-processing), in bits, as 64-bit big-endian integer

    SHA256用一个64位的数据来表示原始消息的长度。

    因此,通过SHA256计算的消息长度必须要小于$ 2^64 $,当然绝大多数情况这足够大了。

    长度信息的编码方式为64-bit big-endian integer

    关于Big endian的含义,文末给出了补充

    回到刚刚的例子,消息“abc”,3个字符,占用24个bit

    因此,在进行了补长度的操作以后,整个消息就变成下面这样了(16进制格式)

    61626380 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000018
    

    2.3 逻辑运算

    SHA256散列函数中涉及的操作全部是逻辑的位运算

    包括如下的逻辑函数:

    C h ( x , y , z ) = ( x ∧ y ) ⊕ ( ¬ x ∧ z ) Ch(x,y,z) = (x \land y) \oplus (\neg x \land z) Ch(x,y,z)=(xy)(¬xz)
    M a ( x , y , z ) = ( x ∧ y ) ⊕ ( x ∧ z ) ⊕ ( y ∧ z ) Ma(x,y,z) = (x \land y) \oplus (x \land z) \oplus (y \land z) Ma(x,y,z)=(xy)(xz)(yz)
    Σ 0 ( x ) = S 2 ( x ) ⊕ S 13 ( x ) ⊕ S 22 ( x ) \Sigma_{0}(x) = S^{2}(x) \oplus S^{13}(x) \oplus S^{22}(x) Σ0(x)=S2(x)S13(x)S22(x)
    Σ 1 ( x ) = S 6 ( x ) ⊕ S 11 ( x ) ⊕ S 25 ( x ) \Sigma_{1}(x) = S^{6}(x) \oplus S^{11}(x) \oplus S^{25}(x) Σ1(x)=S6(x)S11(x)S25(x)
    σ 0 ( x ) = S 7 ( x ) ⊕ S 18 ( x ) ⊕ R 3 ( x ) \sigma_{0}(x) = S^{7}(x) \oplus S^{18}(x) \oplus R^{3}(x) σ0(x)=S7(x)S18(x)R3(x)
    σ 1 ( x ) = S 17 ( x ) ⊕ S 19 ( x ) ⊕ R 10 ( x ) \sigma_{1}(x) = S^{17}(x) \oplus S^{19}(x) \oplus R^{10}(x) σ1(x)=S17(x)S19(x)R10(x)
    其中:

    逻辑运算含义
    ∧ \land 按位“与”
    ¬ \neg ¬按位“补”
    ⊕ \oplus 按位“异或”
    S n S^{n} Sn循环右移n个bit
    R n R^{n} Rn右移n个bit

    2.4 计算消息摘要

    现在来介绍SHA256算法的主体部分,即消息摘要是如何计算的。

    首先:将消息分解成512-bit大小的块

    (break message into 512-bit chunks)

    图::消息分为n个块1

    假设消息M可以被分解为n个块,于是整个算法需要做的就是完成n次迭代,n次迭代的结果就是最终的哈希值,即256bit的数字摘要。

    一个256-bit的摘要的初始值H0,经过第一个数据块进行运算,得到H1,即完成了第一次迭代

    H1经过第二个数据块得到H2,……,依次处理,最后得到Hn,Hn即为最终的256-bit消息摘要

    将每次迭代进行的映射用$ Map(H_{i-1}) = H_{i} $表示,于是迭代可以更形象的展示为:

    图::迭代过程2

    图中256-bit的Hi被描述8个小块,这是因为SHA256算法中的最小运算单元称为“字”(Word),一个字是32位。

    此外,第一次迭代中,映射的初值设置为前面介绍的8个哈希初值,如下图所示:

    图::哈希初值3

    下面开始介绍每一次迭代的内容,即映射$ Map(H_{i-1}) = H_{i} $的具体算法

    STEP1:构造64个字(word)

    break chunk into sixteen 32-bit big-endian words w[0], …, w[15]

    对于每一块,将块分解为16个32-bit的big-endian的字,记为w[0], …, w[15]

    也就是说,前16个字直接由消息的第i个块分解得到

    其余的字由如下迭代公式得到:

    W t = σ 1 ( W t − 2 ) + W t − 7 + σ 0 ( W t − 15 ) + W t − 16 W_{t} = \sigma_{1}(W_{t-2}) + W_{t-7} + \sigma_{0}(W_{t-15}) + W_{t-16} Wt=σ1(Wt2)+Wt7+σ0(Wt15)+Wt16

    STEP2:进行64次循环

    映射 $ Map(H_{i-1}) = H_{i} $ 包含了64次加密循环

    即进行64次加密循环即可完成一次迭代

    每次加密循环可以由下图描述:

    图::加密循环4

    图中,ABCDEFGH这8个字(word)在按照一定的规则进行更新,其中

    深蓝色方块是事先定义好的非线性逻辑函数,上文已经做过铺垫

    红色田字方块代表 mod $ 2^{32} $ addition,即将两个数字加在一起,如果结果大于$ 2^{32} , 你 必 须 除 以 ,你必须除以 2^{32} $并找到余数。

    ABCDEFGH一开始的初始值分别为$ H_{i-1}(0),H_{i-1}(1),…,H_{i-1}(7) $

    Kt是第t个密钥,对应我们上文提到的64个常量

    Wt是本区块产生第t个word。原消息被切成固定长度512-bit的区块,对每一个区块,产生64个word,通过重复运行循环n次对ABCDEFGH这八个字循环加密。

    最后一次循环所产生的八个字合起来即是第i个块对应到的散列字符串$ H_{i} $

    由此变完成了SHA256算法的所有介绍


    3. SHA256算法伪代码

    现在我们可以结合SHA256算法的伪代码,将上述的所有步骤进行梳理整合:

    Note: All variables are unsigned 32 bits and wrap modulo 232 when calculating
    
    
    Initialize variables
    (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19
    
    
    Initialize table of round constants
    (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
    k[0..63] :=
       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    
    
    Pre-processing:
    append the bit '1' to the message
    append k bits '0', where k is the minimum number >= 0 such that the resulting message
        length (in bits) is congruent to 448(mod 512)
    append length of message (before pre-processing), in bits, as 64-bit big-endian integer
    
    
    Process the message in successive 512-bit chunks:
    break message into 512-bit chunks
    for each chunk
        break chunk into sixteen 32-bit big-endian words w[0..15]
    
        Extend the sixteen 32-bit words into sixty-four 32-bit words:
        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
    
        Initialize hash value for this chunk:
        a := h0
        b := h1
        c := h2
        d := h3
        e := h4
        f := h5
        g := h6
        h := h7
    
        Main loop:
        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
    
        Add this chunk's hash to result so far:
        h0 := h0 + a
        h1 := h1 + b
        h2 := h2 + c
        h3 := h3 + d
        h4 := h4 + e
        h5 := h5 + f
        h6 := h6 + g
        h7 := h7 + h
    
    Produce the final hash value (big-endian):
    digest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
    

    4. 参考文献

    本篇笔记主要参考整合的资料如下:

    SHA-2 wiki

    比特币算法——SHA256算法介绍

    SHA-256算法实现

    操作指南:验证SHA256


    知识填补

    大端和小端(Big endian and Little endian)

    对于整型、长整型等数据类型,都存在字节排列的高低位顺序问题。

    Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节)

    而 Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放据的低位字节到高位字节)。

    例如,假设从内存地址 0x0000 开始有以下数据:

    地址数据
    0x00000x12
    0x00010x34
    0x00020xab
    0x00030xcd

    假设我们去读取一个地址为 0x0000 的四个字节变量

    若字节序为big-endian,则读出结果为0x1234abcd;

    若字节序为little-endian,则读出结果为0xcdab3412。

    如果我们将0x1234abcd 写入到以 0x0000 开始的内存中,则Little endian 和 Big endian 模式的存放结果如下:

    地址0x00000x00010x00020x0003
    big-Big_endian0x120x340xab0xcd
    little-endian0xcd0xab0x340x12

    参考文献

    点击返回正文

    展开全文
  • SHA加密算法

    2015-12-11 18:11:18
    SHA加密算法 亲测可用
  • sha加密算法是安全哈希算法(Secure Hash Algorithm)的简称,主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。主要包括SHA-1,SHA-224,SHA...

             sha加密算法是安全哈希算法(Secure Hash Algorithm)的简称,主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。主要包括SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512这几种单向散列算法。本篇就利用jdk自带的方法实现其中的几种加密算法。

             

    1. 首先我们自行配置开发环境并安装myeclipse软件,然后打开myeclipse软件,然后再导航菜单处点击File然后选择New-->Java Project。进行创建java项目。

      sha加密算法介绍以及java实现sha加密算法
    2.  

      然后我们在创建项目的页面,输入本次测试的项目名称:SHAJDKUtil,选择项目所需要的jre环境,此次测试中我们选择自定义配置好的jdk7。以上都编写完成后,然后点击Finish。进行创建java项目。

      sha加密算法介绍以及java实现sha加密算法
    3.  

      然后在我们刚刚创建好的项目上右击,选择New-->Class,进行实体类的创建。

      sha加密算法介绍以及java实现sha加密算法
    4.  

      在实体类创建界面,我们输入包名称为:com.util,类名称为:SHAUtil,然后勾选自动生成main函数。以上都正确后我们点击Finish。完成实体类的创建。

      sha加密算法介绍以及java实现sha加密算法
    5.  

      由于本项目内计算加密后的数据为byte数组形式,我们首先编写将byte数组转换为16进制字符串输出。本篇中方法名称为:convertByteToHexString。具体实现方式如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    6.  

      然后我们编写利用jdk自带的类实现SHA1加密算法。本篇中我们使用方法为:jdksha1,需要传入要加密的字符串。具体加密代码如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    7.  

      然后我们接着编写利用jdk自带的类实现SHA-256加密算法,本篇中我们编写的方法为:jdksha256,需要传入参数字符串。具体的加密代码如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    8.  

      然后我们接着编写利用jdk自带的类实现SHA-384加密算法,本篇中我们使用的方法为:jdksha384,需要参数字符串。具体的加密代码实现如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    9.  

      然后我们接着编写利用jdk自带的类实现SHA-512加密算法,本篇中我们使用的方法为:jdksha512,需要参数字符串。具体的加密代码实现如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    10.  

      最后我们在main方法内调用加密方法。对以上编写的加密方法进行测试。首先我们定义要加密的字符串为:jdksha,然后分别调用以上编写的不同加密方式的加密方法,具体实现方式如下图所示。

      sha加密算法介绍以及java实现sha加密算法
    11.  

      最后我们运行程序,查看结果信息可以看到已经加密成功。如下图所示,至此本篇教程完成。

      sha加密算法介绍以及java实现sha加密算法
    12.  

             

    展开全文
  • SHA2 签名算法兼容性列表

    千次阅读 2016-04-14 09:16:28
    但是,仍有一些较老的系统,诸如windows xp sp3以前的系统不支持sha2算法。  很多单位在转型由SHA1升级至sha2的时候,会遇到用户的体验问题,也就是兼容性。下面列举一些设备sha2的最小支持版本。 浏览器和服务器...
  • SHA散列算法

    2015-02-10 14:09:57
    SHA散列算法,可以非常方便的家密码散列成16进制数据。
  • sha256算法

    2017-07-30 16:39:38
    sha256加密签名算法
  • 哈希函数-SHA1和SHA256算法

    千次阅读 2020-09-25 14:23:13
    SHA2算法是对SHA1算法的继承。区别在于两者的构造和签名长度不同。 SHA1 SHA-1通过4轮运算(每轮20步,共80步)将长度不超过264的输入压缩成为160bit的消息摘要。 初始化MD缓冲区,需要160位来存放哈希函数的...
  • sha512算法程序

    2016-10-21 11:46:20
    sha512算法程序
  • sha512算法文件

    2016-10-21 10:40:44
    sha512算法文件
  • SHA 加密算法

    千次阅读 2019-06-21 23:43:39
    SHA 加密算法 算法简介 SHA安全散列算法SHA(Secure Hash Algorithm,SHA) 是美国国家标准技术研究所发布的国家标准FIPS PUB 180,最新的标准已经于2008年更新到FIPS PUB 180-3。...SHA-1,SHA-224和SHA-2...
  • SHA常用算法实现(SHA-1, SHA256, SHA384, SHA512),使用C语言,包含4个相对独立的算法,并有demo调用示例。
  • sha1算法demo

    2018-07-31 18:51:04
    sha1算法demo,可直接使用。 如有错误,欢迎拍砖
  • rsa算法SHA256算法

    2019-11-21 13:31:23
    1.主要解决同一套Java代码实现RSA加解密算吗,在.net和Android上使用时解密出来的结果不同的问题。(代码中兼容.net和Android) 2。代码中包含SHA256签名验签。 3.解密时还有点问题,
  • 利用对象实现SHA1算法

    2020-12-08 03:03:49
    为您提供利用对象实现SHA1算法下载,利用对象实现SHA1算法系统结构:取SHA1,取SHA1,======窗口程序集1| || |------ _按钮1_被单击| || |------ 取SHA1======窗口程序集1| || |------ _按钮1_被单击| || |------ 取SHA...
  • /*SHA1算法及HMAC<SHA1>算法C语言实现。内附详细测试例程。测试数据取自rfc2202.txt和rfc3174.txt。源文件列表: md5.h, md5.cpp, test.h, test.cpp, rfc2202.txt, rfc3174.txt。包含测试工程: VC++6.0, VC++2008, ...
  • SHA 编码算法

    2008-08-01 01:39:41
    SHA 编码算法 百度百科:http://baike.baidu.com/view/531723.htm
  • sha2 加密算法JS文件

    2008-11-04 12:39:20
    sha2 加密算法JS文件,javascript语言描述的sha算法
  • SHA256算法

    千次阅读 2018-05-10 20:48:39
    SHA-256 算法输入报文的最大长度不超过2^64 bit,输入按512-bit 分组进行处理,产生 的输出是一个256-bit 的报文摘要。该算法处理包括以下几步: STEP1:附加填充比特。对报文进行填充使报文长度与448 模512 同余...
  • AES SHA1算法

    2016-01-19 21:19:43
    AES SHA1加密算法.网上收集.整理硬盘发现的老东西,需要拿走
  • SHA256算法C++实现

    千次阅读 2019-11-14 14:03:16
    一、SHA256算法介绍与原理详解 见博客<<SHA256算法原理详解>> 二、SHA256算法C++实现 /* * Filename: sha256.hpp * Author: YF * Brief: SHA256算法实现 * Version: V1.0.0 * Update log: * 1)...
  • SHA1算法详解

    万次阅读 2018-08-25 13:30:00
    SHA1算法也是哈希算法的一种,只要理解了MD5算法SHA1也很快就能理解。 MD5算法可以参考:MD5算法详解 MD5算法得出的MD5值长度为16个字节(8*16=128位) SHA1算法得出的SHA1值长度为20个字节(8*20=160位) 0x...
  • sha1 算法的js 实现

    2016-07-29 14:48:04
    sha1 算法的js 实现
  • SHA512算法实现 uint32

    2018-08-12 21:10:04
    SHA512算法实现,使用uint32实现,适用于32位MCU,SHA512算法实现,使用uint32实现,适用于32位MCU
  • Python SHA1算法.pdf

    2021-08-06 15:38:06
    Python SHA1算法.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,550
精华内容 36,620
关键字:

sha2算法