基于GMSSL的常用算法特点总结以及源代码分享


前言

本文主要有两部分,第一部分是主要是总结一些算法的特点,
第二部分是源代码,主要是基于GMSSL库的正确性测试和性能测试

GmSSL项目是OpenSSL项目的分支,并与OpenSSL保持接口兼容。因此GmSSL可以替代应用中的OpenSSL组件,并使应用自动具备基于国密的安全能力。


一、对称算法


这些东西网上已经很多总结的比较精炼的,我这里直接引用,也不做赘述


1.1对称加密算法常用的五种分组模式(ECB/CBC/CFB/OFB/CTR)

讲的很通俗易懂,很详细 大家可以直接跳转阅读
详解

1.2 3DES对称算法之双倍长密钥算法和三倍长密钥算法

详解

二、RSA

2.1 算法描述

	1. 选择两个大素数,q,p 对外保密,
    2.计算 n = q * p, n公开
    3.∮(n) = (p?1)?(q?1), ∮(n)保密
    4.随机选一个e值 e由于是作加密使用,故推荐使用小值,一般使用65537(216+1),65537只有两个bit,加密做幂运算的时候速度比较快
    5.ed = 1* mod(∮(n));  得出d值
    6.公钥(n,e) 私钥(n,d) 
    明文 c = m^e * mod(n); 
    密文m = c^e * mod(n);

2.2 中国剩余定理

作用:RSA解密操作中最耗时的地方就是解密计算c^d ,该定理主要作用就是通过降幂来一定程度下降低解密耗时

重新计算私钥:
dp = d \mod {p-1}
dq = d \mod {q-1}
qinv = q^{-1} \mod p
这样最后的私钥就是(p,q,d,dp,dq,qinv)

解密
m1=c^dp * mod§
m2=c^dq * mod(q)
h=qinv(m1?m2)mod§
m=m2+hq m即为明文
这样做虽然要计算两次模幂,但效率依然要比直接计算高得多。因为不管是指数还是模数都要小得多.

2.3特性

  1. 密钥长度增长一倍,公钥操作所需时间增加约4倍,私钥操作所需时间增加约8倍,公私钥生成时间约增长16倍。
  2. 一次能加密的密文长度与公钥长度成正比,如RSA1024,一次能加密的内容长度为 1024/8 =128byte(包含填充字节)。所 以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。
  3. 加密后密文的长度为公钥的长度,例如公钥长度为1024Bit(128Byte),最后生成的密文固定为 1024Bit(128Byte)。

三、哈希

(此处以sha1为例),哈希算法使用起来很简单 可以直接调用sha1函数计算摘要,他使用起来很简单,

但是在32位系统下可以访问的内存空间不能超过4G, 所以openssl还提供另一套API
调用流程如下:
int SHA1_Init(SHA_CTX *c);
int SHA1_Update(SHA_CTX *c, const void *data, unsigned long len);
int SHA1_Final(unsigned char *md, SHA_CTX *c);

SHA1_Init主要是用来初始化SHA_CTX 结构体,该结构体里存储了一些计算散列值的参数和基本相信,可以不关心。
32位情况下,当需要计算摘要的文件大小为5个G的时候,我们可以把文件分割为若干个小块,
在分别调用SHA1_Update函数,最后在调用SHA1_Final生成散列值即可,
看一下例子

byte buffer[10] = {"123456789"};

//假如我们要需要计算buffer的散列值

     char md[SHA_DIGEST_LENGTH];
     SHA_CTX shactx;
     SHA1_Init(&shactx);
     SHA1_Update(&shactx, buffer,5);
     SHA1_Update(&shactx, buffer+5, 4);
     SHA1_Final(md, &shactx);

//上述代码等价于 
     char md[SHA_DIGEST_LENGTH];
     SHA_CTX shactx;
     SHA1_Init(&shactx);
     SHA1_Update(&shactx, buffer,9);
     SHA1_Final(md, &shactx);

四、 代码

主要包含了 对称算法:sm4 ,des,3des,aes, 非对称算法:sm2,rsa , 哈希算法的正确性验证和性能测试。



#include <pthread.h>


#include "openssl/sms4.h"
#include "openssl/des.h"
#include "openssl/aes.h"

#include "openssl/sm2.h"
#include "openssl/rsa.h"

#include "openssl/sm3.h"
#include "openssl/md4.h"
#include "openssl/md5.h"
#include "openssl/sha.h"

#include "openssl/err.h"

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

#include <time.h>
#include <assert.h>

#define sleep(n) usleep(n * 1000)

typedef unsigned char byte;


long getms(struct timeval begin,struct timeval end);


//ascii to hex
int asciitohex(const byte *pIn, int iInLen, byte *pOut)
{
    int i = 0;
    uint8_t highByte, lowByte;
    
    if (iInLen < 2)
    {
        return 0;
    }

    int len = iInLen / 2;

    for (i = 0; i < iInLen; i += 2)
    {
        highByte = toupper(pIn[i]);
        lowByte  = toupper(pIn[i + 1]);
        
        if (highByte > 0x39)
        {
            highByte -= 0x37;
        }
        else
        {
            highByte -= 0x30;
        }
        
        if (lowByte > 0x39)
        {
            lowByte -= 0x37;
        }
        else
        {
            lowByte -= 0x30;
        }

        pOut[i / 2] = (highByte << 4) | lowByte;
    }
    
 
    return len;
}




int hextoascii(const byte* pIn, int iInLen, byte* pOut)
{
    int i, j;

    for (i = 0, j = 0; j < iInLen; j++, i=i+2)
    {
        if ( (pIn[j]/16) > 9 )
        {
            pOut[i] = (pIn[j]/16) + '0' + 7;
        }
        else
        {
            pOut[i] = (pIn[j]/16) + '0';
        }
        
        if ( (pIn[j]%16) > 9 )
        {
            pOut[i+1] = (pIn[j]%16) + '0' + 7;
        }
        else
        {
            pOut[i+1] = (pIn[j]%16) + '0';
        }
    }
    
    pOut[iInLen * 2] = '\0';

    return iInLen * 2;
}


//加密填充,不足16字节末尾填充全0至
int sms4_padding(const byte * input,  int inputlen,  byte * output, int * outputlen)
{
	if(NULL == input || inputlen <= 0 || NULL == output || NULL == outputlen)
	{
		return -1;
	}


	*outputlen = inputlen;
	memcpy(output, input, inputlen);
	
	if(inputlen % 16 != 0)
	{
		int paddlen = 16 - inputlen % 16;
		printf("paddlen:%d\n", paddlen);
		*outputlen += paddlen;

		const byte * c_zore = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
		//const byte * c_zore = "0000000000000000";
		memcpy(output + inputlen, c_zore, paddlen);
	}

	return 0;
}




int test_des_ecb(byte * intput, int inlen, byte* output, int * outlen, int nmode);
int test_des_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode);


int test_3des_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode);

int test_3des_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode);



int test_sm4_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_sm4_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode);

int test_aes128_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_aes128_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode);


int test_aes256_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_aes256_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode);


int test_sm2_enc(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_sm2_sign(byte * input, int inlen, byte* output, int * outlen, int nmode);


int test_rsa_enc(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_rsa_sign(byte * input, int inlen, byte* output, int * outlen, int nmode);


int test_hash_sm3(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_md4(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_md5(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_sha1(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_sha256(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_sha384(byte * input, int inlen, byte* output, int * outlen, int nmode);
int test_hash_sha512(byte * input, int inlen, byte* output, int * outlen, int nmode);




struct timeval begin;
struct timeval end;


//#define TEST_FUNCTION 1 //测试加解密功能 则打开该宏,  
#define TEST_TIME 1 	//统计加解密时间 打开该宏


#define SIZE  32 //输入数据长度


//测试算法
#define TEST_FUN_NAME test_sm2_enc


void test_unhash_algorithm()
{
	byte inputbuffer[SIZE + 1] = {0};
	memset(inputbuffer, 0x31,SIZE);

	byte enc_outputbuffer[10240] = {0};
	int enc_outlen = 0;

	int i = 0;

#ifdef TEST_FUNCTION
	printf("加密输入:");
	i = 0;
	while(i < SIZE)
	{
		printf("%02x", inputbuffer[i]);
		++i;
	}
	printf("\n");
		
#endif

	
	TEST_FUN_NAME(inputbuffer, SIZE, enc_outputbuffer, &enc_outlen, 1);

#ifdef TEST_FUNCTION
		printf("加密输出:");
	i = 0;
	while(i < enc_outlen)
	{
		printf("%02x", enc_outputbuffer[i]);
		++i;
	}
	printf("\n");
		
#endif

	printf("******************************\n");


	byte * decinput = enc_outputbuffer;
	int decinputlen = enc_outlen;

	
	byte dec_outputbuffer[10240] = {0};
	int dec_outlen = 0;
	
	
#ifdef TEST_FUNCTION
	printf("解密输入:");
	i = 0;
	while(i < decinputlen)
	{
		printf("%02x", decinput[i]);
		++i;
	}
	printf("\n");
		
#endif
	
	
	TEST_FUN_NAME(decinput, decinputlen, dec_outputbuffer, &dec_outlen, 0);
	
#ifdef TEST_FUNCTION
	printf("解密输出:");
	i = 0;
	while(i < dec_outlen)
	{
		printf("%02x", dec_outputbuffer[i]);
		++i;  
	}
	printf("\n");
		
#endif





}



typedef int (*pFn_testfun)(byte * , int , byte* , int * , int );

struct cmd
{
	const char *name;
	pFn_testfun ptestfun;
	int type;   //0 加密 1 签名 2哈希
};

#define TYPE_ENC_DEC 0
#define TYPE_SIGN_VERIFY 1
#define TYPE_HASH 2



#define MUTEX pthread_mutex_t
#define MUTEXINIT(m) pthread_mutex_init(m,NULL)
#define MUTEXLOCK(m) pthread_mutex_lock(m)
#define MUTEXUNLOCK(m) pthread_mutex_unlock(m)
#define MUTEXDESTROY(m) pthread_mutex_destroy(m)

MUTEX g_mutex_timeoutflga;


#define TIMEWAITFLAG 0
#define TIMEBEGIN 1
#define TIMEOUTFLAG 2

int timeoutflag = TIMEWAITFLAG;


int gettimeoutflag()
{
	int tempflag = 0;
	MUTEXLOCK(&g_mutex_timeoutflga);
	tempflag = timeoutflag;
	MUTEXUNLOCK(&g_mutex_timeoutflga);
	return tempflag;
}

void settimeoutflag(int tempflag)
{
	MUTEXLOCK(&g_mutex_timeoutflga);
	timeoutflag = tempflag;
	MUTEXUNLOCK(&g_mutex_timeoutflga);
}


void* time_proc(void * parm)
{

		settimeoutflag(TIMEBEGIN);

		sleep(1000);

		settimeoutflag(TIMEOUTFLAG);

	
}



struct PARM
{
	struct cmd * pcmd;
	int nmode;
};



void* rundata_proc(void * parm)
{

	struct PARM * pparm = (struct PARM*)parm;

	byte inputbuffer[SIZE + 1] = {0};
	memset(inputbuffer, 0x31,SIZE);
	
	byte enc_outputbuffer[10240] = {0};
	int enc_outlen = 0;
	
	int i = 0;
	
#ifdef TEST_FUNCTION
		printf("加密输入:");
		i = 0;
		while(i < SIZE)
		{
			printf("%02x", inputbuffer[i]);
			++i;
		}
		printf("\n");
			
#endif

		
		pparm->pcmd->ptestfun(inputbuffer, SIZE, enc_outputbuffer, &enc_outlen, pparm->nmode );
	
#ifdef TEST_FUNCTION
			printf("加密输出:");
		i = 0;
		while(i < enc_outlen)
		{
			printf("%02x", enc_outputbuffer[i]);
			++i;
		}
		printf("\n");
			
#endif
	
		printf("******************************\n");

		return NULL;
	
}



int main()
{
	
	
#if TEST_FUNCTION
	test_unhash_algorithm();
	return 0;
#else
	MUTEXINIT(&g_mutex_timeoutflga);
	struct cmd cmdlist[] = 
		{

			{"des_ecb", test_des_ecb, TYPE_ENC_DEC},
			{"des_cbc", test_des_cbc, TYPE_ENC_DEC},
			{"3des_ecb", test_3des_ecb, TYPE_ENC_DEC},
			{"3des_cbc", test_3des_cbc, TYPE_ENC_DEC},
			{"sm4_ecb", test_sm4_ecb, TYPE_ENC_DEC},
			{"sm4_cbc", test_sm4_cbc, TYPE_ENC_DEC},
			{"aes128_ecb", test_aes128_ecb, TYPE_ENC_DEC},
			{"aes128_cbc", test_aes128_cbc, TYPE_ENC_DEC},
			{"aes256_ecb", test_aes256_ecb, TYPE_ENC_DEC},
			{"aes256_cbc", test_aes256_cbc, TYPE_ENC_DEC},
			{"sm2_enc", test_sm2_enc, TYPE_ENC_DEC},
			{"sm2_sign", test_sm2_sign, TYPE_SIGN_VERIFY},
			{"rsa_enc", test_rsa_enc, TYPE_ENC_DEC},
			{"rsa_sign", test_rsa_sign, TYPE_SIGN_VERIFY},
			{"hash_sm3", test_hash_sm3, TYPE_HASH},
			{"hash_md4", test_hash_md4, TYPE_HASH},
			{"hash_md5", test_hash_md5, TYPE_HASH},
			{"hash_sha1", test_hash_sha1, TYPE_HASH},
			{"hash_sha256", test_hash_sha256, TYPE_HASH},
			{"hash_sha384", test_hash_sha384, TYPE_HASH},
			{"hash_sha512", test_hash_sha512, TYPE_HASH},
			{NULL, NULL, 0}
		};

		while(1)
		{

			struct cmd * pCmd = cmdlist;
			int i = 1;

			printf("%2d  %s\n",0, "退出");

			
			while(pCmd->name != NULL)
			{
				printf("%2d  %s\n",i, pCmd->name);
				++i;
				++pCmd;
			}

			
			
			int algorithmcount = 0;
			while(1)
			{
				printf("请输入需要测试的算法:");
				
				scanf("%d", &algorithmcount);

				if(0 == algorithmcount)
				{
					printf("退出\n");
					return;
				}

				
				if(algorithmcount > 0 && algorithmcount < (sizeof(cmdlist) / sizeof(struct cmd)))
				{
					break;
				}
				else
				{
					printf("输入错误\n");
				}
			}

			--algorithmcount;

			struct PARM parm;
			parm.pcmd = &(cmdlist[algorithmcount]);

			
			pthread_t time_id;
			pthread_t rundata_id;

			parm.nmode = 1;
			
			pthread_create(&rundata_id, NULL, rundata_proc, (void*)&parm);
			assert(rundata_id);
			sleep(1000);
			pthread_create(&time_id, NULL, time_proc, NULL);
			assert(time_id);

			if(cmdlist[algorithmcount].type != TYPE_HASH)
			{
				sleep (2000);
		
				parm.nmode = 0;
				
				pthread_create(&rundata_id, NULL, rundata_proc, (void*)&parm);
				assert(rundata_id);
				sleep(1000);
				pthread_create(&time_id, NULL, time_proc, NULL);
				assert(time_id);
			}
			sleep (2000);

			getchar();
			
			i = 1;
		}
	
#endif

}


//nmode = DES_ENCRYPT 加密, DES_ENCRYPT:解密
int test_des_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_des_ecb\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{	
		return -1;
	}

	DES_cblock key;
	DES_random_key (&key);
	DES_string_to_key ("pass", &key);
	
	int i = 0;
	
#ifdef TEST_FUNCTION
		
	printf("key:");
	while(i < sizeof(key))
	{
		printf("%02x", key[i]);
		++i;
	}
	printf("\n");
#endif

	DES_key_schedule schedule;
	DES_set_key_checked (&key, &schedule);


	i = 0;
	

#ifdef TEST_TIME

	long datacount = 0;

	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		DES_ecb_encrypt ((const_DES_cblock*)(input), (DES_cblock*)(output), &schedule, nmode);
		datacount += 8;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
		
	}
	gettimeofday(&end, NULL);

	long time = getms(begin, end);

	printf("test_des_ecb %s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",  time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);

#else

	while(i < inlen)
	{
		DES_ecb_encrypt((const_DES_cblock*)(input + i), (DES_cblock*)(output + i), &schedule, nmode);
		i += 8;
	}
	*outlen = inlen;

#endif

	return 0;
}



int test_des_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_des_cbc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	DES_cblock key;
	DES_random_key (&key);
	DES_string_to_key ("pass", &key);

	long i = 0;
#ifdef TEST_FUNCTION
	printf("key:");
	while(i < sizeof(key))
	{
		printf("%02x", key[i]);
		++i;
	}
	printf("\n");
#endif
	
	DES_key_schedule schedule;
	DES_set_key_checked (&key, &schedule);

	DES_cblock iv = {"\x00\x00\x00\x00\x00\x00\x00\x00"};

	
		
		
#ifdef TEST_TIME
		
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}
	
	
	gettimeofday(&begin, NULL);
	while(1)
	{
		DES_cbc_encrypt (input, output, inlen, &schedule, &iv,  nmode);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
		
	}
	gettimeofday(&end, NULL);
	

	long time = getms(begin, end);
	
	printf("test_des_cbc %s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
#else


	DES_cbc_encrypt (input, output, inlen, &schedule, &iv,  nmode);
	*outlen = inlen;
#endif

	
	return 0;

}








int test_aes128_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_aes128_ecb\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	AES_KEY key; 

	const int keylen = 128;

	byte userkey[64] = {0};
	memset(userkey, 0x11, 64);


	if(AES_ENCRYPT ==nmode)
	{
		AES_set_encrypt_key(userkey, keylen, &key);
	}
	else if(AES_DECRYPT == nmode)
	{
		AES_set_decrypt_key(userkey, keylen, &key);
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}
	
	int i = 0;

#ifdef TEST_FUNCTION
	
	printf("keylen:%d, key:", keylen);
	while(i < (keylen / 8))
	{
		printf("%02x", userkey[i]);
		++i;
	}
	printf("\n");
#endif
	


#ifdef TEST_TIME
			
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			AES_ecb_encrypt(input, output, &key, nmode);
			datacount += 16;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
	
		long time = getms(begin, end);
		
		printf("test_aes128_ecb%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
		
#else


	i = 0;
	while(i <inlen)
	{
		AES_ecb_encrypt(input + i, output + i, &key, nmode);
		i += 16;
	}
	*outlen = inlen;
#endif

	return 0;
}






int test_aes128_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_aes128_cbc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}	
	AES_KEY key; 
	
	const int keylen = 128;
	
	byte userkey[64] = {0};
	memset(userkey, 0x11, 64);
	
	
	
	if(AES_ENCRYPT ==nmode)
	{
		AES_set_encrypt_key(userkey, keylen, &key);
	}
	else if(AES_DECRYPT == nmode)
	{
		AES_set_decrypt_key(userkey, keylen, &key);
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}
	
	int i = 0;
	
#ifdef TEST_FUNCTION
		
	printf("keylen:%d, key:", keylen);
	while(i < (keylen / 8))
	{
		printf("%02x", userkey[i]);
		++i;
	}
	printf("\n");
#endif


	byte iv[16] = {0};

	
#ifdef TEST_TIME
				
			long datacount = 0;
			
			while(1)
			{
				if(TIMEBEGIN == gettimeoutflag()) //
				{
					break;			
				}
				sleep (1);
			}
			
			
			gettimeofday(&begin, NULL);
			while(1)
			{
				AES_cbc_encrypt(input, output, 16, &key, iv, nmode);
				datacount += 16;
				if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
				{
					break;			
				}
				
			}
			gettimeofday(&end, NULL);
			
		
			long time = getms(begin, end);
			
			printf("test_aes128_cbc%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
			
#else

	
	AES_cbc_encrypt(input, output, inlen, &key, iv, nmode);
	*outlen = inlen;
#endif
	return 0;

}



int test_aes256_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_aes256_ecb\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	
	AES_KEY key; 

	const int keylen = 256;

	byte userkey[64] = {0};
	memset(userkey, 0x11, 64);


	if(AES_ENCRYPT ==nmode)
	{
		AES_set_encrypt_key(userkey, keylen, &key);
	}
	else if(AES_DECRYPT == nmode)
	{
		AES_set_decrypt_key(userkey, keylen, &key);
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}
	
	int i = 0;

#ifdef TEST_FUNCTION
	
	printf("keylen:%d, key:", keylen);
	while(i < (keylen / 8))
	{
		printf("%02x", userkey[i]);
		++i;
	}
	printf("\n");
#endif
	
	
#ifdef TEST_TIME
					
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			AES_ecb_encrypt(input, output, &key, nmode);
			datacount += 16;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_aes256_ecb%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
		
#else
	i = 0;
	while(i <inlen)
	{
		AES_ecb_encrypt(input + i, output + i, &key, nmode);
		i += 16;
	}
	*outlen = inlen;
#endif
	return 0;
	
}






int test_aes256_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{

	printf("test_aes256_cbc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	AES_KEY key; 
	
	const int keylen = 256;
	
	byte userkey[64] = {0};
	memset(userkey, 0x11, 64);
	
	
	
	if(AES_ENCRYPT ==nmode)
	{
		AES_set_encrypt_key(userkey, keylen, &key);
	}
	else if(AES_DECRYPT == nmode)
	{
		AES_set_decrypt_key(userkey, keylen, &key);
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}
	
	int i = 0;
	
#ifdef TEST_FUNCTION
		
	printf("keylen:%d, key:", keylen);
	while(i < (keylen / 8))
	{
		printf("%02x", userkey[i]);
		++i;
	}
	printf("\n");
#endif
		
	byte iv[16] = {0};

#ifdef TEST_TIME
						
			long datacount = 0;
			
			while(1)
			{
				if(TIMEBEGIN == gettimeoutflag()) //
				{
					break;			
				}
				sleep (1);
			}
			
			
			gettimeofday(&begin, NULL);
			while(1)
			{
				AES_cbc_encrypt(input, output, inlen,  &key, iv, nmode);
				datacount += inlen;
				if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
				{
					break;			
				}
				
			}
			gettimeofday(&end, NULL);
			
			
			long time = getms(begin, end);
			
			printf("test_aes256_cbc%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
			
#else

	AES_cbc_encrypt(input, output, inlen,  &key, iv, nmode);
	*outlen = inlen;
	
#endif
	return 0;
}







int test_3des_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode)
{

	printf("test_3des_ecb\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	DES_key_schedule schedule1;
	DES_key_schedule schedule2;
	DES_key_schedule schedule3;

	//DES_set_key_checked会校验密钥的奇偶校验位和密钥强度,自定义密钥很容易校验不通过从而密钥设置失败,所以直接使用DES_set_key_unchecked

	const byte * keylist[3] = 
		{
			"\xb9\x86\x4f\x73\xf7\x23\x08\x6b",
			"\xb9\x86\x4f\x73\xf7\x23\x08\x6b",
			"\x11\x11\x11\x11\x11\x11\x11\x11"
		};
	

	DES_set_key_unchecked((const_DES_cblock*)keylist[0], &schedule1);

	DES_set_key_unchecked((const_DES_cblock*)keylist[1], &schedule2);
	
	DES_set_key_unchecked((const_DES_cblock*)keylist[2], &schedule3);

	
	int  i= 0;
#ifdef TEST_FUNCTION	
	
	printf("key1:");
	i = 0;
	while(i < strlen(keylist[0]))
	{
		printf("%02x", keylist[0][i]);
		++i;
	}
	printf("\n");

	printf("key2:");
	i = 0;
	while(i < strlen(keylist[1]))
	{
		printf("%02x", keylist[1][i]);
		++i;
	}
	printf("\n");

	printf("key3:");
	i = 0;
	while(i < strlen(keylist[2]))
	{
		printf("%02x", keylist[2][i]);
		++i;
	}
	printf("\n");
#endif


#ifdef TEST_TIME
							
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			DES_ecb3_encrypt ((const_DES_cblock*)(input + i), (const_DES_cblock*)(output + i), &schedule1, &schedule2, &schedule3, nmode);
			datacount += 8;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_3des_ecb%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
		
#else



	i = 0;
	while(i < inlen)
	{
		DES_ecb3_encrypt ((const_DES_cblock*)(input + i), (const_DES_cblock*)(output + i), &schedule1, &schedule2, &schedule3, nmode);
		i += 8;
	}
	*outlen = inlen;
#endif

	return 0;
	
}

int test_3des_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_3des_cbc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	DES_key_schedule schedule1;
	DES_key_schedule schedule2;
	DES_key_schedule schedule3;

	//DES_set_key_checked会校验密钥的奇偶校验位和密钥强度,自定义密钥很容易校验不通过从而密钥设置失败,所以直接使用DES_set_key_unchecked

	const byte * keylist[3] = 
		{
			"\xb9\x86\x4f\x73\xf7\x23\x08\x6b",
			"\xb9\x86\x4f\x73\xf7\x23\x08\x6b",
			"\x11\x11\x11\x11\x11\x11\x11\x11"
		};
	
	DES_set_key_unchecked ((const_DES_cblock*)keylist[0], &schedule1);

	DES_set_key_unchecked ((const_DES_cblock*)keylist[1], &schedule2);
	
	DES_set_key_unchecked ((const_DES_cblock*)keylist[2], &schedule3);

	
	int  i= 0;
#ifdef TEST_FUNCTION	
	
	printf("key1:");
	i = 0;
	while(i < strlen(keylist[0]))
	{
		printf("%02x", keylist[0][i]);
		++i;
	}
	printf("\n");

	printf("key2:");
	i = 0;
	while(i < strlen(keylist[1]))
	{
		printf("%02x", keylist[1][i]);
		++i;
	}
	printf("\n");

	printf("key3:");
	i = 0;
	while(i < strlen(keylist[2]))
	{
		printf("%02x", keylist[2][i]);
		++i;
	}
	printf("\n");
#endif

	DES_cblock iv = {"\x00\x00\x00\x00\x00\x00\x00\x00"};


#ifdef TEST_TIME
						
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}
	
	
	gettimeofday(&begin, NULL);
	while(1)
	{
		DES_ede3_cbc_encrypt(input, output, inlen, &schedule1, &schedule2, &schedule3, &iv, nmode);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
		
	}
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_3des_cbc%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
#else

	
	DES_ede3_cbc_encrypt(input, output, inlen, &schedule1, &schedule2, &schedule3, &iv, nmode);
	*outlen = inlen;

#endif
	
	return 0;
}










int test_sm4_ecb(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_sm4_ecb\n");
	if(NULL == input || inlen <= 0 || NULL == output || NULL == outlen || ((0 != nmode) && (1 != nmode)))
	{
		printf("参数错误\n");
		return -1;
	}

	const byte * key = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F";

	int  i= 0;
#ifdef TEST_FUNCTION	
	
	printf("key:");
	i = 0;
	while(i < strlen(key))
	{
		printf("%02x", key[i]);
		++i;
	}
	printf("\n");

#endif
	
	sms4_key_t sms4Key;

	int encmode = 0;
	

	if(1 == nmode)//enc 加密
	{
		sms4_set_encrypt_key (&sms4Key, key);
		encmode = 0;
	}
	else if(0 == nmode)//解密
	{
		sms4_set_decrypt_key(&sms4Key, key);
		encmode = 1;
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}

#ifdef TEST_TIME
							
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			sms4_ecb_encrypt(input + i, output + i, &sms4Key, encmode);
			datacount += 16;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_sm4_ecb%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
		
#else

	
	i = 0;
	while(i < inlen)
	{
		sms4_ecb_encrypt(input + i, output + i, &sms4Key, encmode);
		i += 16;
	}
	
	*outlen = inlen;
#endif
	return 0;

}


int test_sm4_cbc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	
	printf("test_sm4_cbc\n");
	if(NULL == input || inlen <= 0 || NULL == output || NULL == outlen || ((0 != nmode) && (1 != nmode)))
	{
		printf("参数错误\n");
		return -1;
	}

	const byte * key = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F";

	byte iv[16] = {0};

	int  i= 0;
#ifdef TEST_FUNCTION	
	
	printf("key:");
	i = 0;
	while(i < strlen(key))
	{
		printf("%02x", key[i]);
		++i;
	}
	printf("\n");

#endif
	
	sms4_key_t sms4Key;
	int encmode = 0;

	if(1 == nmode)//enc 加密
	{
		sms4_set_encrypt_key (&sms4Key, key);
		encmode = 0;
	}
	else if(0 == nmode)//解密
	{
		sms4_set_decrypt_key(&sms4Key, key);
		encmode = 1;
	}
	else
	{
		printf("模式错误\n");
		return -1;
	}

	
	
#ifdef TEST_TIME
								
			long datacount = 0;
			
			while(1)
			{
				if(TIMEBEGIN == gettimeoutflag()) //
				{
					break;			
				}
				sleep (1);
			}
			
			
			gettimeofday(&begin, NULL);
			while(1)
			{
				sms4_cbc_encrypt(input, output, inlen, &sms4Key, iv, encmode);
				datacount += inlen;
				if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
				{
					break;			
				}
				
			}
			gettimeofday(&end, NULL);
			
			
			long time = getms(begin, end);
			
			printf("test_sm4_cbc%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
			
#else

	sms4_cbc_encrypt(input, output, inlen, &sms4Key, iv, encmode);
	*outlen = inlen;

#endif	
	return 0;
}


int getsm2key(EC_KEY** ppkeypair, EC_GROUP** ppgroup)
{
	

	static EC_KEY *keypair = NULL;
	static EC_GROUP* group = NULL;

	if(EC_KEY_check_key(keypair))
	{
		*ppkeypair = keypair;
		*ppgroup = group;
		return 0;
	}
	
	int ret1,ret2;
	keypair = EC_KEY_new();
	group = EC_GROUP_new_by_curve_name (NID_sm2p256v1);

	ret1 = EC_KEY_set_group (keypair, group);
	ret2 = EC_KEY_generate_key (keypair);

	*ppkeypair = keypair;
	*ppgroup = group;
	return 0;
}




int test_sm2_enc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_sm2_enc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}
	
	EC_KEY *keypair = NULL;
	EC_GROUP* group1 =  NULL;

	getsm2key(&keypair, &group1);
	
	int i = 0;

#ifdef TEST_FUNCTION

	const EC_POINT * eckey_public = EC_KEY_get0_public_key (keypair);
	const BIGNUM * eckey_private = EC_KEY_get0_private_key (keypair);

	byte printfbuffer[1024] = {0};
	int nprivatekeylen = BN_num_bits (eckey_private);
	BN_bn2bin (eckey_private, printfbuffer);
	printf("privatekeylen:%d, privatekey:",nprivatekeylen);

	i = 0;
	while(i < nprivatekeylen)
	{
		printf("%02x", printfbuffer[i]);
		++i;
	}
	printf("\n");
	
	
#endif

	byte miwen[10240] = {0};
	int miwenlen = 0;

	byte* pstr = miwen;

	const EVP_MD *md = EVP_sm3();

	
	
		
#ifdef TEST_TIME

	if(1 == nmode)
	{
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			SM2CiphertextValue* cv =  SM2_do_encrypt(md, input, inlen, keypair);
			datacount += inlen;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_sm2_enc%s 执行时间:%ld(ws), 执行数据%ld(byte), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);

		return 0;
	}
	
#endif


	SM2CiphertextValue* cv =  SM2_do_encrypt(md, input, inlen, keypair);
	
	const EC_GROUP* group = EC_KEY_get0_group (keypair);


	miwenlen = i2o_SM2CiphertextValue (group1, cv, &pstr);

#ifdef TEST_FUNCTION

	printf("miwenlen:%d, miwen:", miwenlen);
	i = 0;
	while(i < miwenlen)
	{
		printf("%02x", miwen[i]);
		++i;
	}
	printf("\n");
#endif


	size_t miwenoutlen = 0;	
#ifdef TEST_TIME
	
	if(0 == nmode)
	{
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		
	
		gettimeofday(&begin, NULL);
		while(1)
		{
			SM2_do_decrypt(md,cv, output, &miwenoutlen, keypair);
			datacount += (miwenlen - 1);
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_sm2_enc%s 执行时间:%ld(ws), 执行数据%ld(bit), 速度:%ld(kbps)\n", nmode == 1?"加密":"解密",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	}
	
#else
	
	SM2_do_decrypt(md,cv, output, &miwenoutlen, keypair);

	*outlen = miwenoutlen;
#endif

	return 0;
	
}



int test_sm2_sign(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_sm2_sign\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}
	
		EC_KEY *keypair = NULL;
		EC_GROUP* group1 =  NULL;

		getsm2key(&keypair, &group1);
		int i = 0;
	
#ifdef TEST_FUNCTION
	
		const EC_POINT * eckey_public = EC_KEY_get0_public_key (keypair);
		const BIGNUM * eckey_private = EC_KEY_get0_private_key (keypair);
	
		byte printfbuffer[1024] = {0};
		int nprivatekeylen = BN_num_bits (eckey_private);
		BN_bn2bin (eckey_private, printfbuffer);
		printf("len:%d, privatekey:",nprivatekeylen);
	
		i = 0;
		while(i < nprivatekeylen)
		{
			printf("%02x", printfbuffer[i]);
			++i;
		}
		printf("\n");
		
	
#endif
	
	

#ifdef TEST_TIME

		

		if(1 == nmode)
		{
			long datacount = 0;
			
			while(1)
			{
				if(TIMEBEGIN == gettimeoutflag()) //
				{
					break;			
				}
				sleep (1);
			}
			
			
			gettimeofday(&begin, NULL);
			while(1)
			{
				ECDSA_SIG* ec_sig =  SM2_do_sign(input, inlen, keypair);
				++datacount;
				if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
				{
					break;			
				}
				
			}
			gettimeofday(&end, NULL);
			
			
			long time = getms(begin, end);
			
			printf("test_sm2_sign%s 执行时间:%ld(ws), 签名%d字节数据 %ld次数, 速度:%ld(次/s)\n", nmode == 1?"签名":"验签",	time, inlen, datacount, datacount * 1000000 / getms(begin, end));

		return 0;

		}
			
		
#endif
	
		
		
		ECDSA_SIG* ec_sig =  SM2_do_sign(input, inlen, keypair);
		
	
		 
#ifdef TEST_TIME
					 
		if(0 == nmode)
		{
			
			 long datacount = 0;
			 
			 while(1)
			 {
				 if(TIMEBEGIN == gettimeoutflag()) //
				 {
					 break; 		 
				 }
				 sleep (1);
			 }
			 
			 
			 gettimeofday(&begin, NULL);
			 while(1)
			 {
				 int ret = SM2_do_verify(input,inlen,ec_sig,  keypair);
				 ++datacount;
				 if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
				 {
					 break; 		 
				 }
				 
			 }
			 gettimeofday(&end, NULL);
			 
			 
			 long time = getms(begin, end);
			 
			 printf("test_sm2_sign%s 执行时间:%ld(ws),    验签 %ld次数, 速度:%ld(次/s)\n", nmode == 1?"签名":"验签",	 time, datacount, datacount * 1000000 / getms(begin, end));
		}
		 
		
#else
		 
		 int ret = SM2_do_verify(input,inlen,ec_sig,  keypair);
		
#endif
		
	
#ifdef TEST_FUNCTION	
		printf("SM2_do_verify result: %d\n", ret);
#endif
	return 0;
}




RSA * get_RSA()
{
	
	RSA* r = RSA_new();

//  rsa1024
#if 1
		byte e[] = {"00010001"};
		byte n[] = {"D4019BC61BB9AD30DCF031D0666A8DCA8DDF18B29368FD18161DA2C0C2A280C9085A70BB7C20D5510593EDDA7D50714FC62404E8B2B90B003940CDE6C4F29AF692CFE6A5B240BBCA6A7BBEF26CBEBE6952B3DAB409EB8561E7A29A74D2BCF3552485686B9E5275938D4886A1F1BD6E9182870F1E40879F61DAAABF2626900E09"};
		byte d[] = {"C015F100AF102D764F4825AA2F912D852FC3CA49CA3BDECD1B04A0F8CBA096D50E877B0AB3EDBFB8D837EED2FEA58AF4FF8E95100D16917C1363BEEAEED8ED4303173DC714139631BDBA7670B82A3E3F2CAF723D95ADC6180A47922A3AF6170FFCE24A5B6ADA5175B132F4B9FF92E44F2D04BA211500879DF3E4EC539B21DACD"};
		byte p[] = {"EAE657604EC3A7B24DAE0DEB34E7661F104C6C62AB7711AF9BF838A01BC687255204104CA477C6BEFE93872300575200149BD227A2AD98FBD37DD2F2EA041FF3"};
		byte q[] = {"E70CD16453BA5BA4966A599ECF1DA7E9D8A9A5F8DDFF9DF3C3E333F8FC2A7FA160A6CB9BD6B02D3501BABA61BDC6A6853902DD05502F7B0E3D4743805F425513"};
		byte dp[] = {"E50EB6979856DC5957BC69A039978812B48F0185FA1402F00E94AF8B196AAF70AA1882586A6CCE268313134D0351230A270E8790D4E6996EBF9E4BAD4A9BB917"};
		byte dq[] = {"928DFCDBA88852CCE963F808D5D337C90AD74121C49EF92FC01703C6711CFBEBFF048DAE01D5AA372F2BA4418F40CC2B40E8620D96B92752F6E797177C54F4E5"};
		byte qinv[] = {"CDEF5E7C93F0FA0EF4DB1A5F99F9F663BC9E5BA890F892B77300EF4A12BFC6C5861FC422BBDBFAC83D848DADE3D348C8DC108F2FF201534B2D6255CB603FC96B"};
#else
	//rsa2048
		byte e[] = {"00010001"};						 
		byte n[] = {"C13BDDB8814473439489275D13578B7B19FAE07F8BD21B71D40B42127B0EF66A55CC993088E7C74DB798A6C8AD28D5768FB337C9CC0160182AB6F9FE52A4E9E5FA81B72B799D5E3DE1879669F39BE34DC2C00F04818FE9820748209A49AEFFCF53CB6C7A196D42F36C05A0812C1D447DE3E5BCD7A7E1A76811E877B63235BBA05C694F3E1DBF521DA0384CC4145715FCD8424024840AB376AB3EAE35536A7DBD869559FBEE27E11DBD5CCA7794FB59B4FFEB9B509AB0FF1127F4B6FEB6122D1B91995D57E1A0101522F51593EC211D456436ED45CBBEB6DE4D9C77C1C4E1071C46F12A45C7073B185E93FADB3F91DF6D261E8E1CB773218D419351450C3C5C59"};
		byte d[] = {"00A309E009CD07F439111AA81BE035FD79E071CCF9D0FF762894C0EAFEACD5F313C550DBF0179378961A52B2669FB3D46834D7023B41E5E72E7CDBE612AFA875B195ABDCE0D1BBF5C8408226673F2448A553ACB8FF145258B35D717E10B01AF7BBF6F7AC8F58E4D7988B8C33E0C957E8724FD7877E6E27F717D8044CFD6D5FE8EDEC1FF2B69D55AFACA1D688A5BE5B9E46F67AFF6E5B25BCDF3E7428DF109A2C3886A6852A7CF09CE032A698933AAD39BB537C5ACBDC817FA1E3BE1FB2B9D5C78236BFE2807F9C72196EE624F54642DDDCF42A6F60ED6D25702D6D19151C53A5A396073E4A2703A9B47183DA607E25B569639B13C3865DCA6D4D6A25C57EAA61"};
		byte p[] = {"F3E234B127CF142D3C7B62715507E0507ABBD17132557DB51E51F107D42D57470D51C51D6C03471A127ACA534AB77F74A2BC1F7D15A29684293029002193C55F94C31CCDFA832D05EE9563D16493BFB8C7773860DD6EAD2F24FB08E1350F349E42BC740722F65D437C072346E1DD8687425A88BA3231F8606A4B85A75A3B108B"};
		byte q[] = {"CAD57ABE125370E4290E7F14C9F8432490C67AA83BB05BA8AEE8B47F023BAEF804154DF9C2047B6B00C6FC5188C80DEA607BB6C04CFE930DB865B952E8028C11543C0FA5E49BC496758F9A39BCA02940F928BA2CCC2C651AA07EBC7F211CC6AE55315BCB357BC088E837284CD857AA03674CF32B49D74E292CCD3022DC275F2B"};
		byte dp[] = {"11DAD7BCB88B6290C542CB3C3CDB6CC2B7999485D3078B427D4BC677AA42FF86C624DC678106E467B63EA31D61F4F931D2D02F05FB5581EB7F10758FFAE554A7E0BE40179C658A204B0D48D785A3837FC5AAA6C800AE1FA3B9F35EFD0DE36518C90DFEF89EC8A69F502F3D97ECE548FA12138ABB06FDBD8F6178D1FA2492FA6D"};
		byte dq[] = {"5E86AA9315DB490B2B8F13EE4E49A290D1DF8D9E056324F431BF450EC3ADA8D6F0A0351CA62C8C8FCB66F083D6E8D4835BBF8BE5867C456FE9758EAE726D6D754DFA47989A3775A060DD3194A2B149487C555C9E2FF0A89586224A1A3D063A19589E8E16DFAFF2845B240965F694B428ADE59095A5EDEF01055E0286DC6E84CD"};
		byte qinv[] = {"84D3109839E1167D7AF13F4D55015060D3BAEBE8DF1AE404B1DB985960A5515B840AA809CC7D1D978DB38AFE1B9B16686AC9ED23F640229C61EE6F13E74864E417F120E326F22AABE0B8EA0A31E8EA2DD282CE1943CD6B528E85AD2B11B64D31045A950F0E136A2BE00BF2E905E5B320481DE72C10B5E2AF9503FA9C40CFC7D2"};

#endif
		BIGNUM * bignum_e = BN_new();	
		BIGNUM * bignum_n = BN_new();	
		BIGNUM * bignum_d = BN_new();	
		BIGNUM * bignum_p = BN_new();	
		BIGNUM * bignum_q = BN_new();	
		BIGNUM * bignum_dp = BN_new();	
		BIGNUM * bignum_dq= BN_new();	
		BIGNUM * bignum_qinv = BN_new();	
	
		BN_hex2bn (&bignum_e, e);
		BN_hex2bn (&bignum_n, n);
		BN_hex2bn (&bignum_d, d);
		BN_hex2bn (&bignum_p, p);	
		BN_hex2bn (&bignum_q, q);
		BN_hex2bn (&bignum_dp, dp);
		BN_hex2bn (&bignum_dq, dq);
		BN_hex2bn (&bignum_qinv, qinv);
		
		
		RSA_set0_key(r, bignum_n, bignum_e, bignum_d);
		RSA_set0_factors(r, bignum_p, bignum_q);
		RSA_set0_crt_params(r,bignum_dp, bignum_dq, bignum_qinv);

		
	if(1 != RSA_check_key(r))
	{
			
		unsigned long ulerr = ERR_get_error();

		char szErrMsg[1024] = {0};
		char * pTemp = NULL;
		pTemp = ERR_error_string (ulerr,szErrMsg);

		printf("errorid:%04x \n errmsg:%s\n", ulerr, szErrMsg);
		
		ERR_reason_error_string (ulerr);

		printf(" ERR_reason:%s\n", szErrMsg);

		return NULL;
	}

	return r;
}


int test_rsa_enc(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	
	printf("test_rsa_enc\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}

	
	RSA * r = get_RSA();
	if(NULL == r)
	{	
		return;
	}

		
	int i = 0;

	

	if(1 == nmode)
	{
#ifdef TEST_TIME
					 
		
	 long datacount = 0;
	 
	 while(1)
	 {
		 if(TIMEBEGIN == gettimeoutflag()) //
		 {
			 break; 		 
		 }
		 sleep (1);
	 }

	 byte inpurbuffer[256] = {0};
	 memset(inpurbuffer, 0x31,256);
	 
	 gettimeofday(&begin, NULL);
	 while(1)
	 {
		RSA_public_encrypt(128, inpurbuffer,output , r, RSA_NO_PADDING);
		 datacount += 128;
		 if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		 {
			 break; 		 
		 }
		 
	 }
	 gettimeofday(&end, NULL);
	 
	 
	 long time = getms(begin, end);
	 
	 printf("test_rsa_enc%s 执行时间:%ld(ws),    执行数据%ld(byte), 速度:%ld(Kbps)\n", nmode == 1?"加密":"解密",	 time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
#else
		RSA_public_encrypt(inlen, input,output , r, RSA_NO_PADDING);

#endif
	}
	else if(0 == nmode)
	{

#ifdef TEST_TIME
					 

	 long datacount = 0;
	 
	 while(1)
	 {
		 if(TIMEBEGIN == gettimeoutflag()) //
		 {
			 break; 		 
		 }
		 sleep (1);
	 }

	 byte inpurbuffer[256] = {"41102679341F49180CDFA2214221FF0B9AE24BE0FF4D4637BFD21914AC1BB3F9D1C9F4570A612CDD8DF1CB8D10F8FD917868966B470526FDB24E98658345C4994409564CBD369DD461DA95F39BE4BCADFCB8E35987B1AAFB2F2AE1E90FE7C6596EB13795D65408D94339E513647315F2F7B85A180405032A1E8DBD809F12CBAF"};
	
	 gettimeofday(&begin, NULL);
	 while(1)
	 {
		RSA_private_decrypt(inlen, input, output, r, RSA_NO_PADDING);
		 datacount += 128;
		 if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		 {
			 break; 		 
		 }
		 
	 }
	 gettimeofday(&end, NULL);
	 
	 long time = getms(begin, end);
	 
	 printf("test_rsa_enc%s 执行时间:%ld(ws),    执行数据%ld(byte), 速度:%ld(Kbps)\n", nmode == 1?"加密":"解密",	 time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
#else
		RSA_private_decrypt(inlen, input, output, r, RSA_NO_PADDING);
#endif

	}
	else
	{
		printf("模式错误\n");
	}

	*outlen = 1024 / 8;

	RSA_free(r);
	
} 

int test_rsa_sign(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_rsa_sign\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen || (nmode != 0 && nmode != 1))
	{
		printf("参数错误\n");
		return -1;
	}
	RSA * r = get_RSA();
	if(NULL == r)
	{	
		return;
	}

	byte sigret[1024] = {0};
	int siglen = 0;


	
#if TEST_TIME
	if(1 == nmode)
	{
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
		byte inpurbuffer[256] = {0};
		 memset(inpurbuffer, 0x31,256);
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			RSA_sign(NID_sha1, inpurbuffer, 64, sigret, &siglen, r);
			++datacount;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_rsa_sign%s 执行时间:%ld(ws),签名%d字节数据 %ld次数, 速度:%ld(次/s)\n", nmode == 1?"签名":"验签",	time, 64, datacount, datacount * 1000000 / getms(begin, end));
	
		return 0;
	
	}

#else

	RSA_sign(NID_sha1, input, inlen / 2, sigret, &siglen, r);

#endif

	int i = 0;
	
		 
#ifdef TEST_FUNCTION	
	printf("siglen:%d, sigret:", siglen);
	i = 0;
	while(i < siglen)
	{
		printf("%02x", sigret[i]);
		++i;
	}
	printf("\n");

#endif


#if TEST_TIME
	if(0 == nmode)
	{
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
	
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			int ret = RSA_verify(NID_sha1, input, 64, sigret, siglen,  r);
			++datacount;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
			
		}
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_rsa_sign%s 执行时间:%ld(ws),验签%ld次数, 速度:%ld(次/s)\n", nmode == 1?"签名":"验签",	time, datacount, datacount * 1000000 / getms(begin, end));
	
	return 0;
	
	}

#else

	int ret = RSA_verify(NID_sha1, input, inlen / 2, sigret, siglen,  r);
#endif
	
#ifdef TEST_FUNCTION	
		printf("RSA_verify result : %d\n", ret);
#endif

	RSA_free(r);
	return 0;
}

int test_hash_sm3(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_sm3\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}

	sm3_ctx_t ctx;
	sm3_init(&ctx);

	
#if TEST_TIME

	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		sm3_update(&ctx, input, inlen);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
		
	}

	sm3_final(&ctx, output);
	
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_sm3%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
#else

	sm3_update(&ctx, input, inlen);
	sm3_final(&ctx, output);

#endif
	
	
	*outlen = SM3_DIGEST_LENGTH;

	return 0;
	
}
int test_hash_md4(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_md4\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}

	MD4_CTX ctx;
	MD4_Init(&ctx);
	
#if TEST_TIME
	
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		MD4_Update(&ctx, input, inlen);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
	}

	MD4_Final(output, &ctx);
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_md4%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	

	
#else
	MD4_Update(&ctx, input, inlen);
	MD4_Final(output, &ctx);
#endif

	
	
	*outlen = MD4_DIGEST_LENGTH;

	return 0;

}


int test_hash_md5(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_md5\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}
	MD5_CTX ctx;
	MD5_Init(&ctx);
	
	
#if TEST_TIME
	
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		MD5_Update(&ctx, input, inlen);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
	}
	MD5_Final(output, &ctx);
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_md4%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	

	
#else	
	MD5_Update(&ctx, input, inlen);
	MD5_Final(output, &ctx);
#endif
	*outlen = MD5_DIGEST_LENGTH;
	return 0;

}


int test_hash_sha1(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_sha1\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}

	byte md[SHA_DIGEST_LENGTH] = {0};

	SHA_CTX c;
	SHA1_Init(&c);


	
	
#if TEST_TIME
	
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		SHA1_Update (&c, input,  inlen);
	
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
	}
	SHA1_Final(output, &c);
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_sha1%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
#else	

	SHA1_Update (&c, input,  inlen);
	SHA1_Final(output, &c);
#endif

	*outlen = SHA_DIGEST_LENGTH;
	return 0;



	
}
int test_hash_sha256(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	
	printf("test_hash_sha256\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}
	
	SHA256_CTX c;
	SHA256_Init(&c);

		
	
#if TEST_TIME
	
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		SHA256_Update (&c, input,  inlen);
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
	}
	SHA256_Final(output, &c);
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_sha256%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
#else	

	SHA256_Update (&c, input,  inlen);
	SHA256_Final(output, &c);
#endif
	*outlen = SHA256_DIGEST_LENGTH;
	
	return 0;
}
int test_hash_sha384(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_sha384\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen )
	{
		printf("参数错误\n");
		return -1;
	}
	SHA512_CTX c;
	SHA384_Init(&c);


		
	
#if TEST_TIME
	
	long datacount = 0;
	
	while(1)
	{
		if(TIMEBEGIN == gettimeoutflag()) //
		{
			break;			
		}
		sleep (1);
	}

	
	gettimeofday(&begin, NULL);
	while(1)
	{
		SHA384_Update (&c, input,  inlen);
	
		datacount += inlen;
		if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
		{
			break;			
		}
	}
		SHA384_Final(output, &c);
	gettimeofday(&end, NULL);
	
	
	long time = getms(begin, end);
	
	printf("test_hash_sha384%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
	
	
	
#else	

	SHA384_Update (&c, input,  inlen);
	SHA384_Final(output, &c);
#endif

	*outlen = SHA384_DIGEST_LENGTH;
		
	return 0;

}


int test_hash_sha512(byte * input, int inlen, byte* output, int * outlen, int nmode)
{
	printf("test_hash_sha512\n");
	if(NULL == input || 0 >= inlen || NULL == output || NULL ==  outlen)
	{
		printf("参数错误\n");
		return -1;
	}
	SHA512_CTX c;
	SHA512_Init(&c);

		
		
#if TEST_TIME
		
		long datacount = 0;
		
		while(1)
		{
			if(TIMEBEGIN == gettimeoutflag()) //
			{
				break;			
			}
			sleep (1);
		}
	
		
		gettimeofday(&begin, NULL);
		while(1)
		{
			SHA512_Update (&c, input,  inlen);
		
			datacount += inlen;
			if(TIMEOUTFLAG == gettimeoutflag()) //时间到了就退出
			{
				break;			
			}
		}
		SHA512_Final(output, &c);
		gettimeofday(&end, NULL);
		
		
		long time = getms(begin, end);
		
		printf("test_hash_sha512%s,执行时间:%ld(ws),执行数据%ld(byte), 速度:%ld(kbps)\n", "计算摘要",	time, datacount, datacount * 1000000 / getms(begin, end) / 1024 * 8);
		
		
#else	

	SHA512_Update (&c, input,  inlen);
	SHA512_Final(output, &c);
	
#endif	
	*outlen = SHA512_DIGEST_LENGTH;
		
	return 0;
}



long getms(struct timeval begin,struct timeval end)
{
	//tv_sec tv_usec
	if(end.tv_usec >= begin.tv_usec)
	{
		return  (end.tv_sec - begin.tv_sec) * 1000 * 1000 +  (end.tv_usec - begin.tv_usec);
	}
	else
	{
		return (end.tv_sec - begin.tv_sec) * 1000 * 1000 -  (begin.tv_usec - end.tv_usec);
	}
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值