SM3

11

#ifndef __SM3_H__
#define __SM3_H__

#include <stdint.h>

#define SM3_HASH_SIZE 32 

typedef struct SM3Context
{
    uint32_t    intermediateHash[SM3_HASH_SIZE / 4];
    uint8_t     messageBlock[64];
} SM3Context;
 

uint8_t *SM3Calc(const uint8_t *message,
    uint32_t messageLen, uint8_t digest[SM3_HASH_SIZE]);
 
#endif /* __SM3_H__ */

 

#include <stdio.h>
#include <string.h>

#include "sm3.h"

/*
 * 判断运行环境是否为小端
**/
static const int endianTest = 1;
#define IsLittleEndian() (*(char *)&endianTest == 1)

/*
 * 向左循环移位
**/
#define LeftRotate(word, bits) ((word) << ((bits)%32) | (word) >> (32 - ((bits)%32)))
 
/*
 * 反转四字节整型字节序
**/
static uint32_t *ReverseWord(uint32_t *word)
{
    uint8_t *byte, temp;
 
    byte = (uint8_t *)word;
    temp = byte[0];
    byte[0] = byte[3];
    byte[3] = temp;
 
    temp = byte[1];
    byte[1] = byte[2];
    byte[2] = temp;
    return word;
}
 
static uint32_t T(int i)
{
    if (i >= 0 && i <= 15)
        return 0x79CC4519;
    else if (i >= 16 && i <= 63)
        return 0x7A879D8A;
    else
        return 0;
}

static uint32_t FF(uint32_t X, uint32_t Y, uint32_t Z, int i)
{
    if (i >= 0 && i <= 15)
        return X ^ Y ^ Z;
    else if (i >= 16 && i <= 63)
        return (X & Y) | (X & Z) | (Y & Z);
    else
        return 0;
}

static uint32_t GG(uint32_t X, uint32_t Y, uint32_t Z, int i)
{
    if (i >= 0 && i <= 15)
        return X ^ Y ^ Z;
    else if (i >= 16 && i <= 63)
        return (X & Y) | (~X & Z);
    else
        return 0;
}

static inline uint32_t P0(uint32_t X)
{
    return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17);
}

static inline uint32_t P1(uint32_t X)
{
    return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23);
}

static void SM3Init(SM3Context *context)
{
    context->intermediateHash[0] = 0x7380166F;
    context->intermediateHash[1] = 0x4914B2B9;
    context->intermediateHash[2] = 0x172442D7;
    context->intermediateHash[3] = 0xDA8A0600;
    context->intermediateHash[4] = 0xA96F30BC;
    context->intermediateHash[5] = 0x163138AA;
    context->intermediateHash[6] = 0xE38DEE4D;
    context->intermediateHash[7] = 0xB0FB0E4E;
}

static void SM3ProcessMessageBlock(SM3Context *context)
{
    int i;
    uint32_t W[68];
    uint32_t W_[64];
    uint32_t A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2;
 
    /* 消息扩展 */
    for (i = 0; i < 16; i++)
    {
        W[i] = *(uint32_t *)(context->messageBlock + i * 4);
        if (IsLittleEndian())
            ReverseWord(W + i);  
    }
    for (i = 16; i < 68; i++)
    {
        W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15))
            ^ LeftRotate(W[i - 13], 7)
            ^ W[i - 6];  
    }
    for (i = 0; i < 64; i++)
    {
        W_[i] = W[i] ^ W[i + 4]; 
    }
 
    /* 消息压缩 */
    A = context->intermediateHash[0];
    B = context->intermediateHash[1];
    C = context->intermediateHash[2];
    D = context->intermediateHash[3];
    E = context->intermediateHash[4];
    F = context->intermediateHash[5];
    G = context->intermediateHash[6];
    H = context->intermediateHash[7];
    for (i = 0; i < 64; i++)
    {
        SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7);
        SS2 = SS1 ^ LeftRotate(A, 12);
        TT1 = FF(A, B, C, i) + D + SS2 + W_[i];
        TT2 = GG(E, F, G, i) + H + SS1 + W[i];
        D = C;
        C = LeftRotate(B, 9);
        B = A;
        A = TT1;
        H = G;
        G = LeftRotate(F, 19);
        F = E;
        E = P0(TT2);
    }
    context->intermediateHash[0] ^= A;
    context->intermediateHash[1] ^= B;
    context->intermediateHash[2] ^= C;
    context->intermediateHash[3] ^= D;
    context->intermediateHash[4] ^= E;
    context->intermediateHash[5] ^= F;
    context->intermediateHash[6] ^= G;
    context->intermediateHash[7] ^= H;
}
 
/*
 * SM3计算
**/
uint8_t *SM3Calc(const uint8_t *message,
    uint32_t messageLen, uint8_t digest[SM3_HASH_SIZE])
{
    SM3Context context;
    uint32_t i, remainder, bitLen;
 
    /* 初始化上下文 */
    SM3Init(&context);
 
    /* 对前面的消息分组进行处理 */
    for (i = 0; i < messageLen / 64; i++)
    {
        memcpy(context.messageBlock, message + i * 64, 64);
        SM3ProcessMessageBlock(&context);
    }
 
    /* 填充消息分组,并处理 */
    bitLen = messageLen * 8;
    if (IsLittleEndian())
        ReverseWord(&bitLen);
    remainder = messageLen % 64;
    memcpy(context.messageBlock, message + i * 64, remainder);
    context.messageBlock[remainder] = 0x80;
    if (remainder <= 55)
    {
        /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
        * 故将高 4 个字节赋为 0 。*/
        memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4);
        memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
        SM3ProcessMessageBlock(&context);
    }
    else
    {
        memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1);
        SM3ProcessMessageBlock(&context);
        /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
        * 故将高 4 个字节赋为 0 。*/
        memset(context.messageBlock, 0, 64 - 4);
        memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
        SM3ProcessMessageBlock(&context);
    }
 
    /* 返回结果 */
    if (IsLittleEndian())
        for (i = 0; i < 8; i++)
            ReverseWord(context.intermediateHash + i);
    memcpy(digest, context.intermediateHash, SM3_HASH_SIZE);
 
    return digest;
}

#if 0
int main( void )
{
    //uint8_t input[256] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
    //int ilen = 64;
    uint8_t input[4] = "abc";
    int ilen = 3;
    uint8_t output[32];
    int i;
    
    SM3Calc(input, ilen, output);
    for (i = 0; i < 32; i++)
    {
        printf("0x%02x ", output[i]);
    }
    printf("\n");
    
}
#endif

 

上一篇:求子矩阵最大累加和


下一篇:yum安装python3.6的方法