oppenssl 3.5.2 x64签名RSA签名验证的C代码,一字节替换公钥的练习素材
本帖最后由 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
#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 = '\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;
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);
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++) {
hLib = LoadLibraryA(dll_names);
if (hLib) break;
}
if (!hLib) {
printf("Failed to load OpenSSL library. Tried:\n");
for (int i = 0; dll_names; i++) printf(" - %s\n", dll_names);
print_search_paths();
return 1;
}
if (!init_openssl_functions(hLib)) {
FreeLibrary(hLib);
return 1;
}
// 读取文件
char* public_key = read_public_key_pem(argv);
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, &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, &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;
}
谢谢分享 PYG20周年生日快乐! 表哥开始教学了,赞 PYG有你更精彩! 膜拜大神~!
PYG有你更精彩! 请问:是什么用途????????、 PYG有你更精彩!
页:
[1]