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

2024-06-03 17:48

本文主要是介绍SHA512/384 原理及C语言实现(附源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

闲来无事,造个哈希轮子,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数后的长度
12345648 bits896 bits1024 bits
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
1024 bits1920 bits2048 bits
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef
123456
1030 bits1920 bits2048 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语言实现(附源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027680

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl