Bootstrap

20221403郑骁恒实验3-2

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;
}

;