当前位置:网站首页>SHA512 / 384 principle and C language implementation (with source code)
SHA512 / 384 principle and C language implementation (with source code)
2022-04-23 13:15:00 【MyeDy】
Be free and at leisure , Make a hash wheel ,SHA384/SHA512 The principle and implementation of the two are the same , Only the output and initialization vectors are different .
Prototype
hash_val = sha512/384(message).
hash_val: SHA512 The output is 512bit(64 individual byte),SHA384 The output is 384bit(48 individual byte)
message: 0 < bits(message) < 2^128,message The maximum length of shall not exceed 2^128 bits.
principle
Actually SHA2 It's very simple , Wikipedia also has a lot of instructions :https://en.wikipedia.org/wiki/SHA-2.
Here is a brief overview of the code implementation .
SHA512 First, we will fill message To 1024 bits Integer multiple . And then message Divided into several 1024 bits Of block. Loop for each block To deal with , Finally get the hash value . As can be seen in the figure below , There is one in the algorithm residence 512 bits The initial vector of IV=H0, And then with a block Calculate to get H1, next H1 Will be with the second block Calculate to get H2, after (len(message) / 1024) After several iterations , Get the final 512 bits Of Hash code .
Fill in the message
- 1. take message convert to byte Array .
- 2. fill message Until the length is 896 = bits(message)%1024. It should be noted here that even if message It's already 1024bits Integer multiple , For example, a message It's exactly the length of 1024bits, It still needs to be filled . Here are three examples .
message | Original length | Length after filling | additional message bit The length after counting |
---|---|---|---|
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 |
The filling rules are as follows : Fill the first bit yes 1, The rest are 0.
- 3. take message The length of ( digit ) Fill in the filled... In the big end mode message Tail of , Refill 128bit, Make the final fill message It's exactly the length of 1024 bits Integer multiple .
Set initial value
SHA512/384 With 1024 individual bit As a block,SHA512 and SHA384 The initial vectors are different , Other processes are the same , It's just here SHA512 The initial vector of , Is the total 512 bits, This is fixed .
A = 0x6a09e667f3bcc908ULL;
B = 0xbb67ae8584caa73bULL;
C = 0x3c6ef372fe94f82bULL;
D = 0xa54ff53a5f1d36f1ULL;
E = 0x510e527fade682d1ULL;
F = 0x9b05688c2b3e6c1fULL;
G = 0x1f83d9abfb41bd6bULL;
H = 0x5be0cd19137e2179ULL;
Loop operation
From the picture 1 You can know the intermediate result of each operation H[n] All are H[n-1] and block[n] Calculated . Every time you fall, you have to go through 80 Machining of wheel . The following figure shows the process of a round of machining . Suppose now the first round of operation , that ABCDEFGH Namely H[n-1], Then after a round of calculation, we get temp1[ABCDEFGH], then temp1 Carry out the second round of processing to get temp2, Do so 80 After the round , Final ABCDEFGH Is that we want to get H[n].
In this picture , We didn't see block[n] Where is the , Look at the picture Wt and Kt,t Represents the number of rounds of this round .K It's a fixed 5120 bits vector , The definition is as follows :
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 Also a 5120 bits vector , Its value is determined by each block(1024 bits) Come by calculation , This calculation relationship is fixed , as follows , among
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];
}
Okay , got it W and K Then let's take a look at the Ch Ma,Sigma0 and Sigma1 The definition of .
,
Converted into C Language , The code is as follows :
#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))
After knowing this, it is very simple to look at the code of each round of operation
#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;
Save the results
After completing the iterative operation ,Hash The code is saved to the final ABCDEFGH in , Then output these vectors in big end mode .
Code implementation
sha512_ctx_t Defined SHA512 The context required
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*/
The implementation code is simple ,easy_sha512_impl It's the mainstream process , There are three steps
1. sha512_init initialization SHA512 According to the length of the message and the context of the starting address .
2. sha512_stage1 Process the data until the penultimate block, Put it in the middle Hash Values are saved in sha512_ctx_t Of val Vector . If the original length of the message is less than 1024 bits, Then this function will not handle , Because the penultimate block non-existent , There is only one 1024 bits Of block. Refer to table 1 Of message = 123456. From the code implementation, we can see that the number of bytes of the message is less than 128 when , Do nothing , Otherwise, cycle through each block.
3. sha512_stage2 Process the filled message The last block, Will the last Hasn Intermediate results and the block Calculate to get the final Hash And save to output in .
4. sha512_hash_factory Is to deal with every block The function that gets the intermediate result , The logic is simple , First, initialize W vector , And then calculate 80 Machining of wheel , Finally, save the intermediate results to sha512_ctx_t Of val in .
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);
}
Configuration header file
Definition CRYPTO_DEBUG_SUPPORT Macros can open DEBUG Print .
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>
#endif
typedef uint32_t crypto_status_t;
#define CRYPTO_FAIL 0x5A5A5A5AUL
#define CRYPTO_SUCCESS 0xA5A5A5A5UL
extern 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*/
test
The test command
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
The tables were tested separately 1 Medium 3 A message SHA384 and 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);
}
}
}
版权声明
本文为[MyeDy]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230612364661.html
边栏推荐
- Translation of attention in natural language processing
- The use of dcast and melt in R language is simple and easy to understand
- AUTOSAR from introduction to mastery 100 lectures (83) - bootloader self refresh
- XML
- Pyqt5 store opencv pictures into the built-in sqllite database and query
- 【快排】215. 数组中的第K个最大元素
- Mui close other pages and keep only the first page
- 4.22 study record (you only did water problems in one day, didn't you)
- AUTOSAR from introduction to mastery 100 lectures (51) - AUTOSAR network management
- CSDN高校俱乐部“名师高校行”——湖南师范大学站
猜你喜欢
普通大学生如何拿到大厂offer?敖丙教你一招致胜!
The difference between string and character array in C language
MySQL5.5安装教程
@优秀的你!CSDN高校俱乐部主席招募!
Design of body fat detection system based on 51 single chip microcomputer (51 + OLED + hx711 + US100)
MySQL -- 16. Data structure of index
FatFs FAT32 learning notes
你和42W奖金池,就差一次“长沙银行杯”腾讯云启创新大赛!
[wechat applet] flex layout usage record
数据仓库—什么是OLAP
随机推荐
MySQL —— 16、索引的数据结构
Mui + hbuilder + h5api simulate pop-up payment style
7_ The cell type scores obtained by addmodule and gene addition method are compared in space
Conflict between Mui picker and drop-down refresh
The first lesson is canvas, showing a small case
100 GIS practical application cases (34) - splicing 2020globeland30
Request和Response及其ServletContext总结
STM32 tracking based on open MV
这几种 VSCode 扩展是我最喜欢的
2020年最新字节跳动Android开发者常见面试题及详细解析
SSM整合之pom.xml
AUTOSAR from introduction to mastery lecture 100 (84) - Summary of UDS time parameters
Translation of multi modal visual tracking: review and empirical comparison
叮~ 你的奖学金已到账!C认证企业奖学金名单出炉
【动态规划】221. 最大正方形
解决虚拟机中Oracle每次要设置ip的问题
Hanlp word splitter (via spark)
4.22学习记录(你一天只做了水题是吗)
Async void provoque l'écrasement du programme
7_Addmodule和基因加和法add 得到的细胞类型打分在空间上空转对比