SM3密码杂凑算法C语言实现

SM3密码杂凑算法C语言实现

信息安全综合实验的一个作业,要求使用miracl库。但实际上,sm3的绝大部分操作都是在32位的字上的,没有任何必要使用这个库,并且由于它对很多操作都不支持,实际上是加大了編程的难度。就当是练手了- -

#include<stdio.h>
#include"miracl.h"
#include<string.h>
#define AND 0
#define OR 3
#define XOR 2
#define PLUS 1
#define MAXN 100

int fill(big m, int l)
//消息填充
{
	//填充1到末尾
	sftbit(m, 1, m);
        add(m, mirvar(1), m);
	//填充k个0
	int k = ((447-l)%512+512)%512;
	sftbit(m, k, m);
	//填充64位比特串
	sftbit(m, 64 ,m);
	add(m, mirvar(l), m);
	return (l+k+65)/512;
}

void leftshift(big a, int len, big ans)
//32位的a 循环左移len位
{
	len %= 32;
	big x = mirvar(0);
	big b = mirvar(0);
	expb2(32-len, x);
	copy(a, ans);
	divide(ans, x, b);
	sftbit(ans, len, ans);
	add(ans, b, ans);
}

void inverse(big x, big ans)
//对32位的x进行取反位操作
{
	char xb[4];
	big_to_bytes(4, x, xb, TRUE);
	for (int i=0;i<4;i++)
		xb[i] = ~xb[i];
	bytes_to_big(4, xb, ans);
}

void operation(big a, big b, int op, big ans)
//对32位的a和b进行操作
{
	if (op == PLUS)
	{
		big x = mirvar(0);expb2(32, x);
		add(a, b, ans);
		divide(ans, x, x);
		return;
	}
	char ab[4], bb[4];
        big_to_bytes(4, a, ab, TRUE);
        big_to_bytes(4, b, bb, TRUE);
	switch(op){
		case XOR:for (int i=0;i<4;i++) ab[i] = ab[i] ^ bb[i];break;
		case AND:for (int i=0;i<4;i++) ab[i] = ab[i] & bb[i];break;
		case OR:for (int i=0;i<4;i++) ab[i] = ab[i] | bb[i];break;
	}
        bytes_to_big(4, ab, ans);
}

void P(int k, big x, big ans)
/*置换函数
P0(X) = X xor (X <<< 9) xor (X<<<17)
P1(X) = X xor (X <<< 15) xor (X<<<23)*/
{
	big a = mirvar(0);
	big b = mirvar(0);
	copy(x, a);
	copy(x, b);
	if (k == 1)
	{
		leftshift(a, 15, a);
		leftshift(b, 23, b);
	}
	else{
		leftshift(a, 9, a);
		leftshift(b, 17, b);
	}
	operation(x, a, XOR, ans);
	operation(ans, b, XOR, ans);
}

void T(int j, big x)
{
	if (0<=j && j<=15)
		cinstr(x, "79cc4519");
	else if (16<=j && j<=63)
		cinstr(x, "7a879d8a");
}

void expand(big B, big W[], big Wap[])
//填充
{
	big t[2];
	t[0] = mirvar(0);copy(B, t[0]);
	t[1] = mirvar(0);
	big x = mirvar(0);expb2(32, x);
	int l = 0;

	for (int i=15;i>=0;i--)
	{
		divide(t[l], x, t[1-l]);
		W[i] = mirvar(0);
		copy(t[l],W[i]);
		l=1-l;
	}
	//Wj = P1(W[j−16] xor W[j−9] xor (W[j−3]<<<15)) xor (W[j−13]<<<7) xor W[j−6]
	for (int i=16;i<=67;i++)
	{
		W[i] = mirvar(0);
		operation(W[i-16],W[i-9], XOR, W[i]);
		big t = mirvar(0);
		leftshift(W[i-3], 15, t);
		operation(W[i], t, XOR, W[i]);
		P(1, W[i], W[i]);
		leftshift(W[i-13], 7, t);
		operation(W[i], t, XOR, W[i]);
		operation(W[i], W[i-6], XOR, W[i]);
	}
	for (int i=0;i<=63;i++)
	{
		Wap[i] = mirvar(0);
		operation(W[i], W[i+4], XOR, Wap[i]);
	}
}

void FF(int j, big X, big Y, big Z, big ans)
{
	if (0<=j && j<=15)
	{
		operation(X, Y, XOR, ans);
		operation(ans, Z, XOR, ans);
	}
	else if (16<=j && j<=63)
	{
		//(X and Y ) or (X and Z) or (Y and Z )
		big t = mirvar(0);
		operation(X, Y, AND, ans);
		operation(X, Z, AND, t);
		operation(ans, t, OR, ans);
		operation(Y, Z, AND, t);
		operation(ans, t, OR, ans);
	}
}

void GG(int j, big X, big Y, big Z, big ans)
{
	if (0<=j && j<=15)
        {
                operation(X, Y, XOR, ans);
                operation(ans, Z, XOR, ans);
        }
        else if (16<=j && j<=63)
        {
		//(X and Y) or (not X and Z)
                big t = mirvar(0);
                operation(X, Y, AND, ans);
		inverse(X, t);
		operation(t, Z, AND, t);
		operation(ans, t, OR, ans);
        }
}

void print(big V[])
{
	char s[10];
	for (int i=0;i<8;i++)
	{
		cotstr(V[i], s);
		for(int j=0;j<8-strlen(s);j++) 
			putchar('0');
		printf("%s", s);
		if (i==7) putchar('\n');
		else putchar(' ');
	}
}

void compress(big W[], big Wap[], big V[])
//压缩
{
	big SS1,SS2,TT1,TT2,t;
	SS1 = mirvar(0);SS2 = mirvar(0);
	TT1 = mirvar(0);TT2 = mirvar(0);
	t = mirvar(0);
	big A,B,C,D,E,F,G,H;
	A = mirvar(0);copy(V[0], A);B = mirvar(0);copy(V[1], B);
	C = mirvar(0);copy(V[2], C);D = mirvar(0);copy(V[3], D);
	E = mirvar(0);copy(V[4], E);F = mirvar(0);copy(V[5], F);
        G = mirvar(0);copy(V[6], G);H = mirvar(0);copy(V[7], H);

	for (int i=0;i<=63;i++)
	{
		//SS1 = ((A<<<12) + E + (Tj<<<j))<<<7
		leftshift(A, 12, SS1);
		operation(SS1, E, PLUS, SS1);
		T(i, t);
		leftshift(t, i, t);
		operation(SS1, t, PLUS, SS1);
		leftshift(SS1, 7, SS1);	
		//SS2 = SS1 xor (A<<<12)
		leftshift(A, 12, SS2);
		operation(SS1, SS2, XOR, SS2);
		//TT1 = FFj(A,B,C) + D + SS2 +Wj′
		FF(i, A, B, C, TT1);
		operation(TT1, D, PLUS, TT1);
		operation(TT1, SS2, PLUS, TT1);
		operation(TT1, Wap[i], PLUS, TT1);
		//TT2 = GGj(E, F, G) + H + SS1 +Wj
		GG(i, E, F, G, TT2);
		operation(TT2, H, PLUS, TT2);
		operation(TT2, SS1, PLUS, TT2);
		operation(TT2, W[i], PLUS, TT2);
		//D=C; C=B<<<9; B=A; A=TT1; H=G; G=F<<<19; F=E; E=P0(TT2)
		copy(C,D);
		leftshift(B, 9, C);
		copy(A, B);
		copy(TT1, A);
		copy(G, H);
		leftshift(F, 19, G);
		copy(E, F);
		P(0, TT2, E);
		//printf("%2d: ", i);
		//print(A,B,C,D,E,F,G,H);
	}
	//V[i+1] = ABCDEFGH xor V[i]
	operation(A, V[0], XOR, V[0]);operation(B, V[1], XOR, V[1]);
	operation(C, V[2], XOR, V[2]);operation(D, V[3], XOR, V[3]);
	operation(E, V[4], XOR, V[4]);operation(F, V[5], XOR, V[5]);
        operation(G, V[6], XOR, V[6]);operation(H, V[7], XOR, V[7]);
}

void iteration(big m, int n, big V[])
//迭代
{
	big Bi[10], t[2], W[68], Wap[64];
        t[0] = mirvar(0);copy(m, t[0]);
	t[1] = mirvar(0);
        int l = 0;
	big x = mirvar(0);expb2(512, x);

        for (int i=n-1;i>=0;i--)
        {
                divide(t[l], x, t[1-l]);
                Bi[i] = mirvar(0);
                copy(t[l],Bi[i]);
                l=1-l;
        }
	
	for (int i=0;i<n;i++)
	{
		expand(Bi[i], W, Wap);
		compress(W, Wap, V);	
	}
}

int main()
{
	//读入
	miracl *mip = mirsys(512*MAXN, 10);
      	mip->IOBASE = 16;	
	char s[64*MAXN];
	scanf("%s", s);
	int l = strlen(s);
	big m = mirvar(0);
	for (int i=0;i<l;i++)
	{
		sftbit(m, 8, m);
		add(m, mirvar(s[i]), m);
	}
	//填充
	l *= 8;
	int n = fill(m,l);
	//迭代压缩
	big V[8];
	for (int i=0;i<8;i++)
		V[i] = mirvar(0);
	cinstr(V[0], "7380166f"); cinstr(V[1], "4914b2b9"); cinstr(V[2], "172442d7");
	cinstr(V[3], "da8a0600"); cinstr(V[4], "a96f30bc"); cinstr(V[5], "163138aa");
	cinstr(V[6], "e38dee4d"); cinstr(V[7], "b0fb0e4e");
	iteration(m, n, V);
	
	print(V);
	return 0;
}


程序运行结果
结果与sm3文档给出的一致。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
由于SM3算法实现过程比较复杂,需要考虑到位运算、字节序转换等问题,因此在这里只能提供一份伪代码作为参考: ``` // 定义一些常量 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17)) #define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23)) #define FF(x, y, z, j) ((j < 16) ? ((x) ^ (y) ^ (z)) : (((x) & (y)) | ((x) & (z)) | ((y) & (z)))) #define GG(x, y, z, j) ((j < 16) ? ((x) ^ (y) ^ (z)) : (((x) & (y)) | ((~x) & (z)))) // 定义一些辅助函数 void T(int i, uint32_t *T) { *T = (i < 16) ? 0x79cc4519 : 0x7a879d8a; } void CF(uint32_t *V, uint32_t *W, uint32_t *X, uint32_t *Y, uint32_t *Z, int i, uint32_t *SS1, uint32_t *SS2) { *SS1 = ROTL((ROTL((*V), 12) + (*Z) + ROTL((T(i)), i)), 7); *SS2 = *SS1 ^ ROTL((*V), 12); *W = P0((*W) ^ GG((*X), (*Y), (*Z), i)); *V = *Z; *Z = P1((*Y)); *Y = *X; *X = *W; } // 定义SM3算法函数 void SM3(uint8_t *message, uint32_t message_len, uint8_t *hash) { // 初始化 uint32_t V[8] = {0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e}; uint32_t W[68], W1[64]; uint32_t SS1, SS2, TT1, TT2; uint32_t A, B, C, D, E, F, G, H; uint32_t *p; int i, j; int n = (message_len + 8) / 64 + 1; uint8_t *msg = (uint8_t *)malloc(n * 64); memcpy(msg, message, message_len); msg[message_len] = 0x80; for (i = message_len + 1; i < n * 64; i++) { msg[i] = 0x00; } *(uint64_t *)(msg + n * 64 - 8) = message_len * 8; // 处理消息分组 for (i = 0; i < n; i++) { p = (uint32_t *)(msg + i * 64); for (j = 0; j < 16; j++) { W[j] = p[j]; } for (j = 16; j < 68; j++) { W[j] = P1(W[j - 16] ^ W[j - 9] ^ ROTL(W[j - 3], 15)) ^ ROTL(W[j - 13], 7) ^ W[j - 6]; } for (j = 0; j < 64; j++) { CF(&V[0], &V[1], &V[2], &V[3], &V[4], j, &SS1, &SS2); TT1 = FF(V[0], V[1], V[2], j) + V[3] + SS2 + W[j]; TT2 = GG(V[4], V[5], V[6], j) + V[7] + SS1 + W1[j]; V[3] = V[2]; V[2] = ROTL(V[1], 9); V[1] = V[0]; V[0] = TT1; V[7] = V[6]; V[6] = ROTL(V[5], 19); V[5] = V[4]; V[4] = P0(TT2); } } // 输出哈希值 A = V[0]; B = V[1]; C = V[2]; D = V[3]; E = V[4]; F = V[5]; G = V[6]; H = V[7]; *(uint32_t *)(hash + 0) = A; *(uint32_t *)(hash + 4) = B; *(uint32_t *)(hash + 8) = C; *(uint32_t *)(hash + 12) = D; *(uint32_t *)(hash + 16) = E; *(uint32_t *)(hash + 20) = F; *(uint32_t *)(hash + 24) = G; *(uint32_t *)(hash + 28) = H; } ``` 需要注意的是,这份伪代码中只提供了SM3算法的核心部分,实际应用中还需要对输入数据进行填充、字节序转换等处理。此外,SM3算法实现涉及到一些位运算及字节序转换,需要在实际编写过程中进行细心调试。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值