课上测试:商用密码接口实现

发布于:2024-12-19 ⋅ 阅读:(16) ⋅ 点赞:(0)

完成下面任务(29分)

1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)

2 参考GM/T0018 2023和实验代码,说明SDF接口调用的一般过程是什么(5分)

  1. 打开设备
    首先,需要打开密码设备,获取设备句柄。这一步是所有后续操作的基础。
  2. 创建会话
    打开设备后,需要创建一个与设备的会话,获取会话句柄。
  3. 执行具体操作
    根据具体需求,调用相应的SDF函数执行操作。比如:
    获取设备信息
    获取密码设备的能力描述信息。
LONG SDF_GetDeviceInfo(HANDLE hSessionHandle, DEVICEINFO *pstDeviceInfo);

产生随机数
生成随机数。

LONG SDF_GenerateRandom(HANDLE hSessionHandle, BYTE *pucRandom, ULONG uiRandomLength);

计算IPSEC会话密钥
使用IKE二阶段(快速模式)交换得到的密钥计算参数,计算IPSEC会话密钥。

  1. 关闭会话
    完成所有操作后,关闭会话,释放相关资源。

3 参考课程代码sdfproject,使用gmssl定义一个私有函数 static int getRandom(char *r, int length), 获取length个字节的随机数(7‘)

#include <stdio.h>
#include <string.h>
#include <openssl/rand.h>  // 引入 OpenSSL 的随机数生成函数
 
// 定义私有函数
static int getRandom(char *r, int length) {
    // 检查输入参数
    if (r == NULL || length <= 0) {
        return -1;  // 参数无效 
    }
 
    // 调用 OpenSSL 的 RAND_bytes 函数生成随机数
    if (RAND_bytes((unsigned char *)r, length) != 1) {
        return -2;  // 生成随机数失败
    }
 
    return 0;  // 成功
}
 
int main() {
    char randomData[32];
    int length = sizeof(randomData);
 
    // 调用私有函数获取随机数
    if (getRandom(randomData, length) == 0) {
        // 打印生成的随机数 
        printf("生成的随机数: ");
        for (int i = 0; i < length; i++) {
            printf("%02X", (unsigned char)randomData[i]);
        }
        printf("\n");
    } else {
        printf("生成随机数失败\n");
    }
 
    return 0;
}
root@LAPTOP-PRC71A0C:~# vim getRandomExample.c
root@LAPTOP-PRC71A0C:~# gcc -o getRandomExample getRandomExample.c -lssl -lcrypto
root@LAPTOP-PRC71A0C:~# ./getRandomExample
生成的随机数: FF71C2ADC8E01029570A9830BAE774A0AC6ED950F75E75EEBE2F474DBC0ADC8E

4 把上述函数集成到src中的sdf.c中的SDF_GenerateRandom中,实现相关代码(10’)

// 定义私有函数
static int getRandom(char *r, int length) {
    // 检查输入参数
    if (r == NULL || length <= 0) {
        return -1;  // 参数无效 
    }
 
    // 调用 OpenSSL 的 RAND_bytes 函数生成随机数
    if (RAND_bytes((unsigned char *)r, length) != 1) {
        return -2;  // 生成随机数失败
    }
 
    return 0;  // 成功
}

将此函数集成到sdf.c中的SDF_GenerateRandom中
以下是集成后的sdf.c

#include "sdf.h"
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <openssl/rand.h>  // 引入 OpenSSL 的随机数生成函数
 
//********************************
//设备管理
//********************************
 
int SDF_OpenDevice(void ** phDeviceHandle) {
    return SDR_OK;
}
 
int SDF_CloseDevice(void *hDeviceHandle) {
    return SDR_OK;
}
 
int SDF_GetDeviceInfo(void * hSessionHandle, DEVICEINFO * pstDeviceInfo) {
    DEVICEINFO di;
    strcpy(di.IssuerName, "RocSDF");
    strcpy(di.DeviceName, "SDFBESTI181x");
    strcpy(di.DeviceSerial, "2021040001");
    di.DeviceVersion = 1;
    //...
 
    *pstDeviceInfo = di;
 
    return SDR_OK;
}
 
// 定义私有函数
static int getRandom(char *r, int length) {
    // 检查输入参数
    if (r == NULL || length <= 0) {
        return -1;  // 参数无效
    }
 
    // 调用 OpenSSL 的 RAND_bytes 函数生成随机数 
    if (RAND_bytes((unsigned char *)r, length) != 1) {
        return -2;  // 生成随机数失败
    }
 
    return 0;  // 成功
}
 
int SDF_GenerateRandom(void * hSessionHandle, unsigned int uiLength, unsigned char * pucRandom) {
    // 检查输入参数
    if (hSessionHandle == NULL || pucRandom == NULL || uiLength <= 0) {
        return SDR_ERR_INVALID_PARAM;  // 参数无效
    }
 
    // 调用私有函数生成随机数 
    if (getRandom((char *)pucRandom, uiLength) != 0) {
        return SDR_ERR_RANDOM_GENERATION_FAILED;  // 生成随机数失败
    }
 
    return SDR_OK;  // 成功
}

5 在test中的main.c调用SDF_GenerateRandom进行测试,至少测试1个字节,5个字节,20个字节三种情况。(4‘)

#include <stdio.h>
#include <stdlib.h>
#include "sdf.h"
 
int main() {
    void *hDeviceHandle;
    void *hSessionHandle;
    DEVICEINFO stDeviceInfo;
    int ret;
 
    // 打开设备
    ret = SDF_OpenDevice(&hDeviceHandle);
    if (ret != SDR_OK) {
        printf("打开设备失败\n");
        return -1;
    } else {
        printf("设备打开成功!\n");
    }
 
    // 创建会话
    ret = SDF_OpenSession(hDeviceHandle, &hSessionHandle);
    if (ret != SDR_OK) {
        printf("创建会话失败\n");
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
 
    // 获取设备信息
    ret = SDF_GetDeviceInfo(hSessionHandle, &stDeviceInfo);
    if (ret != SDR_OK) {
        printf("获取设备信息失败\n");
        SDF_CloseSession(hSessionHandle);
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    } else {
        printf("Issuer Name: %s\n", stDeviceInfo.IssuerName);
        printf("Device Name: %s\n", stDeviceInfo.DeviceName);
        printf("Device Serial: %s\n", stDeviceInfo.DeviceSerial);
        printf("Device Version: %d\n", stDeviceInfo.DeviceVersion);
    }
 
    // 测试生成 1 个字节的随机数
    char pRandom1[1];
    ret = SDF_GenerateRandom(hSessionHandle, 1, pRandom1);
    if (ret != SDR_OK) {
        printf("生成 1 个字节的随机数失败\n");
    } else {
        printf("生成的 1 个字节随机数: %02X\n", pRandom1[0]);
    }
 
    // 测试生成 5 个字节的随机数
    char pRandom5[5];
    ret = SDF_GenerateRandom(hSessionHandle, 5, pRandom5);
    if (ret != SDR_OK) {
        printf("生成 5 个字节的随机数失败\n");
    } else {
        printf("生成的 5 个字节随机数: ");
        for (int i = 0; i < 5; i++) {
            printf("%02X ", pRandom5[i]);
        }
        printf("\n");
    }
 
    // 测试生成 20 个字节的随机数
    char pRandom20[20];
    ret = SDF_GenerateRandom(hSessionHandle, 20, pRandom20);
    if (ret != SDR_OK) {
        printf("生成 20 个字节的随机数失败\n");
    } else {
        printf("生成的 20 个字节随机数: ");
        for (int i = 0; i < 20; i++) {
            printf("%02X ", pRandom20[i]);
        }
        printf("\n");
    }
 
    // 关闭会话
    ret = SDF_CloseSession(hSessionHandle);
    if (ret != SDR_OK) {
        printf("关闭会话失败\n");
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
 
    // 关闭设备
    ret = SDF_CloseDevice(hDeviceHandle);
    if (ret != SDR_OK) {
        printf("关闭设备失败\n");
        return -1;
    }
 
    printf("操作成功\n");
    return 0;
}

经过发现,刚才课程提供的sdf.c和sdf.h中没有建立会话的函数示例
因此,修改sdf.c与sdf.h文件(所以课程提供源代码示例时一定要注意尽量别提供错误代码,以正严谨)
sdf.c

#include <stdio.h>
#include "sdf.h"
 
int main() {
    HANDLE hDeviceHandle;
    HANDLE hSessionHandle;
    BYTE pucRandom[20];
    ULONG uiRandomLength;
 
    // 打开设备
    if (SDF_OpenDevice(&hDeviceHandle) != 0) {
        printf("打开设备失败\n");
        return -1;
    }
 
    // 创建会话
    if (SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) {
        printf("创建会话失败\n");
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
 
    // 测试生成 1 个字节的随机数 
    uiRandomLength = 1;
    if (SDF_GenerateRandom(hSessionHandle, pucRandom, uiRandomLength) != 0) {
        printf("生成 1 个字节的随机数失败\n");
        SDF_CloseSession(hSessionHandle);
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
    printf("生成 1 个字节的随机数: ");
    for (ULONG i = 0; i < uiRandomLength; i++) {
        printf("%02X", pucRandom[i]);
    }
    printf("\n");
 
    // 测试生成 5 个字节的随机数
    uiRandomLength = 5;
    if (SDF_GenerateRandom(hSessionHandle, pucRandom, uiRandomLength) != 0) {
        printf("生成 5 个字节的随机数失败\n");
        SDF_CloseSession(hSessionHandle);
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
    printf("生成 5 个字节的随机数: ");
    for (ULONG i = 0; i < uiRandomLength; i++) {
        printf("%02X", pucRandom[i]);
    }
    printf("\n");
 
    // 测试生成 20 个字节的随机数
    uiRandomLength = 20;
    if (SDF_GenerateRandom(hSessionHandle, pucRandom, uiRandomLength) != 0) {
        printf("生成 20 个字节的随机数失败\n");
        SDF_CloseSession(hSessionHandle);
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
    printf("生成 20 个字节的随机数: ");
    for (ULONG i = 0; i < uiRandomLength; i++) {
        printf("%02X", pucRandom[i]);
    }
    printf("\n");
 
    // 关闭会话
    if (SDF_CloseSession(hSessionHandle) != 0) {
        printf("关闭会话失败\n");
        SDF_CloseDevice(hDeviceHandle);
        return -1;
    }
 
    // 关闭设备
    if (SDF_CloseDevice(hDeviceHandle) != 0) {
        printf("关闭设备失败\n");
        return -1;
    }
 
    printf("操作成功\n");
    return 0;
}

main.c

#include "sdf.h"
#include <stdlib.h>
#include <string.h>
 
// 模拟设备句柄和会话句柄
static HANDLE g_hDeviceHandle = 0;
static HANDLE g_hSessionHandle = 0;
 
// 模拟随机数生成
void generate_random(BYTE *pucRandom, ULONG uiRandomLength) {
    for (ULONG i = 0; i < uiRandomLength; ++i) {
        pucRandom[i] = rand() % 256;
    }
}
 
LONG SDF_OpenDevice(HANDLE *phDeviceHandle) {
    *phDeviceHandle = ++g_hDeviceHandle;
    return 0;
}
 
LONG SDF_OpenSession(HANDLE hDeviceHandle, HANDLE *phSessionHandle) {
    if (hDeviceHandle != g_hDeviceHandle) {
        return -1; // 无效的设备句柄
    }
    *phSessionHandle = ++g_hSessionHandle;
    return 0;
}
 
LONG SDF_GenerateRandom(HANDLE hSessionHandle, BYTE *pucRandom, ULONG uiRandomLength) {
    if (hSessionHandle != g_hSessionHandle) {
        return -1; // 无效的会话句柄
    }
    generate_random(pucRandom, uiRandomLength);
    return 0;
}
 
LONG SDF_CloseSession(HANDLE hSessionHandle) {
    if (hSessionHandle != g_hSessionHandle) {
        return -1; // 无效的会话句柄
    }
    g_hSessionHandle = 0;
    return 0;
}
 
LONG SDF_CloseDevice(HANDLE hDeviceHandle) {
    if (hDeviceHandle != g_hDeviceHandle) {
        return -1; // 无效的设备句柄
    }
    g_hDeviceHandle = 0;
    return 0;
}
root@LAPTOP-PRC71A0C:~/sdfpro# vim sdf.h
root@LAPTOP-PRC71A0C:~/sdfpro# vim sdf.c
root@LAPTOP-PRC71A0C:~/sdfpro# vim main.c
root@LAPTOP-PRC71A0C:~/sdfpro# gcc -o sdfExample main.c sdf.c
root@LAPTOP-PRC71A0C:~/sdfpro# ./sdfExample
生成 1 个字节的随机数: 67
生成 5 个字节的随机数: C6697351FF
生成 20 个字节的随机数: 4AEC29CDBAABF2FBE3467CC254F81BE8E78D765A
操作成功

6 提交git log结果(3分)

root@LAPTOP-PRC71A0C:~/sdfpro# git add .
root@LAPTOP-PRC71A0C:~/sdfpro# git commit -m "商用密码接口实现-5测试随机数生成"
[master (root-commit) 2b65d33] 商用密码接口实现-5测试随机数生成
 4 files changed, 155 insertions(+)
 create mode 100644 main.c
 create mode 100644 sdf.c
 create mode 100644 sdf.h
 create mode 100755 sdfExample
root@LAPTOP-PRC71A0C:~/sdfpro# git log
commit 2b65d33bb114fa8203b505723579778a9953501a (HEAD -> master)
Author: 魏正一 <11565599+wei-zhengyi@user.noreply.gitee.com>
Date:   Tue Dec 17 12:39:33 2024 +0800

    商用密码接口实现-5测试随机数生成

提交要求 (1’)

1 记录实践过程和 AI 问答过程,尽量不要截图,给出文本内容
2 (选做)推荐所有作业托管到 gitee或 github 上
3 (必做)提交作业 markdown文档,命名为“学号-姓名-作业题目.md”
4 (必做)提交作业 markdown文档