生成公私钥
void generateKeys(){
EVP_PKEY* pkey = EVP_RSA_gen(1024);
if(pkey == NULL){
fprintf(stderr,"error: rsa gen\n");
ERR_print_errors_fp(stderr);
return;
}
FILE* fp = fopen("public.pem","wt");
if(fp! = NULL){
PEM_write_PUBKEY(fp,pkey);
fclose(fp);
}else{
perror("file error");
}
fp = fopen("private.pem","wt");
if(fp != NULL){
PEM_write_PrivateKey(fp,pkey,NULL,NULL,0,NULL,NULL);
fclose(fp);
}else{
perror("file error");
}
EVP_PKEY_free(pkey);
}
公钥加密
uchar *encrypt_public(uchar *src, uint len, int *length)
{
FILE *fp;
fopen_s(&fp, "public.pem", "r");
if (fp == NULL)
{
perror("file error");
return NULL;
}
EVP_PKEY *pkey;
pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
fclose(fp);
if (pkey == NULL)
{
fprintf(stderr, "error: read publics key\n");
return NULL;
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
EVP_PKEY_encrypt_init(ctx);
uchar *dst = (uchar *)malloc(2048);
size_t outl = 2048;
if (!EVP_PKEY_encrypt(ctx, dst, &outl, src, (size_t)len))
{
fprintf(stderr, "error: encrypt\n");
EVP_PKEY_free(pkey);
free(dst);
return NULL;
}
int len2 = outl;
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
BIO_dump_fp(stdout, dst, len2);
printf("len: %d, len2: %d\n", len, len2);
if (length != NULL)
{
*length = len2;
}
return dst;
}
私钥解密
uchar *decrypt_private(uchar *src, int len)
{
FILE *fp;
fopen_s(&fp, "private.pem", "r");
if (fp == NULL)
{
perror("file error");
return NULL;
}
EVP_PKEY *pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose(fp);
if (pkey == NULL)
{
fprintf(stderr, "error: read private key\n");
return NULL;
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
EVP_PKEY_decrypt_init(ctx);
uchar *dst = (uchar *)malloc(2048);
size_t outl;
size_t inl = len;
if (!EVP_PKEY_decrypt(ctx, dst, &outl, src, inl))
{
fprintf(stderr, "error: decrypt\n");
free(dst);
dst = NULL;
}
else
{
BIO_dump_fp(stdout, dst, (int)outl);
printf("len: %d, outl: %lld\n", len, outl);
}
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return dst;
}
cmake 静态链接openssl
...
...
...
IF(CMAKE_CL_64)
include_directories("C:\\Program Files\\OpenSSL-Win64\\include")
link_directories("C:\\Program Files\\OpenSSL-Win64\\lib")
ELSE(CMAKE_CL_64)
include_directories("C:\\Program Files (x86)\\OpenSSL-Win32\\include")
link_directories("C:\\Program Files (x86)\\OpenSSL-Win32\\lib")
ENDIF(CMAKE_CL_64)
# STATIC编译 取消openssl依赖
set(OPENSSL_USE_STATIC_LIBS TRUE)
find_package(OpenSSL REQUIRED)
add_library(RSA SHARED library.c)
target_link_libraries(RSA OpenSSL::Crypto)
OPENSSL_Uplink(100F2010,05): no OPENSSL_Applink
在非动态链接库
当中可以通过添加头问题的方式添加文件applink.c
:
#include <openssl/applink.c>
如果是在动态链接库
当中的话, 主要检查IO方式
的影响(读取文件和输出等地方), 比如可以将读取公钥私钥的方式换成BIO
的形式:
BIO* in=NULL;
in = BIO_new(BIO_s_file());
BIO_read_filename(in,"private.pem");
if (in == NULL){
perror("private.pem");
return NULL;
}
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
BIO_free(in);
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
EVP_PKEY_decrypt_init(ctx);
uchar *dst = (uchar *) malloc(2048);
size_t outl;
size_t inl = len;
if (!EVP_PKEY_decrypt(ctx, dst, &outl, src, inl)) {
fprintf(stderr, "error: decrypt\n");
free(dst);
dst = NULL;
} else {
printf("len: %d, outl: %lld\n", len, outl);
}
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return dst;