最近在用C敲代码
然后想添加OpenSSL到自己电脑中
所以找到了他们的Github,然后下master下的所有include文件
然后将其拖到我的Lab2文件夹中
之后,在方法头指定了路径,我感觉讲道理应该就可以使用了
比如,就像这样
#include <openssl/evp.h>
但是,遇到的还是各种报错,各种不行
简单来说,就是各种找不到文件
比如下面这个图这样
那可不行
所以,开始各种找办法
在 这个帖子 中,我感觉应该指定运行C的库才可以
所以,我把我的运行代码变成了
cd "/Users/halu/Desktop/Lab2/" && gcc -I/Users/halu/Desktop/Lab2/include -L/Users/halu/Desktop/Lab2/include Lab2.c -o Lab2 -lcrypto && "/Users/halu/Desktop/Lab2/"Lab2
结果一跑,还是不行
人家还是抱怨没有找到文件
并且,这玩意比较迷的一点是,从报错结果来看的话,evp.c这个文件是已经找到了的
但是,eve.c中又使用了其他文件,所以又找不到了
然后,我把目标转到了Openssl的安装上
我感觉,可能是我的Openssl的安装有问题
所以,是时候祭出我的Brew大法了
在终端中输入brew install openssl 安装 openssl
如果有报错的话,就说明你的HomeBrew没有安装或者安装有问题
去 brew.sh 安装一下就好啦
安装完成后,输入以下代码查看openssl 的安装路径
brew --prefix openssl
然后,就会返回一串路径,比如:/opt/homebrew/opt/openssl@3
这个是因为brew安装的东西是完全独立于系统运行库的,所以它会指向它自己的文件夹,自己的库
我们现在需要做的就是引用这个库
所以,我们更新我们的执行代码
cd "/Users/halu/Desktop/Lab2/" && gcc -I/opt/homebrew/opt/openssl@3/include -L/opt/homebrew/opt/openssl@3/lib Lab2.c -o Lab2 -lcrypto && "/Users/halu/Desktop/Lab2/"Lab2
代码格式如下:
cd "/Users/halu/Desktop/Lab2/"
:- 这个命令将当前工作目录更改为
/Users/halu/Desktop/Lab2/
。
- 这个命令将当前工作目录更改为
&&
:- 这个符号是一个逻辑运算符,它表示只有当前面的命令(
cd "/Users/halu/Desktop/Lab2/"
)成功执行后,才会执行后面的命令。
- 这个符号是一个逻辑运算符,它表示只有当前面的命令(
gcc -I/opt/homebrew/opt/openssl@3/include -L/opt/homebrew/opt/openssl@3/lib Lab2.c -o Lab2 -lcrypto
:- 这个命令调用GCC编译器来编译
Lab2.c
文件。 -I/opt/homebrew/opt/openssl@3/include
指定了头文件的搜索路径,以便编译器能够找到OpenSSL库的头文件。-L/opt/homebrew/opt/openssl@3/lib
指定了库文件的搜索路径,以便链接器能够找到OpenSSL库的库文件。-o Lab2
指定了输出的可执行文件名为Lab2
。-lcrypto
是一个链接选项,它告诉链接器链接OpenSSL的libcrypto
库。
- 这个命令调用GCC编译器来编译
&&
:- 同上,这个符号表示只有当前面的命令(编译命令)成功执行后,才会执行后面的命令。
"/Users/halu/Desktop/Lab2/"Lab2
:- 这个命令运行了刚刚编译的
Lab2
可执行文件。
- 这个命令运行了刚刚编译的
总的来说,这个命令序列首先更改了工作目录,然后编译了Lab2.c
文件,并生成了Lab2
可执行文件,最后尝试运行Lab2
可执行文件。
最后,高亮显示了需要替换的部分:
cd "[你的执行路径]" && gcc -I[你的OpenSSL头文件路径] -L[你的OpenSSL库文件路径] [文件名].c -o [文件夹名称] -lcrypto && "[你的执行路径]" [文件名]
一个可能的例子是:
cd "/Users/你的用户名/Desktop/Lab2/" && gcc -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib Lab2.c -o Lab2 -lcrypto && "/Users/你的用户名/Desktop/Lab2/"Lab2
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#include <string.h>
void 哈希_sha256(const char *信息, char *输出);
void 哈希_md5(const char *信息, char *输出);
void 哈希(const char *算法, const char *信息, char *输出);
void 加密_解密(const unsigned char *明文, unsigned char *密文, unsigned char *解密文);
int main()
{
const char *信息 = "Hello, World!";
char sha256输出[SHA256_DIGEST_LENGTH * 2 + 1]; // 创建一个字符串来存储SHA-256哈希值
char md5输出[MD5_DIGEST_LENGTH * 2 + 1]; // 创建一个字符串来存储MD5哈希值
//因为是已经被弃用了的方法,所以这边放弃使用
//哈希_sha256(信息, sha256输出); // 调用SHA-256哈希函数
//哈希_md5(信息, md5输出); // 调用MD5哈希函数
//改用推荐的EVP方法
哈希("SHA256", 信息, sha256输出);
哈希("MD5", 信息, md5输出);
printf("SHA-256 Hash: %s\n", sha256输出);
printf("MD5 Hash: %s\n", md5输出);
char 用户输入[256];
printf("输入你的密码 (最大 255 字符):");
scanf("%255s", 用户输入);
char 用户输入sha256输出[SHA256_DIGEST_LENGTH * 2 + 1];
char 用户输入md5输出[MD5_DIGEST_LENGTH * 2 + 1];
哈希("SHA256", 用户输入, 用户输入sha256输出);
哈希("MD5", 用户输入, 用户输入md5输出);
printf("密码 SHA-256 Hash: %s\n", 用户输入sha256输出);
printf("密码 MD5 Hash: %s\n", 用户输入md5输出);
const unsigned char 明文[] = "Hello, World!";
unsigned char 密文[128];
unsigned char 解密文[128];
加密_解密(明文, 密文, 解密文);
// 输出结果
printf("原始消息: %s\n", 明文);
printf("加密消息: ");
for (int i = 0; i < strlen((char *)密文); ++i) {
printf("%02x", 密文[i]);
}
printf("\n");
printf("解密消息: %s\n", 解密文);
return 0;
}
void 哈希(const char *算法, const char *信息, char *输出) {
EVP_MD_CTX *mdctx;
const EVP_MD *md;
unsigned char md值[EVP_MAX_MD_SIZE];
unsigned int md长度, i;
md = EVP_get_digestbyname(算法);
if (md == NULL) {
printf("未知的哈希算法: %s\n", 算法);
return;
}
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, 信息, strlen(信息));
EVP_DigestFinal_ex(mdctx, md值, &md长度);
EVP_MD_CTX_free(mdctx);
for(i = 0; i < md长度; i++)
sprintf(输出 + (i * 2), "%02x", md值[i]);
}
void 加密_解密(const unsigned char *明文, unsigned char *密文, unsigned char *解密文) {
// 生成随机密钥和IV (初始化向量)
unsigned char 密钥[EVP_MAX_KEY_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!RAND_bytes(密钥, EVP_MAX_KEY_LENGTH) || !RAND_bytes(iv, EVP_MAX_IV_LENGTH)) {
fprintf(stderr, "生成密钥或IV失败。\n");
return;
}
// 创建并初始化加密上下文
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, 密钥, iv)) {
fprintf(stderr, "初始化加密上下文失败。\n");
return;
}
// 加密明文
int len, 密文长度;
if (!EVP_EncryptUpdate(ctx, 密文, &len, 明文, strlen((char *)明文))) {
fprintf(stderr, "加密失败。\n");
return;
}
密文长度 = len;
if (!EVP_EncryptFinal_ex(ctx, 密文 + len, &len)) {
fprintf(stderr, "完成加密失败。\n");
return;
}
密文长度 += len;
EVP_CIPHER_CTX_free(ctx); // 释放加密上下文
// 创建并初始化解密上下文
ctx = EVP_CIPHER_CTX_new();
if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, 密钥, iv)) {
fprintf(stderr, "初始化解密上下文失败。\n");
return;
}
// 解密密文
int 解密文长度;
if (!EVP_DecryptUpdate(ctx, 解密文, &len, 密文, 密文长度)) {
fprintf(stderr, "解密失败。\n");
return;
}
解密文长度 = len;
if (!EVP_DecryptFinal_ex(ctx, 解密文 + len, &len)) {
fprintf(stderr, "完成解密失败。\n");
return;
}
解密文长度 += len;
解密文[解密文长度] = '\0'; // 在解密字符串末尾添加空字符
EVP_CIPHER_CTX_free(ctx); // 释放解密上下文
}