openEuler下进行OpenSSL测试
一、SM3
1.实验内容
- 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务
- 使用OpenSSL的命令计算你的8位学号的摘要值(SM3),提交截图
- 使用OpenSSL编程对计算"你的8位学号"SM3摘要值,提交代码和运行结果截图。
- 使用OpenSSL编程对计算内容为"所有同学的8位学号"的文件的SM3摘要值,提交代码和运行结果截图
2.实验过程
(1)使用OpenSSL的命令计算你的8位学号的摘要值(SM3)
(2)ope使用OpenSSL编程对计算"你的8位学号"SM3摘要值
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
void tDigest(){
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
EVP_MD_CTX *mdctx;
mdctx = EVP_MD_CTX_new();
char msg1[] = "20201220";
char msg2[] = "I am Cai Dujun!";
EVP_MD_CTX_init(mdctx);
EVP_DigestInit_ex(mdctx, EVP_sm3(), NULL);
EVP_DigestUpdate(mdctx, msg1, strlen(msg1));
EVP_DigestUpdate(mdctx, msg2, strlen(msg2));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
printf("Debug:Message1\n%s \nand Message2\n%s \ndigest to:\n",msg1, msg2);
for(int i = 0; i<md_len; i++){
printf("0x%02x ", md_value[i]);
}
printf("\n");
}
int main(){
OpenSSL_add_all_algorithms();
tDigest();
return 0;
}
(3)使用OpenSSL编程对计算内容为"所有同学的8位学号"的文件的SM3摘要值
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
void tDigest()
{
unsigned char sm3_value[EVP_MAX_MD_SIZE];
int sm3_len, i;
EVP_MD_CTX *sm3ctx;
sm3ctx = EVP_MD_CTX_new();
char msg1[10000] = "";
FILE *file;
char line[32];
char *ret;
file = fopen("all.txt", "r");
if (!file) {
printf("文件打开失败!\n");
exit(0);
}
while (ret = fgets(line, sizeof(line), file)) {
strcat(msg1,line);
} printf("all.txt中的内容为\n%s\n",msg1);
fclose(file);
EVP_MD_CTX_init(sm3ctx);
EVP_DigestInit_ex(sm3ctx, EVP_sm3(), NULL);
EVP_DigestUpdate(sm3ctx, msg1, strlen(msg1));
EVP_DigestFinal_ex(sm3ctx, sm3_value, &sm3_len);
EVP_MD_CTX_reset(sm3ctx);
printf("all.txt的摘要值为:\n");
for(i = 0; i < sm3_len; i++)
{
printf("0x%02x ", sm3_value[i]);
}
printf("\n");
}
int main()
{
OpenSSL_add_all_algorithms();
tDigest();
return 0;
}
二、随机数
1.实验内容
- 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务
- 使用OpenSSL定义一个私有函数 static int getRandom(char *r, int length), 获取length个字节的随机数
- 把上述函数集成到src中的sdf.c中的SDF_GenerateRandom中
- 在test中的main.c调用SDF_GenerateRandom进行测试,至少测试1个字节,5个字节,20个字节三种情况。
2.实验过程
(1)使用OpenSSL定义一个私有函数 static int getRandom(char *r, int length), 获取length个字节的随机数
利用OpenSSL中的bn_rand()函数获取伪随机数
(2)把上述函数集成到src中的sdf.c中的SDF_GenerateRandom中
集成如下
main.c传参n至sdf.c的SDF_GenerateRandom中
(3)在test中的main.c调用SDF_GenerateRandom进行测试,至少测试1个字节,5个字节,20个字节三种情况
源代码如下:
sdf.h:
#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:
#include <stdio.h>
#include <stdlib.h>
#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:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdf.h"
#include <time.h>
#include <openssl/bn.h>
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, "CDJSDF");//tzjSDF
strcpy(di.DeviceName, "SDF-20201220CDJ");
strcpy(di.DeviceSerial, "20210425");
di.DeviceVersion = 20201220;
(*pstDeviceInfo) = di;
return SDF_OK;
}
int SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, unsigned char *pucRandom)
{
BIGNUM *bn;
int i;
bn = BN_new();
int top = -1;
int bottom = 1;
BN_rand(bn, uiLength, top, bottom);
char *a = BN_bn2hex(bn);
puts(a);
printf("\n");
for (i = 0; *(a + i) != '\0'; i++)
{
*(pucRandom + i) = *(a + i);
}
*(pucRandom + i) = '\0';
BN_free(bn);
return SDF_OK;
}
三、大数
1.实验内容
- 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务
- 基于OpenSSL的大数库计算2的N次方,N为你学号的后四位(5‘)
- 基于OpenSSL的大数库计算你以及前面5位同学和后面5位同学的8位学号的乘积,N为你学号的后四位(5‘)
- 用Python或bc命令验证计算的正确性(5’)
2.实验过程
(1)基于OpenSSL的大数库计算2的N次方,N为你学号的后四位
1220的16进制是4C4:
编译运行,用bc验证,才发现openeuler没装bc,装bc的同时顺便装一些其他的东西
bc验证
结果一致。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bn.h>
// 20201220
int main()
{
BN_CTX *r[3];
BIGNUM *a;
BIGNUM *b;
BIGNUM *c;
char s[512 + 1] = "2";
char t[512 + 1] = "4c4";
char *x;
r[0] = BN_CTX_new();
a = BN_new();
b = BN_new();
c = BN_new();
BN_hex2bn(&a, s);
BN_hex2bn(&b, t);
BN_exp(c, a, b, r[0]); // r=pow(a,b)
x = BN_bn2dec(c);
puts(x);
BN_free(a);
BN_free(b);
BN_free(c);
BN_CTX_free(r[0]);
free(x);
return 0;
}
(2)基于OpenSSL的大数库计算你以及前面5位同学和后面5位同学的8位学号的乘积,N为你学号的后四位
计算并利用bc验证:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bn.h>
//20201220
int main()
{
BN_CTX *r[11];
BIGNUM *bn[12];
int i;
const char s[11][9] = {"20201215", "20201216", "20201217", "20201218", "20201219", "20201220", "20201221", "20201222", "20201223", "20201224", "20201225"};
char *out;
char t[2] = "1";
for (i = 0; i < 11; i++)
{
bn[i] = BN_new();
BN_dec2bn(&bn[i], s[i]);
r[i] = BN_CTX_new();
}
bn[11] = BN_new();
BN_dec2bn(&bn[11], t);
for (i = 0; i < 11; i++)
{
BN_mul(bn[11], bn[11], bn[i], r[i]);
}
out = BN_bn2dec(bn[11]);
puts(out); //打印出字符串
for (i = 0; i < 11; i++)
{
BN_free(bn[i]);
BN_CTX_free(r[i]);
}
BN_free(bn[i]);
free(out);
return 0;
}
(3)用Python或bc命令验证计算的正确性
前面已经用bc验证过了,这里用py验证一下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本