实验一-密码引擎-加密API实现与测试

1 下载并查找GMT 0018-2012密码设备应用接口规范原始文档进行学习 (5分)

2 实现GMT 0018-2012密码设备应用接口规范的接口函数,至少实现:

1)设备管理中的打开设备,关闭设备,获取设备信息,产生随机数(4分)
2)密钥管理导出 ECC 签名公钥;SDF_ExportSignPublicKey_ECC I.导出 ECC加密公钥∶SDF_ExportEncPublicKey_ECC J. 产生 ECC非对称密钥对并输出∶SDF_GenerateKeyPair_ECC
K. (6分)
3)非对称算法(至少支持SM2):外部密钥 ECC验证∶SDF_ExternalVerify_ECC ,内部密钥 ECC签名;SDF_InternalSign_ECC ,内部密钥 ECC验证∶SDF_InternalVerify_ECC 外部密钥 ECC加密∶SDF_ExternalEncrypt_ECC
(8分)
4)对称算法(至少支持SM4)∶SDF_Encrypt 对称解密∶SDF_Dccrypt 计算 MAC∶SDF_CalculateMAC(6分)
5)杂凑算法(至少支持SM3):· 杂凑运算初始化∶SDF_HashInit· 多包杂凑运算∶SDF_HashUpdate· 杂凑运算结束∶SDF_HashFinal(6分)

密钥管理要求(10分)
基于本标准设计、开发的密码设备在密钥管理方面,应满足以下要求; 1)设备密钥的使用不对应用系统开放; 2) 密钥必须用安全的方法产生并存储;
3) 在任何时间、任何情况下,除公钥外的密钥均不能以明文形式出现在密码设备外; 4) 密码设备内部存储的密钥应具备有效的密钥保护机制,防止解剖、探测和非法读取; 5) 密码设备内部存储的密钥应具备权限控制机制,防止非法使用和导出。

设备状态要求(5分)
基于本标准设计、开发的密码设备在设备状态方面,应满足以下要求; 1) 密码设备应具有初始和就绪两个状态;
2) 未安装设备密钥的密码设备应处干初始状态,已安装设备密钥的密码设备应处于就绪状态; 3) 在初始状态下,除可读取设备信息、设备密钥的生成或恢复操作外,不能执行任何操作,生成或恢复设备密钥后,密码设备处于就绪状态;
4) 在就绪状态下,除设备密钥的生成或恢复操作外,应能执行任何操作; 5) 在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。

一、下载并查找GMT 0018-2012密码设备应用接口规范原始文档进行学习

基础密码服务包括密钥生成、单一的密码运算、文件管理等服务。
本标准采用C语言描述接口函数,无特别说明时,函数中参数的长度单位均为字节数。

二、实现GMT 0018-2012密码设备应用接口规范的接口函数

1)设备管理中的打开设备,关闭设备,获取设备信息,产生随机数

2)密钥管理导出 ECC 签名公钥;SDF_ExportSignPublicKey_ECC I.导出 ECC加密公钥∶SDF_ExportEncPublicKey_ECC J. 产生 ECC非对称密钥对并输出∶SDF_GenerateKeyPair_ECC
K.

3)非对称算法(至少支持SM2):外部密钥 ECC验证∶SDF_ExternalVerify_ECC ,内部密钥 ECC签名;SDF_InternalSign_ECC ,内部密钥 ECC验证∶SDF_InternalVerify_ECC 外部密钥 ECC加密∶SDF_ExternalEncrypt_ECC
(8分)

4)对称算法(至少支持SM4)∶SDF_Encrypt 对称解密∶SDF_Dccrypt 计算 MAC∶SDF_CalculateMAC(6分)

5)杂凑算法(至少支持SM3):· 杂凑运算初始化∶SDF_HashInit· 多包杂凑运算∶SDF_HashUpdate· 杂凑运算结束∶SDF_HashFinal(6分)

密钥管理要求(10分)

基于本标准设计、开发的密码设备在密钥管理方面,应满足以下要求; 1)设备密钥的使用不对应用系统开放; 2) 密钥必须用安全的方法产生并存储;
3) 在任何时间、任何情况下,除公钥外的密钥均不能以明文形式出现在密码设备外; 4) 密码设备内部存储的密钥应具备有效的密钥保护机制,防止解剖、探测和非法读取; 5) 密码设备内部存储的密钥应具备权限控制机制,防止非法使用和导出。

设备状态要求

基于本标准设计、开发的密码设备在设备状态方面,应满足以下要求; 1) 密码设备应具有初始和就绪两个状态;
2) 未安装设备密钥的密码设备应处干初始状态,已安装设备密钥的密码设备应处于就绪状态; 3) 在初始状态下,除可读取设备信息、设备密钥的生成或恢复操作外,不能执行任何操作,生成或恢复设备密钥后,密码设备处于就绪状态;
4) 在就绪状态下,除设备密钥的生成或恢复操作外,应能执行任何操作; 5) 在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。

代码如下

#ifndef _SDF_H
#define _SDF_H
//定义设备信息结构
typedef struct DeviceInfo_st{
unsigned char IssuerName[40]; //设备生产商名称
unsigned char DeviceName[16];
unsigned char DeviceSerial[16];
unsigned int DeviceVersion;
unsigned int StandardVersion;
unsigned int AsymAlgAbility[2];
unsigned int SymAlgAbility;
unsigned int HashAlgAbility;
unsigned int BufferSize;
}DEVICEINFO;

//Error Code
#define SDF_OK 0x0 //操作成功
#define SDR_BASE   0x01000000   //错误码基础值
#define SDR_UNKNOWERR   SDR_BASE+0x00000001  //未知错误
#define SDR_NOTSUPPORT   SDR_BASE+0x00000002  //不支持的接口调用
#define SDR_COMMFAIL   SDR_BASE +0x00000003  //与设备通信失败
#define SDR_HARDFAIL    SDR_BASE+ 0x00000004   //运算模块无响应
#define SDR_OPENDEVICE   SDR_BASE+0x00000005  //打开设备失败
#define SDR_OPENSESSION  SDR_BASE + 0x00000006  //创建会话失败
#define SDR_PARDENY   SDR_BASE +0x00000007    //无私钥使用权限
#define SDR_KEYNOTEXIST   SDR_ BASE+0x00000008   //不存在的密钥调用
#define SDR_ALGNOTSUPPORT   SDR_BASE + 0x00000009  //不支持的算法调用
#define SDR_ALGMODNOTSUPPORT   SDR_BASE+ 0x0000000A   //不支持的算法模式调用
#define SDR_PKOPERR   SDR_BASE+ 0x0000000B   //公钥运算失败
#define SDR_SK OPERR  SDR_BASE + 0x0000000C  //私钥运算失败
#define SDR_SIGNERR    SDR _BASE+0x0000000D   //签名运算失败
#define SDR_VERIFYERR   SDR_BASE +0x0000000E   //验证签名失败
#define SDR_SYMOPERR   SDR_BASE+ 0x0000000F   //对称算法运算失败
#define SDR_STEPERR   SDR_BASE+0x00000010  //多步运算步骤锗误
#define SDR_FILES1ZEERR   SDR_BASE+0x00000011  //文件长度超出限制
#define SDR_FILENOEXIST   SDR_BASE+0x00000012   //指定的文件不存在
#define SDR_FILEOFSERR  SDR_BASE+0x00000013  //文件起始位置错误
#define SDR_KEYTYPEERR  SDR_BASE+0x00000014  //密钥类型缙误
#define SDR_KEYERR  SDR_BASE+0x00000015  //密钥缙误
#define SDR_ENCDATAERR  SDR_BA3E+0x00000016  //ECC加密数据错误
#define SDR_RANDERR  SDR_BASE+0x00000017  //随机数产生失败
#define SDR_PRKRERR  SDR_BASE+0x00000018  //私钥使用权限获取失败
#define SDR_MACFRR  SDR_BASE+0x00000019 //MAC运算失败
#define SDR_FILEEXISTS   SDR_BASE+ 0x0000001A  //指定文件已存在
#define SDR_FILEWERR  SDR_BASE+0x0000001B  //文件写入失败
#define SDR_NORUFFER  SDR_BASE+0x0000001c  //存储空间不足
#define SDR_INARGERR  SDR_BASE+0x0000001D  //输入参数错误
#define SDR_OUTARGERR  SDR_BASE +0x0000001E  //输出参数错误

//设备管理
/*
功能:打开密码设备
参数:
phDeviceHandle[out]返回设备句柄
返回值:
0       成功
非0   失败,返回错误代码
备注:
phDeviceHandle由函数初始化并填写内容
*/
int SDF_OpenDevice(void ** phDeviceHandle);

/*
功能:关闭密码设备,并释放相关资源。
参数:
hDeviceHandle[in]   已打开的设备句柄
返回值:
0        成功
非0     失败,返回错误代码
*/
int SDF_CloseDevice( void * hDeviceHandle);

/*
功能:获取密码设备能力描述。
参数:
hSessionHandle[in]  与设备建立的会话句柄
pstDeviceInfo [out]  设备能力描述信息,内容及格式见设备信息定义
返回值:
0        成功
非0     失败,返回错误代码 
*/
int SDF_GetDeviceInfo(
void * hSessionHandle,
DEVICEINFO * pstDeviceInfo);

/*
功能:获取指定长度的随机数。
参数:hSessionHandle[in]   与设备建立的会话句柄
uilength[in]   欲获取的随机数长度
pucRandom[out]   缓冲区指针,用于存放获取的随机数
返回值:
0        成功
非0     失败,返回错误代码 
*/
int SDF_GenerateRandom (
void * hSessionHandle,unsigned int uiLength,
unsigned char * pucRandom);


#endif
写main.c,其中调用src里定义的函数
test/main.c


#include
#include
#include "sdf.h"
int main(){
   void **pdh;
   pdh=(void **)malloc(20);  //给pdh分配空间
   int ret;
   ret = SDF_OpenDevice(pdh);  //返回handle的指针

   if(ret != SDF_OK)
   {
    printf("打开设备失败\n");
   }
   else
   {
    printf("打开设备成功!\n");
  }
   printf("查看设备信息\n");
   DEVICEINFO a;
   ret = SDF_GetDeviceInfo(*pdh,&a);
   if(ret !=SDF_OK)
           printf("查看设备信息失败!\n");
   else
           printf("查看设备信息成功!\n");
   printf("设备名字叫做%s\n",a.DeviceName);
   printf("设备版本号为%d\n",a.DeviceVersion);
   printf("想要获取的随机数长度为:\n");
   int n;
   scanf("%d",&n);
   char string[100];
   ret = SDF_GenerateRandom(*pdh,n,string);
   if(ret !=SDF_OK)
    printf("生成随机数失败!");
    else
     printf("生成的随机数为%s\n",string);
   ret = SDF_CloseDevice(*pdh);
   if(ret != SDF_OK)
   {
    printf("关闭不成功!\n");
   }
   else
   {
    printf("关闭成功!\n");
   }
}


sdf.c实现函数
src/sdf.c


#include
# include 
#include
#include "sdf.h"
#include
#include 
int SDF_OpenDevice( void ** phDeviceHandle)
{
 return SDF_OK;
}
int SDF_CloseDevice( void * hDeviceHandle)
{
 return SDF_OK;
}
int SDF_GetDeviceInfo(void * hSessionHandle,DEVICEINFO * pstDeviceInfo)
{
 DEVICEINFO di;
 strcpy(di.IssuerName,"lzySDF");
 strcpy(di.DeviceName,"SDFlzy20181309");
 strcpy(di.DeviceSerial,"20210425");
 di.DeviceVersion=1;
 (*pstDeviceInfo)= di; 
 
 return SDF_OK;
}
int SDF_GenerateRandom (void * hSessionHandle,unsigned int uiLength,unsigned char * pucRandom)
{
 BIGNUM *bn;
        
        int i;
        bn = BN_new(); //生成一个BIGNUM结构
        //int bits = 20;
        int top = -1;
        int bottom = 1;
        BN_rand(bn, uiLength, top, bottom); //生成指定bits的随机数
        char *a = BN_bn2hex(bn); //转化成16进制字符串
        puts(a);
        printf("\n");
        for(i=0;*(a+i)!='\0';i++)
        {
            *(pucRandom+i)=*(a+i);
        }
        *(pucRandom+i)='\0';
        BN_free(bn); //释放BIGNUM结构
        return SDF_OK;
}

编译指令如下

gcc test/main.c src/sdf.c -o bin/test -Iinclude -lpthread -lcrypto

posted @ 2022-04-21 17:43  李业达  阅读(147)  评论(0编辑  收藏  举报