狂自私

导航

一段式SM3算法的实现

C语言

#pragma once
//C语言实现的一段式SM3算法
#include <stdio.h>
#include <memory>
//定义初始值IV,初始值IV是一个常数
unsigned char IV[256 / 8]{ 
    0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00,
    0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e };
//循环左移
unsigned long SL(unsigned long X, int n) {
    /*
    * long:32位
    * __int64:64位
    */
    unsigned __int64 x = X;
    x = x << (n % 32);    //把要移动的位数的值移动到左32位中去
    unsigned long l{ (unsigned long)(x >> 32) };    //把移动的位数的值移动最右边
    return x | l;    //右边32位组合后,截断前32位。
}
//常量判断
unsigned long Tj(int j) {
    return j <= 15 ? 0x79cc4519 : 0x7a879d8a;
}
//布尔函数
unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z) {
    if (j <= 15) {
        unsigned long ret = X ^ Y ^ Z;
        return ret;
    }
    else {
        unsigned long ret = (X & Y) | (X & Z) | (Y & Z);
        return ret;
    }
}

//置换函数
unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z) {
    if (j <= 15) {
        unsigned long ret = X ^ Y ^ Z;
        return ret;
    }
    else {
        unsigned long ret = (X & Y) | (~X & Z);
        return ret;
    }
}
unsigned long P0(unsigned long X) {
    unsigned long  ret = X ^ SL(X, 9) ^ SL(X, 17);
    return ret;
}
unsigned long P1(unsigned long X) {
    unsigned long  ret = X ^ SL(X, 15) ^ SL(X, 23);
    return ret;
}

//拓展
void EB(unsigned char Bi[512 / 8], unsigned long W[68], unsigned long W1[64]) {
    //Bi分为W0~W15
    for (int i{}; i < 16; ++i) {
        W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3];
    }
    for (int i = 16; i <= 67; ++i) {
        W[i] = P1(W[i - 16] ^ W[i - 9] ^ SL(W[i - 3], 15)) ^ SL(W[i - 13], 7) ^ W[i - 6];
    }
    for (int i{}; i <= 63; ++i) {
        W1[i] = W[i] ^ W[i + 4];
    }
}
//压缩函数
void CF(unsigned char Vi[256 / 8], unsigned char Bi[512 / 8], unsigned char Vi1[256 / 8]) {
    //Bi拓展为132个字
    unsigned long W[68]{};
    unsigned long W1[68]{};

    EB(Bi, W, W1);

    //串联 ABCDEFG=Vi
    unsigned long R[8]{};
    for (int i{}; i < 8; ++i) {
        R[i] = ((unsigned long)Vi[i * 4] << 24) | ((unsigned long)Vi[i * 4 + 1] << 16) | ((unsigned long)Vi[i * 4 + 2] << 8) | ((unsigned long)Vi[i * 4 + 3]);
    }
    unsigned long A = R[0];
    unsigned long B = R[1];
    unsigned long C = R[2];
    unsigned long D = R[3];
    unsigned long E = R[4];
    unsigned long F = R[5];
    unsigned long G = R[6];
    unsigned long H = R[7];

    unsigned long SS1{}; 
    unsigned long SS2{}; 
    unsigned long TT1{};
    unsigned long TT2{};
    for (int i{}; i <= 63; ++i) {
        SS1 = SL((SL(A, 12) + E + SL(Tj(i), i)), 7);
        SS2 = SS1 ^ SL(A, 12);
        TT1 = FFj(i, A, B, C) + D + SS2 + W1[i];
        TT2 = GGj(i, E, F, G) + H + SS1 + W[i];
        D = C;
        C = SL(B, 9);
        B = A;
        A = TT1;
        H = G;
        G = SL(F, 19);
        F = E;
        E = P0(TT2);
    }
    //Vi1=ABCDEFGH 串联
    R[0] = A;
    R[1] = B;
    R[2] = C;
    R[3] = D;
    R[4] = E;
    R[5] = F;
    R[6] = G;
    R[7] = H;
    for (int i{}; i < 8; ++i) {
        Vi1[i * 4] = (R[i] >> 24) & 0xff;
        Vi1[i * 4 + 1] = (R[i] >> 16) & 0xff;
        Vi1[i * 4 + 2] = (R[i] >> 8) & 0xff;
        Vi1[i * 4 + 3] = R[i] & 0xff;
    }
    //Vi1=ABCDEFGH^Vi
    for (int i{}; i < 256 / 8; ++i) {
        Vi1[i] ^= Vi[i];
    }
}
//参数 sourceData 是原始数据,sourceData_len 是数据长度,out 是输出参数,存放hash结果
void SM3Hash(unsigned char* sourceData, int sourceData_len, unsigned char out[32])
{
    int sourceLen = sourceData_len * 8;
    int zero_amount = 448 - 1 - sourceLen % 512;// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数
    if (zero_amount <= 0)
    {
        zero_amount += 512;
    }
    //固定公式
    int n = (sourceLen + zero_amount + 65) / 512;

    int PopulatingSourceData_len = n * 512 / 8; // 填充后的长度,512位的倍数
    unsigned char* tempData = new unsigned char[PopulatingSourceData_len] {};
    memset(tempData, 0, PopulatingSourceData_len);
    memcpy(tempData, sourceData, sourceLen / 8);

    tempData[sourceLen / 8] = 0x80; // 消息后补1

    // 再添加一个64位比特串,该比特串是长度l的二进制表示
    unsigned long tempLen = sourceLen;
    for (int i = 0; i < 64 / 8 && tempLen > 0; ++i)
    {
        tempData[PopulatingSourceData_len - 1 - i] = tempLen & 0xFF;
        tempLen = tempLen >> 8;
    }

    //将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(sourceLen + zero_amount+65)/512。
    unsigned char** B = new unsigned char* [n] {};
    for (int i = 0; i < n; ++i)
    {
        B[i] = new unsigned char[512 / 8] {};
        memcpy(B[i], tempData + (512 / 8) * i, 512 / 8);
    }

    delete[] tempData;

    unsigned char** V = new unsigned char* [n + 1] {};
    for (int i = 0; i <= n; ++i)
    {
        V[i] = new unsigned char[256 / 8] {};
        memset(V[i], 0, 256 / 8);
    }

    // 初始化 V0 = VI
    memcpy(V[0], IV, 256 / 8);

    // 压缩函数,V 与扩展的B
    for (int i = 0; i < n; ++i)
    {
        CF(V[i], B[i], V[i + 1]);
    }

    for (int i = 0; i < n; ++i)
    {
        delete[] B[i];
    }
    delete[] B;

    // V[n]是结果
    memcpy(out, V[n], 32);

    for (int i = 0; i < n + 1; ++i)
    {
        delete[] V[i];
    }
    delete[] V;
}

void dumpbuf(unsigned char* buf, int len) {
    int line{ 32 };
    printf("len=%d\n", len);
    for (int i{}; i < len; i++) {
        printf("%02x ", buf[i]);
        if (i > 0 && (i + 1) % 16 == 0) {
            putchar('\n');
        }
    }
}
View Code

C++

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include ".vs\..\..\my_func\my_function.h"
//定义初始值IV,初始值IV是一个常数
std::vector<unsigned char> IV{ 
    0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00,
    0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e };
//常量判断
unsigned long Tj(int j) {
    return j <= 15 ? 0x79cc4519 : 0x7a879d8a;
}
//布尔函数
unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z) {
    if (j <= 15) {
        unsigned long ret = X ^ Y ^ Z;
        return ret;
    }
    else {
        unsigned long ret = (X & Y) | (X & Z) | (Y & Z);
        return ret;
    }
}
//置换函数
unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z) {
    if (j <= 15) {
        unsigned long ret = X ^ Y ^ Z;
        return ret;
    }
    else {
        unsigned long ret = (X & Y) | (~X & Z);
        return ret;
    }
}
unsigned long P0(unsigned long X) {
    unsigned long  ret = X ^ MY_TOOLS::ring_shift_left(X, 9) ^ MY_TOOLS::ring_shift_left(X, 17);
    return ret;
}
unsigned long P1(unsigned long X) {
    unsigned long  ret = X ^ MY_TOOLS::ring_shift_left(X, 15) ^ MY_TOOLS::ring_shift_left(X, 23);
    return ret;
}
/*
拓展
Bi:长度为64
W:长度为68
W1:长度为64
*/
void EB(std::vector<unsigned char> &Bi, std::vector<unsigned long> &W, std::vector<unsigned long> &W1) {
    //Bi分为W0~W15
    for (int i{}; i < 16; ++i) {
        W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3];
    }
    for (int i = 16; i <= 67; ++i) {
        W[i] = P1(W[i - 16] ^ W[i - 9] ^ MY_TOOLS::ring_shift_left(W[i - 3], 15)) ^ MY_TOOLS::ring_shift_left(W[i - 13], 7) ^ W[i - 6];
    }
    for (int i{}; i <= 63; ++i) {
        W1[i] = W[i] ^ W[i + 4];
    }
}
/*
* 压缩函数
* Vi:长度32
* Bi:长度64
* Vi_1:长度32
*/
void CF(std::vector<unsigned char>& Vi, std::vector<unsigned char>& Bi, std::vector<unsigned char>& Vi_1) {
    //Bi拓展为132个字
    std::vector<unsigned long> W(68, 0);
    std::vector<unsigned long> W1(68, 0);

    EB(Bi, W, W1);

    //串联 ABCDEFG=Vi
    std::vector<unsigned long> R(8, 0);
    for (int i{}; i < 8; ++i) {
        R[i] = (static_cast<unsigned long>(Vi[i * 4]) << 24) | (static_cast<unsigned long>(Vi[i * 4 + 1]) << 16) | (static_cast<unsigned long>(Vi[i * 4 + 2]) << 8) | (static_cast<unsigned long>(Vi[i * 4 + 3]));
    }
    unsigned long A = R[0];
    unsigned long B = R[1];
    unsigned long C = R[2];
    unsigned long D = R[3];
    unsigned long E = R[4];
    unsigned long F = R[5];
    unsigned long G = R[6];
    unsigned long H = R[7];

    unsigned long SS1{};
    unsigned long SS2{};
    unsigned long TT1{};
    unsigned long TT2{};
    for (int i{}; i <= 63; ++i) {
        SS1 = MY_TOOLS::ring_shift_left((MY_TOOLS::ring_shift_left(A, 12) + E + MY_TOOLS::ring_shift_left(Tj(i), i)), 7);
        SS2 = SS1 ^ MY_TOOLS::ring_shift_left(A, 12);
        TT1 = FFj(i, A, B, C) + D + SS2 + W1[i];
        TT2 = GGj(i, E, F, G) + H + SS1 + W[i];
        D = C;
        C = MY_TOOLS::ring_shift_left(B, 9);
        B = A;
        A = TT1;
        H = G;
        G = MY_TOOLS::ring_shift_left(F, 19);
        F = E;
        E = P0(TT2);
    }
    //Vi1=ABCDEFGH 串联
    R[0] = A;
    R[1] = B;
    R[2] = C;
    R[3] = D;
    R[4] = E;
    R[5] = F;
    R[6] = G;
    R[7] = H;
    for (int i{}; i < 8; ++i) {
        Vi_1[i * 4] = (R[i] >> 24) & 0xff;
        Vi_1[i * 4 + 1] = (R[i] >> 16) & 0xff;
        Vi_1[i * 4 + 2] = (R[i] >> 8) & 0xff;
        Vi_1[i * 4 + 3] = R[i] & 0xff;
    }
    //Vi1=ABCDEFGH^Vi
    for (int i{}; i < 256 / 8; ++i) {
        Vi_1[i] ^= Vi[i];
    }
}
/*
* hash函数
* 参数 sourceData 是原始数据,sourceData_len 是数据长度,out 是输出参数, 存放hash结果,长度为32
*/
void SM3Hash(std::vector<unsigned char>& sourceData, int sourceData_len, std::vector<unsigned char>& out)
{
    int sourceLen = sourceData_len * 8;
    int zero_amount = 448 - 1 - sourceLen % 512;// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数
    if (zero_amount <= 0)
    {
        zero_amount += 512;
    }
    //固定公式
    int n = (sourceLen + zero_amount + 65) / 512;

    int PopulatingSourceData_len = n * 512 / 8; // 填充后的长度,512位的倍数
    /*unsigned char* tempData = new unsigned char[PopulatingSourceData_len] {};
    memset(tempData, 0, PopulatingSourceData_len);
    memcpy(tempData, sourceData, sourceLen / 8);*/

    std::vector<unsigned char>tempData{ sourceData };
    tempData.resize(PopulatingSourceData_len, 0);

    tempData[sourceLen / 8] = 0x80; // 消息后补1

    // 再添加一个64位比特串,该比特串是长度l的二进制表示
    unsigned long tempLen = sourceLen;
    for (int i = 0; i < 64 / 8 && tempLen > 0; ++i)
    {
        tempData[PopulatingSourceData_len - 1 - i] = tempLen & 0xFF;
        tempLen = tempLen >> 8;
    }

    //将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(sourceLen + zero_amount+65)/512。
    std::vector<std::vector<unsigned char>>B(n);
    for (int i = 0; i < n; ++i)
    {
        B[i].reserve(64);        //提前分配存储空间,不过其实差不多的感觉
        //tempData是512的倍数,所以也是64的倍数
        B[i].insert(B[i].begin(), tempData.begin() + (64 * i), tempData.begin() + (64 * (i + 1)));
    }

    //unsigned char** V = new unsigned char* [n + 1] {};
    std::vector<std::vector<unsigned char>>V(n + 1);
    for (int i = 0; i <= n; ++i)
    {
        V[i].reserve(32);    //分配空间
    }

    // 初始化 V0 = VI
    V[0].insert(V[0].begin(), IV.begin(), IV.end());

    // 压缩函数,V 与扩展的B
    for (int i = 0; i < n; ++i)
    {
        V[i + 1].resize(32, 0);
        CF(V[i], B[i], V[i + 1]);
    }

    // V[n]是结果
    //memcpy(out, V[n], 32);
    out.insert(out.begin(), V[n].begin(), V[n].end());
}
/*
* 以2位的16进制数输出hash值
*/
void dumpbuf(std::vector<unsigned char>& buf, int len) {
    int line{ 32 };
    std::cout << "len = " << len << '\n';
    for (int i{}; i < len; i++) {
        std::cout << std::hex << static_cast<unsigned>(buf[i]) << ' ';
        if (i > 0 && (i + 1) % 16 == 0) {
            std::cout << '\n';
        }
    }
}
View Code

调用

C版:

void main()
{
    unsigned char   data[] = "abc", r[32];
    printf("消息:%s\nHash结果:\n", data);
    SM3Hash(data, 3, r);

    dumpbuf(r, 32);

}

C++版

int main() {
    std::vector<unsigned char> data;
    std::vector<unsigned char> result;

    data.push_back('a');
    data.push_back('b');
    data.push_back('c');

    result.reserve(32);

    std::cout << "消息:" << MY_TOOLS::vecUChar_to_string(data) << "\nHash结果:\n";
    SM3Hash(data, data.size(), result);
    dumpbuf(result, result.size());
}

输出:

消息:abc
Hash结果:
len = 32
66 c7 f0 f4 62 ee ed d9 d1 f2 d4 6b dc 10 e4 e2
41 67 c4 87 5c f2 f7 a2 29 7d a0 2b 8f 4b a8 e0

posted on 2022-09-22 17:44  狂自私  阅读(136)  评论(0编辑  收藏  举报