闲来无事,造个哈希轮子,SHA384/SHA512这两者原理及实现一样的,只是输出和初始化的向量不一样。

原型

hash_val = sha512/384(message).
hash_val: SHA512输出是512bit(64个byte),SHA384输出是384bit(48个byte)
message: 0 < bits(message) < 2^128,message的最长不超过2^128 bits。

原理

其实SHA2的原理很简单,维基百科上也有很多说明:https://en.wikipedia.org/wiki/SHA-2。
这里就结合后面代码实现简单概述一下。
SHA512首先会将填充message到1024 bits的整数倍。然后将message分成若干个1024 bits的block。循环对每一个block进行处理,最终得到哈希值。如下图可以看到,在算法住处有一个512 bits的初始向量IV=H0, 然后与一个block进行运算得到H1,接着H1会与第二个block进行运算得到H2,经过(len(message) / 1024)次的迭代运算后,得到最终512 bits的Hash码。

填充消息

  • 1.将message转换成byte数组。
  • 2.填充message 直至长度为 896 = bits(message)%1024。这里需要注意的是即使message已经是1024bits的整数倍,比如一个message的长度正好是1024bits,还是需要继续填充的。下面举三个例子。
message 原始长度 填充后长度 附加message bit数后的长度
123456 48 bits 896 bits 1024 bits
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
1024 bits 1920 bits 2048 bits
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
123456
1030 bits 1920 bits 2048 bits

填充规则如下:填充的第一个bit是1,其余都是0。

  • 3.将message的长度(位数)以大端模式填到填充后的message的尾部,再次填充128bit,使最终填充的message的长度正好是1024 bits的整数倍。

设置初始值

SHA512/384 以1024个bit作为一个block,SHA512和SHA384的初始向量不同,其他的流程都是一样的,这里只看SHA512的初始向量,一共是512 bits,这个是固定不变的。

        A = 0x6a09e667f3bcc908ULL;B = 0xbb67ae8584caa73bULL;C = 0x3c6ef372fe94f82bULL;D = 0xa54ff53a5f1d36f1ULL;E = 0x510e527fade682d1ULL;F = 0x9b05688c2b3e6c1fULL;G = 0x1f83d9abfb41bd6bULL; H = 0x5be0cd19137e2179ULL;

循环运算

从图1可以知道每次运算的中间结果H[n]都是H[n-1] 和 block[n]进行运算得到的。每一次跌倒运算都要经过80轮的加工。下图是一轮加工的过程。假设现在第一轮运算,那么ABCDEFGH就是H[n-1],然后经过一轮运算后得到temp1[ABCDEFGH],然后temp1进行第二轮加工得到temp2,如此进行80轮之后,最终ABCDEFGH就是我们要得到H[n]。

在这幅图中,我们并没有看到block[n]在哪里,看图上的Wt和Kt,t代表该轮的轮数。K是一个固定的5120 bits向量,定义如下:

static const uint64_t 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
};

W也是一个5120 bits向量,它的值是由每一个block(1024 bits)计算而来,这个计算关系是固定的,如下,其中

    uint64_t W[80];/* 1. Calculate the W[80] */for(i = 0; i < 16; i++) {sha512_decode(&W[i], block, i << 3 );}for(; i < 80; i++) {W[i] = GAMMA1(W[i -  2]) + W[i -  7] + GAMMA0(W[i - 15]) + W[i - 16];}

好了,知道了W和K之后我们就看一看图中的Ch Ma,Sigma0和Sigma1的定义。
,
折合成C语言,代码如下:

#define LSR(x,n) (x >> n)
#define ROR(x,n) (LSR(x,n) | (x << (64 - n)))#define MA(x,y,z) ((x & y) | (z & (x | y)))
#define CH(x,y,z) (z ^ (x & (y ^ z)))
#define GAMMA0(x) (ROR(x, 1) ^ ROR(x, 8) ^  LSR(x, 7))
#define GAMMA1(x) (ROR(x,19) ^ ROR(x,61) ^  LSR(x, 6))
#define SIGMA0(x) (ROR(x,28) ^ ROR(x,34) ^ ROR(x,39))
#define SIGMA1(x) (ROR(x,14) ^ ROR(x,18) ^ ROR(x,41))

知道这些之后再来看每一轮运算的代码就非常简单

#define COMPRESS( a,  b,  c, d,  e,  f,  g,  h, x,  k)   \tmp0 = h + SIGMA1(e) + CH(e,f,g) + k + x;              \tmp1 = SIGMA0(a) + MA(a,b,c); d += tmp0; h = tmp0 + tmp1;

保存运算结果

完成迭代运算后,Hash码保存到了最终的ABCDEFGH中,然后将这些向量按照大端模式输出。

代码实现

sha512_ctx_t定义了SHA512所需要的上下文

easy_sha512.h

/** Copyright (c) 2018, Jiamin Ma* BSD License*/
#ifndef EASY_SHA512_H
#define EASY_SHA512_H#include "easy_crypto.h"#ifdef CRYPTO_DEBUG_SUPPORT
#define SHA512_DEBUG printf
#else
#define SHA512_DEBUG(fmt, ...)
#endif/*** @brief   Convert uint64_t to big endian byte array.* @param   input       input uint64_t data* @param   output      output big endian byte array* @param   idx         idx of the byte array.* @retval  void*/
static void inline sha512_encode(uint64_t input, uint8_t *output, uint32_t idx)
{output[idx + 0] = (uint8_t)(input >> 56);output[idx + 1] = (uint8_t)(input >> 48);output[idx + 2] = (uint8_t)(input >> 40);output[idx + 3] = (uint8_t)(input >> 32);output[idx + 4] = (uint8_t)(input >> 24);output[idx + 5] = (uint8_t)(input >> 16);output[idx + 6] = (uint8_t)(input >>  8);output[idx + 7] = (uint8_t)(input >>  0);
}/*** @brief   Convert big endian byte array to uint64_t data* @param   output      output uint64_t data* @param   input       input big endian byte array* @param   idx         idx of the byte array.* @retval  void*/
static inline void sha512_decode(uint64_t *output, uint8_t *input, uint32_t idx)
{*output = ((uint64_t)input[idx + 0] << 56)| ((uint64_t)input[idx + 1] << 48)| ((uint64_t)input[idx + 2] << 40)| ((uint64_t)input[idx + 3] << 32)| ((uint64_t)input[idx + 4] << 24)| ((uint64_t)input[idx + 5] << 16)| ((uint64_t)input[idx + 6] <<  8)| ((uint64_t)input[idx + 7] <<  0);
}typedef struct sha512_ctx_tag {uint32_t is_sha384;/*SHA512 process the data by one block:1024 bits*/uint8_t block[128];/*SHA512 will fill 128 bits length field: unit:bit*/uint64_t len[2];/*Hash values*/uint64_t val[8];/*Payload address to hash*/uint8_t *payload_addr;/*Payload length*/uint64_t payload_len;
} sha512_ctx_t;#define LSR(x,n) (x >> n)
#define ROR(x,n) (LSR(x,n) | (x << (64 - n)))#define MA(x,y,z) ((x & y) | (z & (x | y)))
#define CH(x,y,z) (z ^ (x & (y ^ z)))
#define GAMMA0(x) (ROR(x, 1) ^ ROR(x, 8) ^  LSR(x, 7))
#define GAMMA1(x) (ROR(x,19) ^ ROR(x,61) ^  LSR(x, 6))
#define SIGMA0(x) (ROR(x,28) ^ ROR(x,34) ^ ROR(x,39))
#define SIGMA1(x) (ROR(x,14) ^ ROR(x,18) ^ ROR(x,41))#define INIT_COMPRESSOR() uint64_t tmp0 = 0, tmp1 = 0
#define COMPRESS( a,  b,  c, d,  e,  f,  g,  h, x,  k)   \tmp0 = h + SIGMA1(e) + CH(e,f,g) + k + x;              \tmp1 = SIGMA0(a) + MA(a,b,c); d += tmp0; h = tmp0 + tmp1;#endif /*EASY_SHA512_H*/

实现代码很简单,easy_sha512_impl是主流程,分为三步
1. sha512_init初始化SHA512根据消息的长度和起始地址的上下文。
2. sha512_stage1处理数据直到倒数第二个block,将其中间Hash值保存在sha512_ctx_t的val向量中。如果消息的原始长度小于1024 bits,那么这个函数将不处理,因为倒数第二个block不存在,只存在一个1024 bits的block。参考表1的message = 123456。从代码实现中可以看到消息的字节数小于128时,不做任何处理,否则循环处理每一个block。
3. sha512_stage2处理处理填充后的message的最后一个block,将上一次的Hasn中间结果和该block进行运算得到最终的Hash并且保存到output中。
4. sha512_hash_factory就是处理每一个block得到其中间结果的函数,里面逻辑很简单,首先初始化了W向量,然后计算80轮的加工,最终将得到中间结果保存到sha512_ctx_t的val中。

easy_sha512.c

/** Copyright (c) 2018, Jiamin Ma* BSD License*/
#include "easy_sha512.h"
#include <stdio.h>/** Predefined sha512 padding bytes*/
static const uint8_t sha512_padding[128] =
{0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};/** K byte array used for iteration*/
static const uint64_t 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
};static inline void sha512_memcpy(uint8_t *src, uint8_t *dst, uint32_t size)
{uint32_t i = 0;for (;i < size;i++) {*dst++ = *src++;}
}static inline void sha512_memclr(uint8_t *dst, uint32_t size)
{uint32_t i = 0;for (;i < size;i++) {*dst++ = 0;}
}/*** @brief   Init the SHA384/SHA512 Context* @param   sha512_ctx      SHA384/512 context* @param   payload         address of the hash payload* @param   payload_len     length of the hash payload* @param   is_sha384       0:SHA512, 1:SHA384* @retval  crypto_status_t* @return  CRYPTO_FAIL if hash failed*          CRYPTO_SUCCESS if hash successed*/
static crypto_status_t sha512_init(sha512_ctx_t *sha512_ctx, uint8_t *payload_addr, uint64_t payload_len, uint32_t is_sha384)
{crypto_status_t ret = CRYPTO_FAIL;SHA512_DEBUG("%s\n", __func__);if (payload_len == 0 || payload_addr == NULL) {SHA512_DEBUG("%s parameter illegal\n", __func__);goto cleanup;}sha512_memclr((uint8_t *)sha512_ctx, sizeof(sha512_ctx_t));if (1 == is_sha384) {SHA512_DEBUG("%s SHA384\n", __func__);sha512_ctx->val[0] = 0xCBBB9D5DC1059ED8ULL;sha512_ctx->val[1] = 0x629A292A367CD507ULL;sha512_ctx->val[2] = 0x9159015A3070DD17ULL;sha512_ctx->val[3] = 0x152FECD8F70E5939ULL;sha512_ctx->val[4] = 0x67332667FFC00B31ULL;sha512_ctx->val[5] = 0x8EB44A8768581511ULL;sha512_ctx->val[6] = 0xDB0C2E0D64F98FA7ULL;sha512_ctx->val[7] = 0x47B5481DBEFA4FA4ULL;} else {SHA512_DEBUG("%s SHA512\n", __func__);sha512_ctx->val[0] = 0x6A09E667F3BCC908ULL;sha512_ctx->val[1] = 0xBB67AE8584CAA73BULL;sha512_ctx->val[2] = 0x3C6EF372FE94F82BULL;sha512_ctx->val[3] = 0xA54FF53A5F1D36F1ULL;sha512_ctx->val[4] = 0x510E527FADE682D1ULL;sha512_ctx->val[5] = 0x9B05688C2B3E6C1FULL;sha512_ctx->val[6] = 0x1F83D9ABFB41BD6BULL;sha512_ctx->val[7] = 0x5BE0CD19137E2179ULL;}sha512_ctx->is_sha384 = is_sha384;sha512_ctx->payload_addr = payload_addr;sha512_ctx->payload_len = (uint64_t)payload_len;sha512_ctx->len[0] = payload_len << 3;sha512_ctx->len[1] = payload_len >> 61;ret = CRYPTO_SUCCESS;cleanup:return ret;
}/*** @brief   SHA384/512 iteration compression* @param   sha512_ctx        context of the sha384/512* @param   data              hash block data, 1024 bits.* @retval  crypto_status_t* @return  CRYPTO_FAIL if failed*          CRYPTO_SUCCESS if successed*/
static crypto_status_t sha512_hash_factory(sha512_ctx_t *ctx, uint8_t data[128])
{uint32_t i = 0;uint64_t W[80];/* One iteration vectors* v[0] --> A* ...* v[7] --> H* */uint64_t v[8];INIT_COMPRESSOR();SHA512_DEBUG("%s\n", __func__);/* 1. Calculate the W[80] */for(i = 0; i < 16; i++) {sha512_decode(&W[i], data, i << 3 );}for(; i < 80; i++) {W[i] = GAMMA1(W[i -  2]) + W[i -  7] + GAMMA0(W[i - 15]) + W[i - 16];}/* 2.Init the vectors */for (i = 0;i < 8; i++) {v[i] = ctx->val[i];}/* 3. Iteration to do the SHA-2 family compression. */for(i = 0; i < 80;) {COMPRESS(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], W[i], K[i] ); i++;COMPRESS(v[7], v[0], v[1], v[2], v[3], v[4], v[5], v[6], W[i], K[i] ); i++;COMPRESS(v[6], v[7], v[0], v[1], v[2], v[3], v[4], v[5], W[i], K[i] ); i++;COMPRESS(v[5], v[6], v[7], v[0], v[1], v[2], v[3], v[4], W[i], K[i] ); i++;COMPRESS(v[4], v[5], v[6], v[7], v[0], v[1], v[2], v[3], W[i], K[i] ); i++;COMPRESS(v[3], v[4], v[5], v[6], v[7], v[0], v[1], v[2], W[i], K[i] ); i++;COMPRESS(v[2], v[3], v[4], v[5], v[6], v[7], v[0], v[1], W[i], K[i] ); i++;COMPRESS(v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[0], W[i], K[i] ); i++;}/* 4. Move the vectors to hash output */for (i = 0; i < 8; i++) {ctx->val[i] += v[i];}return CRYPTO_SUCCESS;
}/*** @brief   SHA384/512 stage1* @param   sha512_ctx        context of the sha384/512* @param   output            output of hash value* @retval  crypto_status_t* @return  CRYPTO_FAIL if failed*          CRYPTO_SUCCESS if successed*/
static crypto_status_t sha512_stage1(sha512_ctx_t *sha512_ctx)
{SHA512_DEBUG("%s\n", __func__);while (sha512_ctx->payload_len >= 128) {sha512_hash_factory(sha512_ctx, sha512_ctx->payload_addr);sha512_ctx->payload_addr += 128;sha512_ctx->payload_len -= 128;SHA512_DEBUG("%x, %x\n", (uint32_t) sha512_ctx->payload_addr, (uint32_t) sha512_ctx->payload_len);}return CRYPTO_SUCCESS;
}/*** @brief   SHA384/512 stage2:Do padding and digest the fianl bytes* @param   sha512_ctx        context of the sha384/512* @param   output            output of hash value* @retval  crypto_status_t* @return  CRYPTO_FAIL if failed*          CRYPTO_SUCCESS if successed*/
static crypto_status_t sha512_stage2(sha512_ctx_t *sha512_ctx,uint8_t output[64])
{uint32_t block_pos = sha512_ctx->payload_len;uint32_t padding_bytes = 0;uint8_t temp_data[128] = {0};uint8_t *temp_data_p = (uint8_t *)&temp_data[0];uint8_t len_be[16] = {0};uint8_t i = 0;SHA512_DEBUG("%s\n", __func__);/*Copy the last byte to the temp buffer*/sha512_memcpy(sha512_ctx->payload_addr, temp_data_p, sha512_ctx->payload_len);padding_bytes = 112 - block_pos;temp_data_p += block_pos;/*Copy the padding byte to the temp buffer*/sha512_memcpy((uint8_t *)sha512_padding, temp_data_p, padding_bytes);temp_data_p += padding_bytes;/*Append the length*/sha512_encode(sha512_ctx->len[1], len_be, 0);sha512_encode(sha512_ctx->len[0], len_be, 8);sha512_memcpy(len_be, temp_data_p, 16);sha512_hash_factory(sha512_ctx, temp_data);/*encode the hash val to big endian byte array*/for (i = 0; i < 6; i++) {sha512_encode(sha512_ctx->val[i], output, i * 8);}/*No need to encode the last 16 bytes for SHA384*/for ( ;(i < 8) && (sha512_ctx->is_sha384 == 0); i++) {sha512_encode(sha512_ctx->val[i], output, i * 8);}return CRYPTO_SUCCESS;
}/*** @brief   SHA384/512 implementation function* @param   payload         address of the hash payload* @param   payload_len     length of the hash payload* @param   hash            output of hash value* @param   is_sha384       0:SHA512, 1:SHA384* @retval  crypto_status_t* @return  CRYPTO_FAIL if hash failed*          CRYPTO_SUCCESS if hash successed*/
crypto_status_t easy_sha512_impl(uint8_t *payload, uint64_t payload_len,uint8_t output[64], uint32_t is_sha384)
{crypto_status_t ret = CRYPTO_FAIL;sha512_ctx_t g_sha512_ctx;ret = sha512_init(&g_sha512_ctx, payload, payload_len, is_sha384);if (ret != CRYPTO_SUCCESS) {goto cleanup;}ret = sha512_stage1(&g_sha512_ctx);if (ret != CRYPTO_SUCCESS) {goto cleanup;}ret = sha512_stage2(&g_sha512_ctx, output);cleanup:return ret;
}/*** @brief   API for SHA512* @param   payload         address of the hash payload* @param   payload_len     length of the hash payload* @param   hash            output of hash value* @retval  crypto_status_t* @return  CRYPTO_FAIL if hash failed*          CRYPTO_SUCCESS if hash successed*/
crypto_status_t easy_sha512(uint8_t *payload, uint64_t payload_len, uint8_t hash[64])
{return easy_sha512_impl(payload, payload_len, hash, 0);
}/*** @brief   API for SHA384* @param   payload         address of the hash payload* @param   payload_len     length of the hash payload* @param   hash            output of hash value* @retval  crypto_status_t* @return  CRYPTO_FAIL if hash failed*          CRYPTO_SUCCESS if hash successed*/
crypto_status_t easy_sha384(uint8_t *payload, uint64_t payload_len, uint8_t hash[64])
{return easy_sha512_impl(payload, payload_len, hash, 1);
}

配置头文件
定义CRYPTO_DEBUG_SUPPORT宏可以打开DEBUG打印。
easy_crypto.h

/** Copyright (c) 2018, Jiamin Ma* BSD License*/
#ifndef EASY_CRYPTO_H
#define EASY_CRYPTO_H#include <stdint.h>#ifdef CRYPTO_DEBUG_SUPPORT
#include <stdio.h>
#endiftypedef uint32_t crypto_status_t;
#define CRYPTO_FAIL             0x5A5A5A5AUL
#define CRYPTO_SUCCESS          0xA5A5A5A5ULextern crypto_status_t easy_sha512(uint8_t *payload, uint64_t payaload_len, uint8_t hash[64]);
extern crypto_status_t easy_sha384(uint8_t *payload, uint64_t payaload_len, uint8_t hash[64]);#endif /*EASY_CRYPTO_H*/

测试

测试命令
gcc main.c easy_sha512.c -o sha512
./sha512
SHA384 Test 0 Passed
SHA384 Test 1 Passed
SHA384 Test 2 Passed
SHA512 Test 0 Passed
SHA512 Test 1 Passed
SHA512 Test 2 Passed

分别测试了表1中的3个消息的SHA384和SHA512。
main.c

/** Copyright (c) 2018, Jiamin Ma* BSD License*/
#include "easy_crypto.h"
#include <stdio.h>
#include <stdint.h>#define TEST_VEC_NUM 3
static const uint8_t sha384_res0[TEST_VEC_NUM][48] = {{0x0a,0x98,0x9e,0xbc,0x4a,0x77,0xb5,0x6a,0x6e,0x2b,0xb7,0xb1,0x9d,0x99,0x5d,0x18,0x5c,0xe4,0x40,0x90,0xc1,0x3e,0x29,0x84,0xb7,0xec,0xc6,0xd4,0x46,0xd4,0xb6,0x1e,0xa9,0x99,0x1b,0x76,0xa4,0xc2,0xf0,0x4b,0x1b,0x4d,0x24,0x48,0x41,0x44,0x94,0x54,},{0xf9,0x32,0xb8,0x9b,0x67,0x8d,0xbd,0xdd,0xb5,0x55,0x80,0x77,0x03,0xb3,0xe4,0xff,0x99,0xd7,0x08,0x2c,0xc4,0x00,0x8d,0x3a,0x62,0x3f,0x40,0x36,0x1c,0xaa,0x24,0xf8,0xb5,0x3f,0x7b,0x11,0x2e,0xd4,0x6f,0x02,0x7f,0xf6,0x6e,0xf8,0x42,0xd2,0xd0,0x8c,},{0x4e,0x72,0xf4,0x07,0x66,0xcd,0x1b,0x2f,0x23,0x1b,0x9c,0x14,0x9a,0x40,0x04,0x6e,0xcc,0xc7,0x2d,0xa9,0x1d,0x5a,0x02,0x42,0xf6,0xab,0x49,0xfe,0xea,0x4e,0xfd,0x55,0x43,0x9b,0x7e,0xd7,0x82,0xe0,0x3d,0x69,0x0f,0xb9,0x78,0xc3,0xdb,0xce,0x91,0xc1},
};static const uint8_t sha512_res0[TEST_VEC_NUM][64] = {{0xba,0x32,0x53,0x87,0x6a,0xed,0x6b,0xc2,0x2d,0x4a,0x6f,0xf5,0x3d,0x84,0x06,0xc6,0xad,0x86,0x41,0x95,0xed,0x14,0x4a,0xb5,0xc8,0x76,0x21,0xb6,0xc2,0x33,0xb5,0x48,0xba,0xea,0xe6,0x95,0x6d,0xf3,0x46,0xec,0x8c,0x17,0xf5,0xea,0x10,0xf3,0x5e,0xe3,0xcb,0xc5,0x14,0x79,0x7e,0xd7,0xdd,0xd3,0x14,0x54,0x64,0xe2,0xa0,0xba,0xb4,0x13},{0x45,0x1e,0x75,0x99,0x6b,0x89,0x39,0xbc,0x54,0x0b,0xe7,0x80,0xb3,0x3d,0x2e,0x5a,0xb2,0x0d,0x6e,0x2a,0x2b,0x89,0x44,0x2c,0x9b,0xfe,0x6b,0x47,0x97,0xf6,0x44,0x0d,0xac,0x65,0xc5,0x8b,0x6a,0xff,0x10,0xa2,0xca,0x34,0xc3,0x77,0x35,0x00,0x8d,0x67,0x10,0x37,0xfa,0x40,0x81,0xbf,0x56,0xb4,0xee,0x24,0x37,0x29,0xfa,0x5e,0x76,0x8e},{0x51,0x33,0x35,0xc0,0x7d,0x10,0xed,0x85,0xe7,0xdc,0x3c,0xa9,0xb9,0xf1,0x1a,0xe7,0x59,0x1e,0x5b,0x36,0xf9,0xb3,0x71,0xfb,0x66,0x21,0xb4,0xec,0x6f,0xc8,0x05,0x57,0xfe,0x1e,0x7b,0x9e,0x1c,0xc1,0x12,0x32,0xb0,0xb2,0xdd,0x92,0x1d,0x80,0x56,0xbf,0x09,0x7a,0x91,0xc3,0x6d,0xd7,0x28,0x46,0x71,0xfc,0x46,0x8e,0x06,0x17,0x49,0xf4},
};static char *test_vectors[TEST_VEC_NUM]= {"123456","0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123456",
};static uint32_t vector_len[TEST_VEC_NUM] = {6, 128, 134};int main()
{uint8_t output[64];uint32_t i = 0, j = 0;for (i = 0; i < TEST_VEC_NUM; i++) {easy_sha384(test_vectors[i], vector_len[i], output);for (j = 0; j < 48; j++) {if (output[j] != sha384_res0[i][j]) {printf("SHA384 Test %d Failed\n", i);printf("hash should be %x, calu:%x\n",  sha384_res0[i][j], output[j]);break;}}if (j == 48) {printf("SHA384 Test %d Passed\n", i);}}for (i = 0; i < TEST_VEC_NUM; i++) {easy_sha512(test_vectors[i], vector_len[i], output);for (j = 0; j < 64; j++) {if (output[j] != sha512_res0[i][j]) {printf("SHA512 Test %d Failed\n", i);printf("hash should be %x, calu:%x\n",  sha512_res0[i][j], output[j]);break;}}if (j == 64) {printf("SHA512 Test %d Passed\n", i);}}
}

SHA512/384 原理及C语言实现(附源码)相关推荐

  1. Visual Studio 控制台程序世界杯足球C语言版(附源码)

    Visual Studio 控制台程序世界杯足球C语言版 程序之美 前言 主体 运行效果 核心代码 逻辑分析 结束语 程序之美 前言 一年一度的世界杯如期而至,相信很多球迷小伙伴们一定不会错过这个难得 ...

  2. B树的原理以及C++实现(附源码和文档)

    B树的C++实现 之前课程设计做的一个BTrees数据结构,在这里添加了算法说明的PDF文档以及配套的Latex文档,同时有源代码和详细的说明,算法思路全部来自于算法导论,,需要的同学直接拿走..喜欢 ...

  3. SHA512系列哈希算法原理及实现(附源码)

    相关文章: SHA512系列哈希算法原理及实现(附源码) SHA224和SHA256哈希算法原理及实现(附源码) 国密SM3哈希算法原理及实现(附源码) SHA1哈希算法原理及实现(附源码) MD5哈 ...

  4. SHA3系列(KECCAK)哈希算法原理及实现(附源码)

    相关文章: (本文持续更新中) SHA3系列(KECCAK)哈希算法原理及实现(附源码) SHA512系列哈希算法原理及实现(附源码) SHA224和SHA256哈希算法原理及实现(附源码) 国密SM ...

  5. SHA224和SHA256哈希算法原理及实现(附源码)

    相关文章: SHA224和SHA256哈希算法原理及实现(附源码) 国密SM3哈希算法原理及实现(附源码) SHA1哈希算法原理及实现(附源码) MD5哈希算法原理及实现(附源码) MD4哈希算法原理 ...

  6. 免费开源的高精度OCR文本提取,支持 100 多种语言、自动文本定位和脚本检测,几行代码即可实现离线使用(附源码)

    免费开源的高精度OCR文本提取,支持 100 多种语言.自动文本定位和脚本检测,几行代码即可实现离线使用(附源码). 要从图像.照片中提取文本吗?是否刚刚拍了讲义的照片并想将其转换为文本?那么您将需要 ...

  7. 谁说程序员不懂浪漫——我的C语言结婚请柬(附源码)

    前言:但行好事,莫问前程--<增广贤文> 从上学起开始学C++,后面也做过H5,现在做Android.无论是学习用的,还是工作用的,上百个软件不止.但最另我骄傲的是,我用程序烂漫了一把. ...

  8. 国密SM3密码杂凑算法原理及实现(附源码)

    相关文章: 国密SM3哈希算法原理及实现(附源码) SHA1哈希算法原理及实现(附源码) MD5哈希算法原理及实现(附源码) MD4哈希算法原理及实现(附源码) MD2哈希算法原理及实现(附源码) M ...

  9. C语言——史上最全通讯录讲解(附源码)

    C语言--史上最全通讯录讲解(附源码) 一.开始界面的打印 二.对六大板块进行定义操作 三.对联系人进行初始化 四.对通讯录进行初始化 4.1动态版本 4.2静态版本 五.通讯录六大功能的具体实现 5 ...

最新文章

  1. 基于机器学习的文本分类!
  2. 博士在读却连矩阵的秩都搞不清,我该如何毕业?
  3. Use After Free Tutorial
  4. Python爬虫入门(5):URLError异常处理
  5. 电脑教程从入门到精通_如何自学原画设计|新手如何开始学原画?(附视频教程从入门到精通)...
  6. 通过Source insight查看内核源码
  7. NTFS USN的Create和工具代码汇总
  8. 【Servlet】请求转发与重定向
  9. MyBatis框架 注解
  10. AdvancedWindowsPasswordRecovery3 及 注册码
  11. python scipy库函数solve用法_python scipy linalg.solve_banded用法及代码示例
  12. 如何查看chrome的版本
  13. 数据通信最新技术复习
  14. 如何修改文件的编码格式
  15. 域名是否被墙的辨别及解决方法
  16. 攻击与脆弱性之间的关系
  17. 娱乐篇~最近挺火的520遍我爱你源码和利用大数计算1~50的阶乘
  18. 计算机毕业设计之java+ssm校园视频监控系统
  19. Linux下python的卸载与安装
  20. 【洛谷题解/TJOI2007】P3853路标设置

热门文章

  1. 连续激光电源市场现状及未来发展趋势分析
  2. mysql 提现_第四站——网贷平台数据分析(MySQL篇)
  3. vscode初次远程连接服务器报错解决
  4. 【数据库】学生档案管理系统
  5. java 根据mac地址获取ip_java根据本地IP获取mac地址的方法
  6. tomcat窗口中文乱码
  7. CentOS7安装Proxychains实现linux代理
  8. PCA(explained_variance_ratio_与explained_variance_)
  9. 计算机病毒可以破坏网络吗,计算机病毒的主要危害
  10. SAP知识精解-物料需求计划MRP-概览