文章目录
- 完成下面任务(29分)
-
-
- 1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
- 2 参考GM/T0018 2023和实验代码,说明SDF接口调用的一般过程是什么(5分)
- 3 参考课程代码sdfproject,使用gmssl定义一个私有函数 static int getRandom(char *r, int length), 获取length个字节的随机数(7‘)
- 4 把上述函数集成到src中的sdf.c中的SDF_GenerateRandom中,实现相关代码(10')
- 5 在test中的main.c调用SDF_GenerateRandom进行测试,至少测试1个字节,5个字节,20个字节三种情况。(4‘)
- 6 提交git log结果(3分)
- 提交要求 (1')
-
完成下面任务(29分)
1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
2 参考GM/T0018 2023和实验代码,说明SDF接口调用的一般过程是什么(5分)
- 打开设备
首先,需要打开密码设备,获取设备句柄。这一步是所有后续操作的基础。 - 创建会话
打开设备后,需要创建一个与设备的会话,获取会话句柄。 - 执行具体操作
根据具体需求,调用相应的SDF函数执行操作。比如:
获取设备信息
获取密码设备的能力描述信息。
LONG SDF_GetDeviceInfo(HANDLE hSessionHandle, DEVICEINFO *pstDeviceInfo);
产生随机数
生成随机数。
LONG SDF_GenerateRandom(HANDLE hSessionHandle, BYTE *pucRandom, ULONG uiRandomLength);
计算IPSEC会话密钥
使用IKE二阶段(快速模式)交换得到的密钥计算参数,计算IPSEC会话密钥。
- 关闭会话
完成所有操作后,关闭会话,释放相关资源。
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文档