SM3(下)

说明,此文章为C开发的SM3.c文件,没有使用第三方密码库,如果不足,欢迎指出

/************************************************************
版权声明:
文件名称: SM3.c
文件描述: 包括了实现SM3的相关常量、函数和其他定义
创 建 者: 程帅
创建时间:2023/7/18
修改历史:

*********************************************************************/
#include "SM3.h"

typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;

static uint32_t globalIV[8] = { 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa,
0xe38dee4d, 0xb0fb0e4e };//常量

//字结构体,包含了W和W'
struct myWord {
    uint32_t W[68];
    uint32_t W1[64];
};

/********************************************************************************
函 数 名:Conver
说    明 : 大小端转化
功能描述:对4字节的数进行大小的转化
参数:
value(in)待转化的字节
返 回 值 : 逆向大小端的四字节
********************************************************************************/
#define Conver(value) ((((value) & 0x000000FFU) << 24 | ((value) & 0x0000FF00U) << 8 |((value) &\
 0x00FF0000U) >> 8 | ((value) & 0xFF000000U) >> 24))

/********************************************************************************
函 数 名:ROTATE_LEFG
说    明 : 循环左移
功能描述:对4字节的数进行大小的转化
参数:
a(in)要循环左移的字
k(in)左移的次数
返 回 值 : 左移k次的字
********************************************************************************/
#define ROTATE_LEFG(a, k) (((a) << (k))  | ((a) >> (32 - (k))))

/*******************************************************************************
函 数 名:T
说    明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
返 回 值 : 相应的常量
*******************************************************************************/
#define T(j) (j) <= 15 ? 0x79cc4519 : 0x7a879d8a

/*******************************************************************************
函 数 名 FF
说    明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
 x(in)字X
 y(in)字Y
 z(in)字Z
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define FF( j,  x,  y,  z) ((j) <= 15 ? (x) ^ (y) ^ (z) : ((x) & (y)) | ((x) & (z)) | ((y) & (z)))

/*******************************************************************************
函 数 名 GG
说    明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
 x(in)字X
 y(in)字Y
 z(in)字Z
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define GG(j, x, y, z) ((j) <= 15 ? (x) ^ (y) ^ (z) : ((x) & (y)) | (~(x) & (z)) )

/*******************************************************************************
函 数 名:DISPLACE_0
说    明 : 置换函数0
功能描述:对字x进行固定的计算
参数:
x(in)字X
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define DISPLACE_0(X)  ((X) ^ (ROTATE_LEFG((X), 9)) ^ (ROTATE_LEFG((X), 17)))

/*******************************************************************************
函 数 名:DISPLACE_0
说    明 : 置换函数1
功能描述:对字x进行固定的计算
参数:
x(in)字X
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define DISPLACE_1(X) ((X) ^ (ROTATE_LEFG((X), 15)) ^ (ROTATE_LEFG((X), 23)))

/*******************************************************************************
函 数 名:bitStuffing
说    明 : 比特填充
功能描述:将message需要填充的部分放入stuffFinBlock中,并对stuffFinBlock进行填充
参数:
*message(in)消息
 len(in)消息长度
 *stuffFinBlock(out)填充后的消息
返 回 值 :
*******************************************************************************/
void bitStuffing(uint8_t* message, uint64_t len, uint8_t* stuffFinBlock)
{
    uint8_t* finBlock;/*用来存储消息的末尾数据*/
    uint8_t emptyBlock[64];/*一个空块,当末尾数据为空时,使用该块*/
    uint8_t temp;/*存储大小端转化时的中间变量*/
    uint64_t bitLen = len * 8;/*存储消息长度的比特大小*/

    
    /*判断消息是否为整块512比特,即消息的末尾数据是否为空*/
    if (0 != len % 64) { 

        /*非整块则获得原有最有一块消息的数据*/
        uint64_t suffLen = (len / 64) * 64;
        finBlock = message + suffLen;
    }
    else {

        /*整块则使用一个新的空消息块*/
        finBlock = emptyBlock;
    }

    /*填充'0'和消息*/
    memset(stuffFinBlock, 0, 64);
    memcpy(stuffFinBlock, finBlock, len % 64);

    /*填充'1'*/
    *(stuffFinBlock + (len % 64)) = 0b10000000;

    /*填充'消息长度'*/
    memcpy(stuffFinBlock + 64 - 8, (uint8_t *)&bitLen, 8);

    /*小字节转大字节,大小端转化开始*/
    for (int i = 1; i <= 4; i++) {
        temp = stuffFinBlock[64 - i];
        stuffFinBlock[64 - i] = stuffFinBlock[64 - 9 + i];
        stuffFinBlock[64 - 9 + i] = temp;
    }/*大小端转化结束*/
}

/*******************************************************************************
函 数 名: MessExtension
说    明 : 消息扩展
功能描述:对消息message进行字扩展,扩展后的字将放入myW中
参数:
*message(in)消息
 *W(in)扩展字W
 *W1(in)扩展字W'
返 回 值 : 0成功,-1失败
*******************************************************************************/
int MessExtension(uint8_t* message, uint32_t* W, uint32_t* W1)
{
    uint8_t temp;/*存储大小端转化时的中间变量*/
    uint8_t mess_copy[64];/*存储消息副本*/

    /*消息拷贝*/
    memcpy(mess_copy, message, 64);

    /*扩展字W填充结束*/
    /*1.大小端转化和拷贝字开始*/
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 2; j++) {
            temp = mess_copy[i * 4 + j];
            mess_copy[i * 4 + j] = mess_copy[i * 4 + 4 - 1 - j];
            mess_copy[i * 4 + 4 - 1 - j] = temp;
        }

        memcpy(W + i, mess_copy + i * 4, 4);/*4个一字节拷入1个四字节*/
    }/*1.大小端转化和拷贝字结束*/

    /*2.扩展字W计算结束*/
    for (int j = 16; j <= 67; j++) {
        W[j] = DISPLACE_1(W[j - 16] ^ W[j - 9] ^ (ROTATE_LEFG(W[j - 3], 15))) ^ (ROTATE_LEFG(W[j - 13], 7)) ^ W[j - 6];
    }/*2.扩展字W计算结束*/

    /*扩展字W填充结束*/

    /*扩展字W'填充开始*/
    for (int j = 0; j <= 63; j++) {
        W1[j] = W[j] ^ W[j + 4];
    }/*扩展字W'填充结束*/

    return 0;
}

/*******************************************************************************
函 数 名: CF
说    明 : 压缩函数
功能描述:利用扩展字myW对向量IV进行压缩,结构输出到IV中,参数(输入向量,扩展字)
参数:
*IV(in)输入向量
 *W(in)扩展字W
 *W1(in)扩展字W'
返 回 值 :
*******************************************************************************/
void CF(uint32_t* V, uint32_t* W, uint32_t* W1)
{
    /*初始化初始向量*/
    uint32_t A = V[0];
    uint32_t B = V[1];
    uint32_t C = V[2];
    uint32_t D = V[3];
    uint32_t E = V[4];
    uint32_t F = V[5];
    uint32_t G = V[6];
    uint32_t H = V[7];

    /*初始化中间值*/
    uint32_t SS1, SS2, TT1, TT2;

    /*中间值计算开始*/
    for (int j = 0; j <= 63; j++) {
        SS1 = ROTATE_LEFG(ROTATE_LEFG(A, 12) + E + ROTATE_LEFG(T(j), j), 7);
        SS2 = SS1 ^ ROTATE_LEFG(A, 12);
        TT1 = FF(j, A, B, C) + D + SS2 + W1[j];
        TT2 = GG(j, E, F, G) + H + SS1 + W[j];
        D = C;
        C = ROTATE_LEFG(B, 9);
        B = A;
        A = TT1;
        H = G;
        G = ROTATE_LEFG(F, 19);
        F = E;
        E = DISPLACE_0(TT2);
    }/*中间值计算结束*/

    /*结果运算*/
    V[0] = A ^ V[0];
    V[1] = B ^ V[1];
    V[2] = C ^ V[2];
    V[3] = D ^ V[3];
    V[4] = E ^ V[4];
    V[5] = F ^ V[5];
    V[6] = G ^ V[6];
    V[7] = H ^ V[7];
}

/*******************************************************************************
函 数 名:iteration
说    明 : 迭代过程
功能描述:对message进行迭代处理,其中包括对message经行扩展和压缩
参数:
*message(in)消息
 n(in)消息块数
 *hash(out)杂凑值
返 回 值 : 0成功,-1失败
*******************************************************************************/
int iteration(uint8_t* message, int n, uint32_t* hash)
{

    uint32_t V[8];/*存储每一组计算完的向量值*/
    uint8_t messageBlk[64];/*存储消息快*/
    struct myWord myW;

    /*初始化向量*/
    memcpy(V, globalIV, 32);

    /*迭代运算开始*/
    for (int i = 0; i <= n; i++) {

        /*拷贝消息*/
        memcpy(messageBlk, message + i * 64, 64);

        /*扩展*/
        MessExtension(messageBlk, myW.W, myW.W1);

        /*压缩*/
        CF(V, myW.W, myW.W1);

    }/*迭代运算结束*/

    /*将结果拷贝给hash作为输出*/
    memcpy(hash, V, 32);
    return 0;
}

/*******************************************************************************
函 数 名:SM3Hash
说    明 : SM3接口函数
功能描述:对输入的数据mess进行SM3杂凑值提取
参数:
mess(in)待处理的消息
len(in)    消息长度(字节)
hash(out)杂凑值
返 回 值 : -1失败 0成功
*******************************************************************************/
int SM3Hash(uint8_t* mess, uint64_t len, uint8_t* hash) 
{

    uint8_t* mess_copy;/*消息的拷贝*/
    uint8_t stuffFinBlock[64];/*填充的块*/
    uint32_t hashValue[8];/*存储迭代的中间哈希值*/
    const int n = (int)len / 64;/*消息的分组个数*/

    /*拷贝原有的消息内容*/
    uint64_t maxLen = ((uint64_t)n + 1) * 64;/*消息填充后的最大长度*/

    mess_copy = malloc((size_t)maxLen);
    if (NULL == mess_copy) {
        return -1;
    }

    /*拷贝消息到局部副本*/
    memset(mess_copy, 0, (size_t)maxLen);
    memcpy(mess_copy, mess, (size_t)len);


    /*消息填充*/
    bitStuffing(mess_copy, len, stuffFinBlock);
    memcpy(mess_copy + n * 64, (uint8_t*)stuffFinBlock, 64);

    /*开始迭代*/
    iteration(mess_copy, n, hashValue);

    /*大小端处理开始*/
    for (int i = 0; i < sizeof(hashValue) / 4; i++) {
        hashValue[i] = Conver(hashValue[i]);
    }/*大小端处理结束*/

    /*将杂凑值拷贝到输出*/
    memcpy(hash, hashValue, 32);

    /*释放内存*/
    free(mess_copy);
    mess_copy = NULL;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值