最近在用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

代码格式如下:

  1. cd "/Users/halu/Desktop/Lab2/"

    • 这个命令将当前工作目录更改为/Users/halu/Desktop/Lab2/
  2. &&

    • 这个符号是一个逻辑运算符,它表示只有当前面的命令(cd "/Users/halu/Desktop/Lab2/")成功执行后,才会执行后面的命令。
  3. 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库。
  4. &&

    • 同上,这个符号表示只有当前面的命令(编译命令)成功执行后,才会执行后面的命令。
  5. "/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);  // 释放解密上下文
}

Last modification:October 13, 2023
如果觉得我的文章对你有用,请随意赞赏