2021-05-12 14:32:11
呼叫OpenSSL實現RSA加解密和簽名操作
RSA公鑰可以從證書和公鑰檔案,RSA私鑰可以從私鑰檔案中提取。OpenSSL使用了一種BIO抽象IO機制讀寫所用檔案,可以開啟檔案相關聯的BIO,通過BIO讀寫檔案內容。
程式碼範例如下:
// 證書、私鑰、公鑰都是PEM格式檔案
// 編譯命令:gcc -o test test_pubkey_pem.c -lcrypto -std=c99
#include <openssl/x509.h>
#include <openssl/pem.h>
#include<stdio.h>
#include<string.h>
// 檔案路徑
char cert_filename[] = "/root/test.crt";
char pubkey_filename[] = "/root/testpub.pem";
char prikey_filename[] = "/root/testpri.pem";
int main()
{
EVP_PKEY *pkey;
BIO *pubkey_bio;
BIO *prikey_bio;
BIO *cert;
/************ 從證書中提取公鑰 ****************/
// 開啟證書檔案
cert = BIO_new_file(cert_filename, "r");
// 讀入X509證書
X509 * x_cert = PEM_read_bio_X509(cert, NULL, NULL, NULL);
BIO_free(cert);
// 提取出金鑰EVP_PKEY結構
pkey = X509_get_pubkey(x_cert);
// 提取出RSA結構的公鑰
RSA* rsa_from_cert = EVP_PKEY_get1_RSA(pkey);
X509_free(x_cert);
EVP_PKEY_free(pkey);
// 列印公鑰的值
BIO * print_out=BIO_new(BIO_s_file());
BIO_set_fp(print_out,stdout,BIO_NOCLOSE);
RSA_print(print_out, rsa_from_cert, 0);
int ret;
/************ 從公鑰檔案中提取公鑰 ****************/
//匯入公鑰檔案
char rsa_in[] = "testing";
int rsa_inlen = strlen(rsa_in);
pubkey_bio=BIO_new_file(pubkey_filename,"r");
// 提取出金鑰EVP_PKEY結構
pkey=PEM_read_bio_PUBKEY(pubkey_bio, NULL, NULL, NULL);
// 提取出公鑰RSA結構
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
RSA_print(print_out, rsa, 0);
/************ 從公鑰檔案中提取公鑰 ****************/
prikey_bio=BIO_new_file(prikey_filename,"r");
pkey=PEM_read_bio_PrivateKey(prikey_bio, NULL, NULL, NULL);
RSA *pri_rsa = EVP_PKEY_get1_RSA(pkey);
/*********** 預分配控制元件 ******************/
// 根據RSA公鑰長度分配RSA加密輸出空間
int keysize = RSA_size(rsa);
printf("keysize:%dn", keysize);
unsigned char *rsa_out = OPENSSL_malloc(keysize);
unsigned char *rsa_out_cert = OPENSSL_malloc(keysize);
unsigned char *dec_out = OPENSSL_malloc(keysize);
unsigned char *sign_out = OPENSSL_malloc(keysize);
unsigned char *verify_out = OPENSSL_malloc(keysize);
// 使用RKCS#1填充標準
int pad = RSA_PKCS1_PADDING;
/*********** RSA公鑰加密 ******************/
int rsa_outlen_cert = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out_cert, rsa_from_cert, pad);
int rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
printf("rsa_outlen is: %dn", rsa_outlen);
for(int i=0; i<rsa_outlen; i++){
printf("%02x", rsa_out[i]);
if((i+1)%16 == 0)
printf("n");
}
printf("n");
printf("rsa_outlen_cert is: %dn", rsa_outlen_cert);
for(int i=0; i<rsa_outlen_cert; i++){
printf("%02x", rsa_out_cert[i]);
if((i+1)%16 == 0)
printf("n");
}
printf("n");
/*********** RSA私鑰解密 ******************/
int dec_len = RSA_private_decrypt(rsa_outlen_cert, rsa_out_cert, dec_out, pri_rsa, pad);
if(!memcmp(rsa_in, dec_out, dec_len)){
printf("decrypt success!n");
}else{
printf("decrypt fail!n");
}
printf("dec_len is %dn", dec_len);
/*********** RSA私鑰簽名 *******************/
int sign_len = RSA_private_encrypt(rsa_inlen, rsa_in, sign_out, pri_rsa, pad);
printf("sign_len is: %dn", sign_len);
for(int i=0; i<sign_len; i++){
printf("%02x", sign_out[i]);
if((i+1)%16 == 0)
printf("n");
}
printf("n");
/********** RSA公鑰驗籤 *******************/
int verify_len = RSA_public_decrypt(sign_len, sign_out, verify_out, rsa, pad);
printf("verify_len is %dn", verify_len);
if(!memcmp(rsa_in, verify_out, verify_len)){
printf("verify success!n");
}else{
printf("verify fail!n");
}
/***********釋放變數清理空間 ****************/
OPENSSL_free(rsa_out);
OPENSSL_free(dec_out);
OPENSSL_free(rsa_out_cert);
OPENSSL_free(sign_out);
OPENSSL_free(verify_out);
BIO_free(pubkey_bio);
BIO_free(prikey_bio);
EVP_PKEY_free(pkey);
RSA_free(rsa);
RSA_free(pri_rsa);
RSA_free(rsa_from_cert);
return 0;
}
Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址:https://www.linuxidc.com/Linux/2018-09/154050.htm
相關文章