飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 460|回复: 6

[原创] oppenssl 3.5.2 x64签名RSA签名验证的C代码,一字节替换公钥的练习素材

[复制链接]
  • TA的每日心情
    奋斗
    2024-5-22 16:18
  • 签到天数: 1129 天

    [LV.10]以坛为家III

    发表于 3 天前 | 显示全部楼层 |阅读模式
    本帖最后由 slzslz 于 2025-8-10 16:23 编辑

    敲代码不易,求点赞
    可以作为小白练习一字节替换公钥的对象
    加密自己软件也可以在这个模版上深化
    mingw x64 编译命令
    gcc verify_license.c -o verify_license.exe -ladvapi32
    签名验证命令   verify_license.exe public_key.pem license_sig.bin data.txt
    [C] 纯文本查看 复制代码
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    
    // 定义 OpenSSL 初始化标志
    #define OPENSSL_INIT_LOAD_CONFIG         0x00000004L
    #define OPENSSL_INIT_ADD_ALL_CIPHERS     0x00000004L
    #define OPENSSL_INIT_ADD_ALL_DIGESTS     0x00000008L
    #define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
    
    // 声明OpenSSL不透明结构体类型
    typedef struct evp_md_ctx_st EVP_MD_CTX;
    typedef struct bio_st BIO;
    typedef struct evp_pkey_st EVP_PKEY;
    typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
    typedef struct engine_st ENGINE;
    typedef struct evp_md_st EVP_MD;
    typedef struct ossl_provider_st OSSL_PROVIDER;
    
    // 定义密码回调类型
    typedef int (*pem_password_cb)(char* buf, int size, int rwflag, void* u);
    
    // 定义最小化函数指针类型
    typedef EVP_MD_CTX* (*fp_EVP_MD_CTX_new)(void);
    typedef void (*fp_EVP_MD_CTX_free)(EVP_MD_CTX* ctx);
    typedef int (*fp_EVP_DigestVerifyInit)(EVP_MD_CTX* ctx, EVP_PKEY_CTX** pctx, const EVP_MD* type, ENGINE* e, EVP_PKEY* pkey);
    typedef int (*fp_EVP_DigestVerifyUpdate)(EVP_MD_CTX* ctx, const void* d, size_t cnt);
    typedef int (*fp_EVP_DigestVerifyFinal)(EVP_MD_CTX* ctx, const unsigned char* sig, size_t siglen);
    typedef BIO* (*fp_BIO_new_mem_buf)(const void* buf, int len);
    typedef int (*fp_BIO_free)(BIO* a);
    typedef EVP_PKEY* (*fp_PEM_read_bio_PUBKEY)(BIO* bp, EVP_PKEY** x, pem_password_cb cb, void* u);
    typedef void (*fp_EVP_PKEY_free)(EVP_PKEY* pkey);
    typedef const EVP_MD* (*fp_EVP_sha256)(void);
    typedef int (*fp_OPENSSL_init_crypto)(uint64_t opts, const void* settings);
    typedef OSSL_PROVIDER* (*fp_OSSL_PROVIDER_load)(void* ctx, const char* name);
    typedef int (*fp_OSSL_PROVIDER_unload)(OSSL_PROVIDER* prov);
    
    // 全局函数指针
    static fp_EVP_MD_CTX_new EVP_MD_CTX_new = NULL;
    static fp_EVP_MD_CTX_free EVP_MD_CTX_free = NULL;
    static fp_EVP_DigestVerifyInit EVP_DigestVerifyInit = NULL;
    static fp_EVP_DigestVerifyUpdate EVP_DigestVerifyUpdate = NULL;
    static fp_EVP_DigestVerifyFinal EVP_DigestVerifyFinal = NULL;
    static fp_BIO_new_mem_buf BIO_new_mem_buf = NULL;
    static fp_BIO_free BIO_free = NULL;
    static fp_PEM_read_bio_PUBKEY PEM_read_bio_PUBKEY = NULL;
    static fp_EVP_PKEY_free EVP_PKEY_free = NULL;
    static fp_EVP_sha256 EVP_sha256 = NULL;
    static fp_OPENSSL_init_crypto OPENSSL_init_crypto = NULL;
    static fp_OSSL_PROVIDER_load OSSL_PROVIDER_load = NULL;
    static fp_OSSL_PROVIDER_unload OSSL_PROVIDER_unload = NULL;
    static OSSL_PROVIDER* default_provider = NULL;
    
    // 加载OpenSSL函数(最小化版本)
    int init_openssl_functions(HMODULE hLib) {
        #define LOAD_FUNC(type, name) \
            name = (type)GetProcAddress(hLib, #name); \
            if (!name) { \
                printf("Failed to load function: %s\n", #name); \
                return 0; \
            }
    
        // 核心验证函数
        LOAD_FUNC(fp_EVP_MD_CTX_new, EVP_MD_CTX_new);
        LOAD_FUNC(fp_EVP_MD_CTX_free, EVP_MD_CTX_free);
        LOAD_FUNC(fp_EVP_DigestVerifyInit, EVP_DigestVerifyInit);
        LOAD_FUNC(fp_EVP_DigestVerifyUpdate, EVP_DigestVerifyUpdate);
        LOAD_FUNC(fp_EVP_DigestVerifyFinal, EVP_DigestVerifyFinal);
        
        // BIO函数
        LOAD_FUNC(fp_BIO_new_mem_buf, BIO_new_mem_buf);
        LOAD_FUNC(fp_BIO_free, BIO_free);
        
        // 密钥函数
        LOAD_FUNC(fp_PEM_read_bio_PUBKEY, PEM_read_bio_PUBKEY);
        LOAD_FUNC(fp_EVP_PKEY_free, EVP_PKEY_free);
        
        // 哈希函数
        LOAD_FUNC(fp_EVP_sha256, EVP_sha256);
        
        // OpenSSL 3.0+ 初始化
        LOAD_FUNC(fp_OPENSSL_init_crypto, OPENSSL_init_crypto);
        LOAD_FUNC(fp_OSSL_PROVIDER_load, OSSL_PROVIDER_load);
        LOAD_FUNC(fp_OSSL_PROVIDER_unload, OSSL_PROVIDER_unload);
    
        // 初始化OpenSSL 3.0
        uint64_t init_flags = OPENSSL_INIT_LOAD_CONFIG | 
                             OPENSSL_INIT_ADD_ALL_CIPHERS |
                             OPENSSL_INIT_ADD_ALL_DIGESTS |
                             OPENSSL_INIT_LOAD_CRYPTO_STRINGS;
        
        if (OPENSSL_init_crypto(init_flags, NULL) == 0) {
            printf("OPENSSL_init_crypto failed\n");
            return 0;
        }
        
        // 加载默认提供者
        default_provider = OSSL_PROVIDER_load(NULL, "default");
        if (!default_provider) {
            printf("Failed to load default provider\n");
            return 0;
        }
    
        return 1;
        #undef LOAD_FUNC
    }
    
    // 读取二进制文件
    int read_binary_file(const char* filename, unsigned char** data, size_t* len) {
        FILE* file = fopen(filename, "rb");
        if (!file) {
            perror("Error opening file");
            return 0;
        }
    
        fseek(file, 0, SEEK_END);
        *len = ftell(file);
        fseek(file, 0, SEEK_SET);
    
        *data = (unsigned char*)malloc(*len);
        if (!*data) {
            fclose(file);
            printf("Memory allocation failed\n");
            return 0;
        }
    
        if (fread(*data, 1, *len, file) != *len) {
            fclose(file);
            free(*data);
            printf("Error reading file\n");
            return 0;
        }
    
        fclose(file);
        return 1;
    }
    
    // 修正PEM格式
    char* fix_pem_format(const char* pem_data) {
        const char* header = "-----BEGIN";
        const char* footer = "-----END";
        
        const char* begin = strstr(pem_data, header);
        if (!begin) return NULL;
        
        const char* end = strstr(pem_data, footer);
        if (!end) return NULL;
        
        end += strlen(footer);
        while (*end && *end != '\n' && *end != '\r') end++;
        
        size_t length = end - begin;
        char* fixed = (char*)malloc(length + 2);
        if (!fixed) return NULL;
        
        const char* src = begin;
        char* dst = fixed;
        
        while (src < end) {
            if (*src == '\r') { src++; continue; }
            *dst++ = *src++;
        }
        
        if (*(dst-1) != '\n') *dst++ = '\n';
        *dst = '\0';
        
        return fixed;
    }
    
    // 读取公钥文件
    char* read_public_key_pem(const char* filename) {
        FILE* file = fopen(filename, "r");
        if (!file) {
            perror("Error opening public key file");
            return NULL;
        }
    
        fseek(file, 0, SEEK_END);
        long file_size = ftell(file);
        fseek(file, 0, SEEK_SET);
    
        char* pem_data = (char*)malloc(file_size + 1);
        if (!pem_data) {
            fclose(file);
            return NULL;
        }
    
        fread(pem_data, 1, file_size, file);
        pem_data[file_size] = '\0';
        fclose(file);
    
        char* fixed_pem = fix_pem_format(pem_data);
        free(pem_data);
        return fixed_pem;
    }
    
    // 验证签名(最小化版本)
    int verify_signature(const char* plaintext, size_t text_len,
                        const unsigned char* signature, size_t sig_len,
                        const char* public_key_pem) {
        EVP_MD_CTX* ctx = NULL;
        BIO* bio = NULL;
        EVP_PKEY* pkey = NULL;
        int ret = 0;
    
        if (!(bio = BIO_new_mem_buf(public_key_pem, -1))) {
            printf("Error creating BIO\n");
            goto cleanup;
        }
    
        if (!(pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) {
            printf("Error loading public key\n");
            goto cleanup;
        }
    
        if (!(ctx = EVP_MD_CTX_new())) {
            printf("Error creating EVP_MD_CTX\n");
            goto cleanup;
        }
    
        if (EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, pkey) <= 0) {
            printf("Error initializing verification\n");
            goto cleanup;
        }
    
        if (EVP_DigestVerifyUpdate(ctx, plaintext, text_len) <= 0) {
            printf("Error updating verification data\n");
            goto cleanup;
        }
    
        ret = (EVP_DigestVerifyFinal(ctx, signature, sig_len) == 1);
    
    cleanup:
        if (ctx) EVP_MD_CTX_free(ctx);
        if (pkey) EVP_PKEY_free(pkey);
        if (bio) BIO_free(bio);
        return ret;
    }
    
    void print_search_paths() {
        char path[4096];
        if (GetEnvironmentVariableA("PATH", path, sizeof(path))) {
            printf("Current PATH: %s\n", path);
        }
    }
    
    int main(int argc, char** argv) {
        if (argc != 4) {
            printf("Usage: %s <public_key.pem> <signature.bin> <data.txt>\n", argv[0]);
            return 1;
        }
    
        // 尝试加载OpenSSL
        const char* dll_names[] = {
            "libcrypto-3-x64.dll",  // Windows默认名称
            "libcrypto-3.dll",      // 某些安装可能的名称
            NULL
        };
    
        HMODULE hLib = NULL;
        for (int i = 0; dll_names[i]; i++) {
            hLib = LoadLibraryA(dll_names[i]);
            if (hLib) break;
        }
    
        if (!hLib) {
            printf("Failed to load OpenSSL library. Tried:\n");
            for (int i = 0; dll_names[i]; i++) printf(" - %s\n", dll_names[i]);
            print_search_paths();
            return 1;
        }
    
        if (!init_openssl_functions(hLib)) {
            FreeLibrary(hLib);
            return 1;
        }
    
        // 读取文件
        char* public_key = read_public_key_pem(argv[1]);
        if (!public_key) {
            printf("Invalid public key file\n");
            FreeLibrary(hLib);
            return 1;
        }
    
        unsigned char* signature = NULL;
        size_t sig_len = 0;
        if (!read_binary_file(argv[2], &signature, &sig_len)) {
            printf("Invalid signature file\n");
            free(public_key);
            FreeLibrary(hLib);
            return 1;
        }
    
        unsigned char* data = NULL;
        size_t data_len = 0;
        if (!read_binary_file(argv[3], &data, &data_len)) {
            printf("Invalid data file\n");
            free(public_key);
            free(signature);
            FreeLibrary(hLib);
            return 1;
        }
    
        // 验证签名
        if (verify_signature((const char*)data, data_len, signature, sig_len, public_key)) {
            printf("Signature VALID\n");
        } else {
            printf("Signature INVALID\n");
        }
    
        // 清理
        free(public_key);
        free(signature);
        free(data);
        FreeLibrary(hLib);
        return 0;
    }

    sign.png

    附件.rar

    21.91 KB, 下载次数: 5, 下载积分: 飘云币 -2 枚

    评分

    参与人数 2威望 +2 飘云币 +2 收起 理由
    wgz001 + 1 + 1 感谢发布原创作品,PYG有你更精彩!
    UlRevenge + 1 + 1 PYG有你更精彩!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2025-1-13 09:04
  • 签到天数: 339 天

    [LV.8]以坛为家I

    发表于 前天 14:18 | 显示全部楼层
    PYG20周年生日快乐!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-26 11:14
  • 签到天数: 459 天

    [LV.9]以坛为家II

    发表于 前天 07:30 | 显示全部楼层
    表哥开始教学了,赞
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-1-14 13:49
  • 签到天数: 393 天

    [LV.9]以坛为家II

    发表于 3 天前 | 显示全部楼层
    PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-1-14 20:41
  • 签到天数: 876 天

    [LV.10]以坛为家III

    发表于 3 天前 | 显示全部楼层
    膜拜大神~!
    PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2025-1-14 11:19
  • 签到天数: 501 天

    [LV.9]以坛为家II

    发表于 3 天前 | 显示全部楼层
    请问:是什么用途????????、
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-1-14 13:49
  • 签到天数: 393 天

    [LV.9]以坛为家II

    发表于 3 天前 | 显示全部楼层
    PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表