实验一 密码引擎-4-国密算法交叉测试
在Ubuntu中使用OpenSSL用SM4算法加密上述文件,然后用龙脉eKey解密,提交代码和运行结果截图
openssl加密
UKEY解密
OPENSSL代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
int main(int argc, char *argv[])
{
int rv;
unsigned char Buffer[4096]; //保存待处理的文件数据的数组
unsigned char SessionKey[16]; //加密发送文件的会话密钥
unsigned int SessionKeyLen = 16; //会话密钥的密文长度
unsigned char err[1024];
OpenSSL_add_all_algorithms();
//产生随机数,作为会话密钥
RAND_bytes(SessionKey,16);
//利用会话密钥加密原文,并输出到密文到文件
FILE *fpIn;
FILE *fpOut;
fpIn = fopen(argv[1],"rb");
if(fpIn == NULL)
{
return 0;
}
fpOut = fopen(argv[2],"wb");
if(fpOut == NULL)
{
return 0;
}
//密文文件格式:
// |------------------|--------|------------------------|------------|--------------
// |签名信息长度4Bytes|签名信息|会话密钥的密文长度4Bytes|会话密钥密文|原文数据的密文
fwrite(&SessionKeyLen,1,sizeof(SessionKeyLen),fpOut); //写密文的会话密钥的长度到文件
fwrite(SessionKey,1,SessionKeyLen,fpOut);//写密文的会话密钥到文件
EVP_CIPHER_CTX *ctx;
ctx = EVP_CIPHER_CTX_new();
unsigned char out[1024];
int outl;
unsigned char in[1024];
int inl;
EVP_CIPHER_CTX_init(ctx);//初始化密码算法上下文
//设置密码算法和密钥,这里采用128位的sm4算法。
rv = EVP_EncryptInit_ex(ctx,EVP_sm4_ecb(),NULL,SessionKey,NULL);
if(rv != 1)
{
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//以1024字节为单位,循环读取原文,并加密,然后输出到密文文件。
for(;;)
{
inl = fread(in,1,1024,fpIn);//读取1024字节
if(inl <= 0)
break;
rv = EVP_EncryptUpdate(ctx,out,&outl,in,inl);//加密
if(rv != 1)
{
fclose(fpIn);
fclose(fpOut);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fwrite(out,1,outl,fpOut);//输出密文到文件
}
rv = EVP_EncryptFinal_ex(ctx,out,&outl);//完成加密,输出剩余的密文。
if(rv != 1)
{
fclose(fpIn);
fclose(fpOut);
EVP_CIPHER_CTX_cleanup(ctx);
return 0;
}
fwrite(out,1,outl,fpOut);//写文件
fclose(fpIn);
fclose(fpOut);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
UKEY代码
#include "../include/skfapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define ERROR_THROW(r) {if((r) != SAR_OK) goto END_OF_FUN;}
int main(int argc, char* argv[])
{
ULONG ulRslt = SAR_OK;
HANDLE hdev = NULL;
HANDLE happ = NULL;
HANDLE hkey = NULL;
HANDLE hcont = NULL;
char szDevName[256] = {0};
ULONG ulDevNameLen = 256;
char szAppName[256] = {0};
ULONG ulAppNameLen = 256;
char szContName[256] = {0};
ULONG ulContName = 256;
char *pUserPin = "12345678";
ULONG ulRetryCount = 0;
BYTE SessionKey[16]; //会话密钥
unsigned int SessionKeyLen; //会话密钥长度
BYTE pbEncrypt[256] = {0};
ULONG ulEncryptLen = 256;
BLOCKCIPHERPARAM bp = {0};
int nDatalen = strlen(pData);
char *pContName = szContName;
char *pdevname = szDevName;
char *pappname = szAppName;
ulRslt = SKF_EnumDev(TRUE, szDevName, &ulDevNameLen);
ERROR_THROW(ulRslt)
ulRslt = SKF_ConnectDev(pdevname, &hdev);
ERROR_THROW(ulRslt)
ulRslt = SKF_EnumApplication(hdev, szAppName, &ulAppNameLen);
ERROR_THROW(ulRslt)
ulRslt = SKF_OpenApplication(hdev, pappname, &happ);
ERROR_THROW(ulRslt)
ulRslt = SKF_VerifyPIN(happ, USER_TYPE, pUserPin, &ulRetryCount);
ERROR_THROW(ulRslt)
ulRslt = SKF_EnumContainer(happ, szContName, &ulContName);
ERROR_THROW(ulRslt)
ulRslt = SKF_OpenContainer(happ, pContName, &hcont);
ERROR_THROW(ulRslt)
//根据安全报文的文件格式,读取安全报文
//--------------------|--------|--------------
//会话密钥的长度4Bytes|会话密钥|原文数据的密文
//密文Sessionkey
FILE* fp = fopen(argv[1],"rb");
FILE *fpOut = fopen(argv[2],"wb");
if(fp == NULL)
{
fprintf(stderr,"打开加密文件失败\n");
goto END_OF_FUN;
}
if(fpOut==NULL)
{
fprintf(stderr,"打开解密文件失败!");
fclose(fp);
goto END_OF_FUN;
}
fread(&SessionKeyLen,1,sizeof(SessionKeyLen),fp);
printf("%d",SessionKeyLen);
if((SessionKeyLen<=0)||(SessionKeyLen >18))
{
fprintf(stderr,"读取会话密钥错误!");
fclose(fp);
goto END_OF_FUN;
}
fread(SessionKey,1,SessionKeyLen,fp);
ulRslt = SKF_SetSymmKey(hdev, SessionKey, SGD_SM4_ECB, &hkey);
ERROR_THROW(ulRslt)
bp.PaddingType = 1;
ulRslt = SKF_DecryptInit(hkey, bp);
ERROR_THROW(ulRslt)
//利用明文的会话密钥解密安全报文
BYTE out[1024];
INT32 outl;
BYTE in[1024];
INT32 inl;
for( ; ; )
{
inl = fread(in,1,1024,fp);//读取1024个字节
if(inl <= 0)
break;
ulRslt = SKF_DecryptUpdate(hkey,in, inl,out, &outl);
if(ulRslt != SAR_OK)
{
fclose(fp);
fclose(fpOut);
goto END_OF_FUN;
}
fwrite(out,1,outl,fpOut);
}
ulRslt = SKF_DecryptFinal(hkey, out, &outl);
if(ulRslt != SAR_OK)
{
fclose(fp);
fclose(fpOut);
goto END_OF_FUN;
}
fwrite(out,1,outl,fpOut);
printf("解密成功!");
fclose(fp);
fclose(fpOut);
END_OF_FUN:
printf("%x\n",ulRslt);
if(hkey)
SKF_CloseHandle(hkey);
if(hcont)
SKF_CloseContainer(hcont);
if(happ)
SKF_CloseApplication(happ);
if(hdev)
SKF_DisConnectDev(hdev);
return 1;
}