Ubuntu16.04 使用OpenSSL库实现RSA

本文介绍如何在Ubuntu上安装OpenSSL并使用C语言实现RSA加密和解密过程。包括安装指南、C代码示例及Python调用动态库执行加解密的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Ubuntu安装OpenSSL开发包
Ubuntu已经安装过openssl但是仍然不能进行openssl编程
需安装openssl-devel包。
Ubuntu16.04下安装OpenSSL库
sudo apt-get install openssl
sudo apt-get install libssl-dev

二、编写C代码,实现RSA接口
1、代码实现:
1、Public Encryption and Private Decryption
Below is the OpenSSL API for Public encryption and Private decryption.

int RSA_public_encrypt(int flen, unsigned char *from,
   unsigned char *to, RSA *rsa, int padding);

int RSA_private_decrypt(int flen, unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);

1.1 Preparing RSA Structure
For encryption and decryption we need to prepare RSA structure. Use the below function to create RSA with key buffer.

RSA * createRSA(unsigned char * key,int public)
{
    RSA *rsa= NULL;
    BIO *keybio ;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio==NULL)
    {
        printf( "Failed to create key BIO");
        return 0;
    }
    if(public)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    }

    return rsa;
}

Usage for public key: createRSA(“PUBLIC_KEY_BUFFER”,1);
Usage for private key: createRSA(“PRIVATE_KEY_BUFFER”,0);

If you want to create RSA with key file name, you can use this function

RSA * createRSAWithFilename(char * filename,int public)
{
    FILE * fp = fopen(filename,"rb");

    if(fp == NULL)
    {
        printf("Unable to open file %s \n",filename);
        return NULL;    
    }
    RSA *rsa= RSA_new() ;

    if(public)
    {
        rsa = PEM_read_RSA_PUBKEY(fp, &rsa,NULL, NULL);
    }
    else
    {
        rsa = PEM_read_RSAPrivateKey(fp, &rsa,NULL, NULL);
    }

    return rsa;
}

1.2 Public Key Encryption.
For encryption we can use padding, below is the list of supported paddings.

RSA_PKCS1_PADDING
PKCS #1 v1.5 padding. This currently is the most widely used mode.
RSA_PKCS1_OAEP_PADDING
EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. This mode is recommended for all new applications.
RSA_SSLV23_PADDING
PKCS #1 v1.5 padding with an SSL-specific modification that denotes that the server is SSL3 capable.
RSA_NO_PADDING
Raw RSA encryption. This mode should only be used to implement cryptographically sound padding modes in the application code. Encrypting user data directly with RSA is insecure.

You can use the below method, to encrypt the data with public key.

int padding = RSA_PKCS1_PADDING;

int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,1);
    int result = RSA_public_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}

Note: public key encryption supports all the paddings.

1.3 Private Decryption.
You can use the below method to decrypt the data with private key

int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,0);
    int  result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}

2、Private Key Encryption and Public Key Decryption.
Below is the OpenSSL API for private encryption and public decryption.

int RSA_private_encrypt(int flen, unsigned char *from,
   unsigned char *to, RSA *rsa, int padding);

int RSA_public_decrypt(int flen, unsigned char *from,
   unsigned char *to, RSA *rsa, int padding);

Note: private key encryption supports only these paddings. RSA_PKCS1_PADDING and RSA_NO_PADDING.

2.1 Private Key Encryption.
You can use the below function for private key encryption.

int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,0);
    int result = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}

2.2 Public Key Decryption.
You can use the below function for public key decryption.

int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,1);
    int  result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}

3) Encryption and Decryption Example code.

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>

int padding = RSA_PKCS1_PADDING;

RSA * createRSA(unsigned char * key,int public)
{
    RSA *rsa= NULL;
    BIO *keybio ;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio==NULL)
    {
        printf( "Failed to create key BIO");
        return 0;
    }
    if(public)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    }
    if(rsa == NULL)
    {
        printf( "Failed to create RSA");
    }

    return rsa;
}

int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,1);
    int result = RSA_public_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,0);
    int  result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}


int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,0);
    int result = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,1);
    int  result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}

void printLastError(char *msg)
{
    char * err = malloc(130);;
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    printf("%s ERROR: %s\n",msg, err);
    free(err);
}

int main(){

  char plainText[2048/8] = "Hello this is Ravi"; //key length : 2048

 char publicKey[]="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";

 char privateKey[]="-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\
"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\
"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\
"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\
"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\
"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\
"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\
"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\
"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\
"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\
"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\
"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\
"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\
"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\
"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\
"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\
"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\
"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\
"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\
"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\
"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\
"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\
"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\
"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\
"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\
"-----END RSA PRIVATE KEY-----\n";


unsigned char  encrypted[4098]={};
unsigned char decrypted[4098]={};

int encrypted_length= public_encrypt(plainText,strlen(plainText),publicKey,encrypted);
if(encrypted_length == -1)
{
    printLastError("Public Encrypt failed ");
    exit(0);
}
printf("Encrypted length =%d\n",encrypted_length);

int decrypted_length = private_decrypt(encrypted,encrypted_length,privateKey, decrypted);
if(decrypted_length == -1)
{
    printLastError("Private Decrypt failed ");
    exit(0);
}
printf("Decrypted Text =%s\n",decrypted);
printf("Decrypted Length =%d\n",decrypted_length);


encrypted_length= private_encrypt(plainText,strlen(plainText),privateKey,encrypted);
if(encrypted_length == -1)
{
    printLastError("Private Encrypt failed");
    exit(0);
}
printf("Encrypted length =%d\n",encrypted_length);

decrypted_length = public_decrypt(encrypted,encrypted_length,publicKey, decrypted);
if(decrypted_length == -1)
{
    printLastError("Public Decrypt failed");
    exit(0);
}
printf("Decrypted Text =%s\n",decrypted);
printf("Decrypted Length =%d\n",decrypted_length);




}

Reference:openssl documentaion
代码转自:http://hayageek.com/rsa-encryption-decryption-openssl-c/#private-encrypt
参考:http://www.qmailer.net/archives/216.html

2、引用OpenSSL的动态库,将上述代码编译成.so文件

不管什么库文件,都既要在包含.h文件(不然编译通不过:有未声明的函数),也要在gcc选项里面指定.so文件的位置(不然链接通不过:未知的符号)

gcc -c -g -fPIC -O2 rsa.c -I include_path -I lib_path
gcc -shared -o./libRSA.so rsa.o -L lib_path -lcrypto

include_path 改成你所编译的库文件头文件的目录
lib_path 改成应用的OpenSSL动态库文件的目录
libRSA.so 改成你所编译的库文件名字
-lcrypto OpenSSL动态库的名字

第一条编译指令,引用OpenSSL的动态库将rsa.c编译为rsa.o
第二条编译指令,将rsa.o文件编译为动态库libRSA.so

三、Python调用.so,执行加解密
1、将yourlib.so与Python脚本放在同一文件夹;
2、Python引用.so代码如下:

import ctypes 
ll = ctypes.cdll.LoadLibrary   
MyRSA = ll("./libRSA.so") 
res = MyRSA.main() 
print str(res)

3、生成公私钥对

os.system('openssl genrsa -out private.pem 2048')
os.system('openssl rsa -in private.pem -outform PEM -pubout -out public.pem')

以上代码便可执行以上C代码实现的main函数(Encryption and Decryption Example code),执行一个rsa加解密的例子。

### 如何在 Ubuntu 16.04 上升级 OpenSSL 对于希望提升安全性或修复已知漏洞的用户来说,在 Ubuntu 16.04 上手动编译并安装最新版本的 OpenSSL 是一种方法。然而,推荐的方式是通过官方更新渠道来获取最新的安全补丁。 #### 使用 APT 更新 OpenSSL 为了确保系统的稳定性和兼容性,建议优先考虑使用 `apt` 来更新软件包: ```bash sudo apt update && sudo apt install --only-upgrade openssl ``` 这条命令会检查是否有可用的安全更新,并仅当存在更高版本时才执行升级操作[^1]。 如果上述方式未能提供所需的新版 OpenSSL,则可以尝试添加第三方 PPA 或者直接下载源码进行编译安装。不过需要注意的是,这种方式可能会引入未知的风险以及破坏现有依赖关系链。 #### 手动编译安装 OpenSSL 若决定采用手工编译的形式来进行升级工作,请按照如下流程操作: 1. 卸载当前版本(可选) 如果担心新旧版本冲突,可以选择先移除现有的 OpenSSL 安装: ```bash sudo apt remove openssl libssl-dev ``` 2. 下载目标版本源代码 访问 [OpenSSL官方网站](https://www.openssl.org/source/) 获取指定版本 tarball 文件,这里假设要安装 v3.0.x 版本为例: ```bash wget https://www.openssl.org/source/openssl-3.0.5.tar.gz tar -xf openssl-3.0.5.tar.gz cd openssl-3.0.5/ ``` 3. 配置构建环境 & 编译 进入解压后的目录后运行配置脚本,根据需求调整参数选项;之后即可开始编译过程: ```bash ./config shared zlib no-tests make depend make ``` 4. 测试&替换原生 (谨慎) 成功编译完成后,可以通过测试套件验证功能正常与否: ```bash make test ``` 当确认无误后,再继续完成最终部署动作: ```bash sudo make install ``` 请注意,以上步骤中的具体细节可能因不同发行版而有所差异,务必仔细阅读相关文档说明后再行动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值