信息安全系统设计实验二 密码算法实现 1-3学时

《密码系统设计》实验

实验项目

实验序号 实验名称 实验学时数 实验目的 实验内容 实验类型 学生学习预期成果
实验二 密码算法实现 6 掌握常见商用密码算法的原理与实现 基于国产化平台使用C语言编程实现SM2、SM3、SM4等算法; 验证性 1.基于Arm等平台和国产化操作系统使用C语言编程实现SM2、SM3、SM4算法;
2.对比分析算法实现的正确性和效率。

实验二 密码算法实现

1-3 学时实践要求(30 分)

1. 在 Ubuntu或openEuler中(推荐 openEuler)中调试运行商用密码检测中心https://www.scctc.org.cn/xzzx/sfydm/ydmxz/提供的源代码,至少运行SM2,SM3,SM4代码。使用GmSSL命令验证你代码的正确性。使用Markdown记录详细记录实践过程,每完成一项功能或者一个函数git commit 一次。(14分)

//SM2

//main.c加密解密
#include "miracl.h" 
#include "mirdef.h" 
#include "SM2_ENC.h" 
#include "kdf.h" 
#include <stdio.h> 
#include <string.h> 
 
// 主函数,调用SM2算法相关函数进行加密解密操作 
int main() 
{
    
    int result; 
    big priKey; 
    epoint *pubKey; 
    unsigned char message[128]; 
    unsigned char ciphertext[115 + 128]; 
    unsigned char decryptedMessage[128]; 
    unsigned char randK[32]; 
 
    // 初始化MIRACL系统 
    mip = mirsys(1000, 16); 
    mip->IOBASE = 16; 
    priKey = mirvar(0); 
    pubKey = epoint_init(); 
 
    // 初始化SM2相关参数 
    result = SM2_Init(); 
    if (result!= 0) 
    {
    
        printf("SM2初始化失败,错误码: %d\n", result); 
        return 1; 
    } 
 
    // 生成密钥对 
    // 这里简单生成一个随机私钥(实际应用中应使用安全的随机数生成器) 
    irand((long)time(NULL)); 
    bigrand(para_n, priKey); 
    result = SM2_KeyGeneration(priKey, pubKey); 
    if (result!= 0) 
    {
    
        printf("密钥生成失败,错误码: %d\n", result); 
        return 1; 
    } 
 
    // 准备要加密的消息 
    strcpy((char *)message, "20221417wzy"); 
    // 生成随机数randK(实际应用中应使用安全的随机数生成器) 
    for (int i = 0; i < 32; i++) 
    {
    
        randK[i] = (unsigned char)rand(); 
    } 
 
    // 加密消息 
    result = SM2_Encrypt(randK, pubKey, message, strlen((char *)message), ciphertext); 
    if (result!= 0) 
    {
    
        printf("加密失败,错误码: %d\n", result); 
        return 1; 
    } 
    printf("加密成功,密文:\n"); 
    for (int i = 0; i < sizeof(ciphertext); i++) 
    {
    
        printf("%02X", ciphertext[i]); 
    } 
    printf("\n"); 
 
    // 解密消息 
    result = SM2_Decrypt(priKey, ciphertext, sizeof(ciphertext), decryptedMessage); 
    if (result!= 0) 
    {
    
        printf("解密失败,错误码: %d\n", result); 
        return 1; 
    } 
    printf("解密成功,消息: %s\n", decryptedMessage); 
 
    // 清理MIRACL系统资源 
    mirexit(); 
    return 0; 
} 
//SM2_ENC.c
#include "miracl.h"  
#include "mirdef.h"  
#include "SM2_ENC.h" 
#include "kdf.h"

int Test_Point(epoint* point)
{
   
	big x, y, x_3, tmp;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);



	//test if y^2=x^3+ax+b
	epoint_get(point, x, y);
	power(x, 3, para_p, x_3);
	multiply(x, para_a, x);
	divide(x, para_p, tmp);
	add(x_3, x, x);
	add(x, para_b, x);
	divide(x, para_p, tmp);
	power(y, 2, para_p, y);
	if (compare(x, y) != 0)
		return ERR_NOT_VALID_POINT;
	else
		return 0;
}

int Test_PubKey(epoint* pubKey)
{
   

	big x, y, x_3, tmp;
	epoint* nP;
	x = mirvar(0);
	y = mirvar(0);
	x_3 = mirvar(0);
	tmp = mirvar(0);

	nP = epoint_init();

	//test if the pubKey is the point at infinity
	if (point_at_infinity(pubKey))// if pubKey is point at infinity, return error; 
		return ERR_INFINITY_POINT;
	//test if x<p   and  y<p  both hold
	epoint_get(pubKey, x, y);
	if ((compare(x, para_p) != -1) || (compare(y, para_p) != -1))
		return ERR_NOT_VALID_ELEMENT;

	if (Test_Point(pubKey) != 0)
		return ERR_NOT_VALID_POINT;

	//test if the order of pubKey is equal to n
	ecurve_mult(para_n, pubKey, nP);        // nP=[n]P
	if (!point_at_infinity(nP))           // if np is point NOT at infinity, return error;
		return ERR_ORDER;
	return 0;
}

int Test_Null(unsigned char array[], int len)
{
   
	int i = 0;
	for (i = 0; i < len; i++) {
   
		if (array[i] != 0x00)
			return 0;
	}
	return 1;
}

int SM2_Init()
{
   
	epoint* nG;
	para_p = mirvar(0);
	para_a = mirvar(0);
	para_b = mirvar(0);
	para_n = mirvar(0);
	para_Gx = mirvar(0);
	para_Gy = mirvar(0);
	para_h = mirvar(0);
	G = epoint_init();
	nG = epoint_init();
	bytes_to_big(SM2_NUMWORD, SM2_p, para_p);
	bytes_to_big(SM2_NUMWORD, SM2_a, para_a);
	bytes_to_big(SM2_NUMWORD, SM2_b, para_b);
	bytes_to_big(SM2_NUMWORD, SM2_n, para_n);
	bytes_to_big(SM2_NUMWORD, SM2_Gx, para_Gx);
	bytes_to_big(SM2_NUMWORD, SM2_Gy, para_Gy);
	bytes_to_big(SM2_NUMWORD, SM2_h, para_h);

	ecurve_init(para_a, para_b, para_p, MR_PROJECTIVE);//Initialises GF(p) elliptic curve.
	//MR_PROJECTIVE specifying  projective coordinates

	if (!epoint_set(para_Gx, para_Gy, 0, G))//initialise point G 
	{
   
		return ERR_ECURVE_INIT;
	}

	ecurve_mult(para_n, G, nG);

	if (!point_at_infinity(nG))    //test if the order of the point is n
	{
   
		return ERR_ORDER;
	}
	return 0;
}


int SM2_KeyGeneration(big priKey, epoint* pubKey)
{
   
	int i = 0;
	big x, y;
	x = mirvar(0);
	y = mirvar(0);

	ecurve_mult(priKey, G, pubKey);//通过大数和基点产生公钥 
	epoint_get(pubKey, x, y);

	if (Test_PubKey(pubKey) != 0)
		return 1;
	else
		return 0;
}


int SM2_Encrypt(unsigned char* randK, epoint* pubKey, unsigned char M[], int klen, unsigned char C[])
{
   

	big C1x, C1y, x2, y2, rand;
	epoint* C1, * kP, * S;
	int i = 0;
	unsigned char x2y2[SM2_NUMWORD * 2] = {
    0 };
	SM3_STATE md;
	C1x = mirvar(0);
	C1y = mirvar(0);
	x2 = mirvar(0);
	y2 = mirvar(0);
	rand = mirvar(0);
	C1 = epoint_init();
	kP = epoint_init();
	S = epoint_init();

	//Step2.  calculate C1=[k]G=(rGx,rGy) 
	bytes_to_big(SM2_NUMWORD, randK, rand);
	ecurve_mult(rand, G, C1);            //C1=[k]G
	epoint_get(C1, C1x, C1y);
	big_to_bytes(SM2_NUMWORD, C1x, C, 1);
	big_to_bytes(SM2_NUMWORD, C1y, C + SM2_NUMWORD, 1);

	//Step3.  test if S=[h]pubKey if the point at infinity 
	ecurve_mult(para_h, pubKey, S);

	if (point_at_infinity(S))// if S is point at infinity, return error; 
		return ERR_INFINITY_POINT;

	//Step4.  calculate [k]PB=(x2,y2)
	ecurve_mult(rand, pubKey, kP);     //kP=[k]P
	epoint_get(kP, x2, y2);

	//Step5.  KDF(x2||y2,klen)
	big_to_bytes(SM2_NUMWORD, x2, x2y2, 1);
	big_to_bytes(SM2_NUMWORD, y2, x2y2 + SM2_NUMWORD, 1);
	SM3_KDF(x2y2, SM2_NUMWORD * 2, klen, C + SM2_NUMWORD * 3);
	if (Test_Null(C + SM2_NUMWORD * 3, klen) != 0)
		return ERR_ARRAY_NULL;

	//Step6.  C2=M^t
	for (i = 0; i < klen; i++) {
   
		C[SM2_NUMWORD * 3 + i] = M[i] ^ C[SM2_NUMWORD * 3 + i];
	}

	//Step7.  C3=hash(x2,M,y2) 
	SM3_init(&md);
	SM3_process(&md, x2y2, SM2_NUMWORD);
	SM3_process(&md, M, klen);
	SM3_process(&md, x2y2 + SM2_NUMWORD, SM2_NUMWORD);
	SM3_done(&md, C + SM2_NUMWORD * 2);

	return 0;
}



int SM2_Decrypt(big dB, unsigned char C[], int Clen, unsigned char M[]) {
   

	SM3_STATE md;
	int i = 0;
	unsigned char x2y2[SM2_NUMWORD * 2] = {
    0 };
	unsigned char hash[SM2_NUMWORD] = {
    0 };
	big C1x, C1y, x2, y2;
	epoint* C1, * S, * dBC1;
	C1x = mirvar(0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值