1.完成gmt0018中,对称加密解密,非对称加密解密,签名验签,hash运算,MAC运算接口中的至少一类(至少5选1)
我选择了hash运算和MAC运算的接口实现,同时也带有设备的打开和关闭的接口实现。
- 以下是接口代码及注释的实现:
/*
功能:打开密码设备
参数:phDeviceHandle[out] 返回设备句柄
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_OpenDevice(void ** phDeviceHandle);
/*
功能:关闭密码设备,并释放相关资源
参数:hDeviceHandle[in] 已打开的设备句柄
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_CloseDevice(void * hDeviceHandle);
/*
功能:使用指定的密钥句柄和IV对数据进行MAC运算
参数:hSessionHandle[in] 与设备建立的会话句柄
hKeyHandle[in] 指定的密钥句柄
uiAlgID[in] 算法标识,指定对称加密算法
pucIV[in|out] 缓冲区指针,用于存放输入和返回的IV数据
pucData[in] 缓冲区指针,用于存放输出的数据明文
uiDataLength[in] 输入的数据明文长度
pucMAC[out] 缓冲区指针,用于存放输出的MAC值
puiMACLength[out] 输出的MAC值长度
返回值:0 成功
非0 失败,返回错误代码
备注:此函数不对数据进行分包处理,多包数据MAC运算由IV控制最后的MAC值
*/
int SDF_CalculateMAC(void * hSessionHandle,void * hKeyHandle, unsigned int uiAlgID, unsigned char * pucIV, unsigned char * pucData, unsigned int uiDataLength ,unsigned char * pucMAC, unsigned int * puiMACLength);
/*
功能:三步式数据杂凑运算第一步,杂凑运算初始化
参数:hSessionHandle[in] 与设备建立的会话句柄
uiAlgID[in] 指定杂凑算法标识
pucPublicKey[in] 签名者公钥。当uiAlgID为SGD_SM3时有效。
pucID[in] 签名者的ID值,当uiAlgID为SGD_SM3时有效。
uiIDLength[in] 签名者ID的长度,当uiAlgID为SGD.SM3时有效。
返回值:0 成功
非0 失败,返回错误代码
备注:uiIDLength非零且uiAlgID为SGD_SM3时,函数执行SM2的预处理1操作。计算过程见GM/T 0009。
*/
int SDF_HashInit(void * hSessionHandle, unsigned int uiAlgID,ECCrefPublicKey * pucPublicKey,unsigned char * pucID, unsigned int uiIDLength);
/*
功能:三步式数据杂凑运算第二步,对输入的明文进行杂凑运算
参数:hSessionHandle[in] 与设备建立的会话句柄
pucData[in] 缓冲区指针,用于存放输入的数据明文
uiDataLength[in] 输入的数据明文长度
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_HashUpdate(void * hSessionHandle,unsigned char * pucData,unsigned int uiDataLength);
/*
功能:三步式数据杂凑运算第三步,杂凑运算结束返回杂凑数据并清除中间数据
参数:hSessionHandle[in] 与设备建立的会话句柄
pucHash[out] 缓冲区指针,用于存放输出的杂凑数据
puiHashLength[out] 返回的杂凑数据长度
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_HashFinal (void * hSessionHandle,unsigned char * pucHash,unsigned int * puiHashLength);
2.接口放入sdfh,实现内容实现sdf.c,testsdf.c
实现过程:
我实现了对我的学号姓名(20221403zxh)的杂凑运算和MAC运算,以及设备的打开和关闭
zxh@zxh-VirtualBox:~/zxh/3-2/include$ touch sdf.h
zxh@zxh-VirtualBox:~/zxh/3-2/include$ vim sdf.h
zxh@zxh-VirtualBox:~/zxh/3-2/src$ touch sdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ vim sdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ touch testsdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ vim testsdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ ls
sdf.c testsdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ gcc -I/home/zxh/zxh/3-2/include testsdf.c sdf.c -o testsdf -lcrypto
zxh@zxh-VirtualBox:~/zxh/3-2/src$ ls
sdf.c testsdf testsdf.c
zxh@zxh-VirtualBox:~/zxh/3-2/src$ ./testsdf
设备打开成功。
杂凑完成成功,杂凑值: 1A591EE60F23EA647E07B6D31CB8BF8A9D5EC56446396425FAC649F7A7019A90
MAC计算成功,MAC值: 7A000C390DAB84548DF217C7CDA47BF69C46553EF710C5424B9DBFD9863204A4
设备关闭成功。
以下是各文件的源代码:
sdf.h
#ifndef __SDF_H
#define __SDF_H
#include <stdint.h> // 包含标准整数类型定义
// 定义 ULONG 和 BYTE
typedef uint32_t ULONG;
typedef uint8_t BYTE;
typedef void* HANDLE; // 定义 HANDLE 为 void*
// 定义设备信息结构
typedef struct DeviceInfo_st
{
unsigned int HashAlgAbility; // 所有支持的杂凑算法,表示方法为杂凑算法标识按位或运算结果
unsigned int BufferSize; // 支持的最大文件存储空间(单位字节)
} DEVICEINFO;
// Error Code
#define SDR_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_KEYNOTEXIST SDR_BASE + 0x00000008 // 不存在的密钥调用
#define SDR_ALGNOTSUPPORT SDR_BASE + 0x00000009 // 不支持的算法调用
#define SDR_ALGMODNOTSUPPORT SDR_BASE + 0x0000000A // 不支持的算法模式调用
#define SDR_FILESIZEERR SDR_BASE + 0x00000011 // 文件长度超出限制
#define SDR_FILENOEXIST SDR_BASE + 0x00000012 // 指定的文件不存在
#define SDR_FILEOFSERR SDR_BASE + 0x00000013 // 文件起始位置错误
#define SDR_MACERR SDR_BASE + 0x00000019 // MAC运算失败
#define SDR_FILEEXISTS SDR_BASE + 0x0000001A // 指定文件已存在
#define SDR_FILEWERR SDR_BASE + 0x0000001B // 文件写入失败
#define SDR_NOBUFFER SDR_BASE + 0x0000001C // 存储空间不足
#define SDR_INARGERR SDR_BASE + 0x0000001D // 输入参数错误
#define SDR_OUTARGERR SDR_BASE + 0x0000001E // 输出参数错误
#define SGD_SM3 0x00000001
// 函数声明
//SDR_BASE + 0x0000001F至SDR_BASE + 0x00FFFFFF 预留
/*
功能:打开密码设备
参数:phDeviceHandle[out] 返回设备句柄
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_OpenDevice(void ** phDeviceHandle);
/*
功能:关闭密码设备,并释放相关资源
参数:hDeviceHandle[in] 已打开的设备句柄
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_CloseDevice(void * hDeviceHandle);
/*
功能:使用指定的密钥句柄和IV对数据进行MAC运算
参数:hSessionHandle[in] 与设备建立的会话句柄
hKeyHandle[in] 指定的密钥句柄
uiAlgID[in] 算法标识,指定对称加密算法
pucIV[in|out] 缓冲区指针,用于存放输入和返回的IV数据
pucData[in] 缓冲区指针,用于存放输出的数据明文
uiDataLength[in] 输入的数据明文长度
pucMAC[out] 缓冲区指针,用于存放输出的MAC值
puiMACLength[out] 输出的MAC值长度
返回值:0 成功
非0 失败,返回错误代码
备注:此函数不对数据进行分包处理,多包数据MAC运算由IV控制最后的MAC值
*/
int SDF_CalculateMAC(void * hSessionHandle,void * hKeyHandle, unsigned int uiAlgID, unsigned char * pucIV, unsigned char * pucData, unsigned int uiDataLength ,unsigned char * pucMAC, unsigned int * puiMACLength);
/*
功能:三步式数据杂凑运算第一步,杂凑运算初始化
参数:hSessionHandle[in] 与设备建立的会话句柄
uiAlgID[in] 指定杂凑算法标识
pucPublicKey[in] 签名者公钥。当uiAlgID为SGD_SM3时有效。
pucID[in] 签名者的ID值,当uiAlgID为SGD_SM3时有效。
uiIDLength[in] 签名者ID的长度,当uiAlgID为SGD.SM3时有效。
返回值:0 成功
非0 失败,返回错误代码
备注:uiIDLength非零且uiAlgID为SGD_SM3时,函数执行SM2的预处理1操作。计算过程见GM/T 0009。
*/
int SDF_HashInit(void * hSessionHandle, unsigned int uiAlgID,ECCrefPublicKey * pucPublicKey,unsigned char * pucID, unsigned int uiIDLength);
/*
功能:三步式数据杂凑运算第二步,对输入的明文进行杂凑运算
参数:hSessionHandle[in] 与设备建立的会话句柄
pucData[in] 缓冲区指针,用于存放输入的数据明文
uiDataLength[in] 输入的数据明文长度
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_HashUpdate(void * hSessionHandle,unsigned char * pucData,unsigned int uiDataLength);
/*
功能:三步式数据杂凑运算第三步,杂凑运算结束返回杂凑数据并清除中间数据
参数:hSessionHandle[in] 与设备建立的会话句柄
pucHash[out] 缓冲区指针,用于存放输出的杂凑数据
puiHashLength[out] 返回的杂凑数据长度
返回值:0 成功
非0 失败,返回错误代码
*/
int SDF_HashFinal (void * hSessionHandle,unsigned char * pucHash,unsigned int * puiHashLength);
#endif // __SDF_H
sdf.c
#include "sdf.h"
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
EVP_MD_CTX *evp_md_ctx;
} SessionHandle;
int SDF_HashInit(void * hSessionHandle, unsigned int uiAlgID, ECCrefPublicKey * pucPublicKey, unsigned char * pucID, unsigned int uiIDLength) {
SessionHandle *session = (SessionHandle *)hSessionHandle;
if (uiAlgID == SGD_SM3) {
session->evp_md_ctx = EVP_MD_CTX_new();
if (session->evp_md_ctx == NULL) {
return SDR_HARDFAIL; // 内存分配失败
}
if (EVP_DigestInit_ex(session->evp_md_ctx, EVP_sha256(), NULL) != 1) {
EVP_MD_CTX_free(session->evp_md_ctx);
session->evp_md_ctx = NULL;
return SDR_ALGNOTSUPPORT; // 初始化失败
}
return SDR_OK;
}
return SDR_ALGNOTSUPPORT; // 不支持的算法
}
int SDF_HashUpdate(void * hSessionHandle, unsigned char * pucData, unsigned int uiDataLength) {
SessionHandle *session = (SessionHandle *)hSessionHandle;
if (EVP_DigestUpdate(session->evp_md_ctx, pucData, uiDataLength) != 1) {
return SDR_HARDFAIL; // 更新失败
}
return SDR_OK;
}
int SDF_HashFinal(void * hSessionHandle, unsigned char * pucHash, unsigned int * puiHashLength) {
SessionHandle *session = (SessionHandle *)hSessionHandle;
if (EVP_DigestFinal_ex(session->evp_md_ctx, pucHash, puiHashLength) != 1) {
return SDR_HARDFAIL; // 最终化失败
}
EVP_MD_CTX_free(session->evp_md_ctx);
session->evp_md_ctx = NULL;
return SDR_OK;
}
int SDF_CalculateMAC(void * hSessionHandle, void * hKeyHandle, unsigned int uiAlgID, unsigned char * pucIV, unsigned char * pucData, unsigned int uiDataLength, unsigned char * pucMAC, unsigned int * puiMACLength) {
// 使用HMAC-SHA256计算MAC
if (uiAlgID == SGD_SM3) {
// 假设hKeyHandle是密钥,这里直接使用pucIV作为密钥
if (HMAC(EVP_sha256(), pucIV, pucIV ? strlen((char *)pucIV) : 0, pucData, uiDataLength, pucMAC, puiMACLength) == NULL) {
return SDR_MACERR; // MAC计算失败
}
return SDR_OK;
}
return SDR_ALGNOTSUPPORT; // 不支持的算法
}
int SDF_OpenDevice(HANDLE* deviceHandle) {
// 打开设备的实际逻辑
*deviceHandle = malloc(sizeof(SessionHandle)); // 分配会话句柄
if (*deviceHandle == NULL) {
return SDR_OPENDEVICE; // 打开设备失败
}
memset(*deviceHandle, 0, sizeof(SessionHandle)); // 初始化会话句柄
return SDR_OK;
}
int SDF_CloseDevice(HANDLE deviceHandle) {
// 关闭设备的实际逻辑
if (deviceHandle != NULL) {
free(deviceHandle); // 释放会话句柄
}
return SDR_OK;
}
testsdf.c
#include <stdio.h>
#include "sdf.h"
// 假设 SGD_SM3 是一个有效的算法标识符
#define SGD_SM3 0x00000001 // 请根据实际情况定义
int main() {
HANDLE deviceHandle;
ULONG openResult, closeResult;
// 打开设备
openResult = SDF_OpenDevice(&deviceHandle);
if (openResult == SDR_OK) {
printf("设备打开成功。\n");
// 进行一些操作,例如杂凑运算和MAC计算
unsigned char data[] = "20221403zxh";
unsigned int dataLength = sizeof(data);
unsigned char hash[32];
unsigned int hashLength;
unsigned char mac[32];
unsigned int macLength = sizeof(mac);
// 杂凑运算
int hashResult = SDF_HashInit(deviceHandle, SGD_SM3, NULL, NULL, 0);
if (hashResult != SDR_OK) {
printf("杂凑初始化失败,错误代码: %d\n", hashResult);
} else {
hashResult = SDF_HashUpdate(deviceHandle, data, dataLength);
if (hashResult != SDR_OK) {
printf("杂凑更新失败,错误代码: %d\n", hashResult);
} else {
hashResult = SDF_HashFinal(deviceHandle, hash, &hashLength);
if (hashResult != SDR_OK) {
printf("杂凑完成失败,错误代码: %d\n", hashResult);
} else {
printf("杂凑完成成功,杂凑值: ");
for (unsigned int i = 0; i < hashLength; i++) {
printf("%02X", hash[i]);
}
printf("\n");
}
}
}
// MAC计算
int macResult = SDF_CalculateMAC(deviceHandle, NULL, SGD_SM3, NULL, data, dataLength, mac, &macLength);
if (macResult != SDR_OK) {
printf("MAC计算失败,错误代码: %d\n", macResult);
} else {
printf("MAC计算成功,MAC值: ");
for (unsigned int i = 0; i < macLength; i++) {
printf("%02X", mac[i]);
}
printf("\n");
}
}
else {
printf("设备打开失败,错误代码: %d\n", openResult);
}
// 关闭设备
closeResult = SDF_CloseDevice(deviceHandle);
if (closeResult == SDR_OK) {
printf("设备关闭成功。\n");
} else {
printf("设备关闭失败,错误代码: %d\n", closeResult);
}
return 0;
}
3.参考云班课实验资源中的 sdfproject 代码或者 git pull 课程代码 ch06中的 sdfproject
实现过程
zxh@zxh-VirtualBox:~/bestidiocs2024/ch06/sdftest/src$ gcc -I/home/zxh/bestidiocs2024/ch06/sdftest/include testsdf.c sdf.c -o testsdf -lcrypto
zxh@zxh-VirtualBox:~/bestidiocs2024/ch06/sdftest/src$ ls
sdf.c testsdf testsdf.c
zxh@zxh-VirtualBox:~/bestidiocs2024/ch06/sdftest/src$ ./testsdf
设备打开成功。
设备关闭成功。
各文件源代码:
sdf.h
#ifndef __SDF_H
#define __SDF_H
//typedefine
typedef unsigned char BYTE;
typedef unsigned char CHAR;
typedef int LONG;
typedef unsigned int ULONG;
typedef unsigned int FLAGS;
typedef CHAR * LPSTR;
typedef void * HANDLE;
typedef struct DeviceInfo_st{
CHAR IssuerName[40];
CHAR DeviceName[16];
CHAR DeviceSerial[16];
ULONG DeviceVersion;
ULONG StandardVersion;
ULONG AsymAlgAbility[2];
ULONG SymAlgAbility;
ULONG HashAlgAbility;
ULONG BufferSize;
}DEVICEINFO;
#define ECCref_MAX_BITS 512
#define ECCref_MAX_LEN ((ECCref_MAX_BITS + 7) / 8)
typedef struct ECCrefPublicKey_st
{
ULONG bits;
BYTE x[ECCref_MAX_LEN];
BYTE y[ECCref_MAX_LEN];
} ECCrefPublicKey;
typedef struct ECCrefPrivateKey_st
{
ULONG bits;
BYTE K[ECCref_MAX_LEN];
} ECCrefPrivateKey;
//device management interface
// 打开密码设备。phDeviceHandle由函数初始化并填写内容。
// 参数:
// phDeviceHandle[out] 返回的设备句柄
// 返回值:
// 0 成功
// 非0 失败,返回错误代码
LONG SDF_OpenDevice(HANDLE * phDeviceHandle);
// 关闭密码设备,并释放相关资源。
// 参数:
// hDeviceHandle[in] 已打开的设备句柄
// 返回值:
// 0 成功
// 非0 失败,返回错误代码
LONG SDF_CloseDevice(HANDLE hDeviceHandle);
// 获取密码设备能力描述。
// 参数:
// hSessionHandle[in] 与设备建立的会话句柄
// pstDeviceInfo[out] 设备能力描述信息,内容及格式见设备信息定义
// 返回值:
// 0 成功
// 非0 失败,返回错误代码
LONG SDF_GetDeviceInfo(HANDLE hSessionHandle, DEVICEINFO *pstDeviceInfo);
#endif
sdf.c
#include "sdf.h"
/*int main(){
HANDLE * myDeviceHandle;
SDF_OpenDevice(myDeviceHandle);
SDF_CloseDevice(myDeviceHandle);
return 0;
}*/
LONG SDF_OpenDevice(HANDLE * phDeviceHandle){
return 0;
}
LONG SDF_CloseDevice(HANDLE hDeviceHandle){
return 0;
}
testsdf.c
#include <stdio.h>
#include "sdf.h"
int main() {
HANDLE deviceHandle;
LONG openResult, closeResult;
// 打开设备
openResult = SDF_OpenDevice(&deviceHandle);
if (openResult == 0) {
printf("设备打开成功。\n");
} else {
printf("设备打开失败,错误代码: %d\n", openResult);
}
// 关闭设备
closeResult = SDF_CloseDevice(deviceHandle);
if (closeResult == 0) {
printf("设备关闭成功。\n");
} else {
printf("设备关闭失败,错误代码: %d\n", closeResult);
}
return 0;
}