如何利用OpenSSL库进行RSA加密和解密

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用OpenSSL库进行RSA加密和解密相关的知识,希望对你有一定的参考价值。

参考技术A #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/rsa.h>
#include<openssl/engine.h>

int main(int argc, char* argv[])

   printf("openssl_test begin\\n");
   RSA* rsa=NULL;
   char originstr[]="hello\\n";   //这是我们需要加密的原始数据
   //allocate RSA structure,首先需要申请一个RSA结构题用于存放生成的公私钥,这里rsa就是这个结构体的指针
   rsa = RSA_new();
   if(rsa==NULL)
    
         printf("RSA_new failed\\n");          
         return -1;
    

    //generate RSA keys
   BIGNUM* exponent;
    exponent = BN_new();        //生成RSA公私钥之前需要选择一个奇数(odd number)来用于生成公私钥
    if(exponent ==NULL)
    
       printf("BN_new failed\\n"); 
       goto FAIL1;
    
    if(0==BN_set_word(exponent,65537))    //这里选择奇数65537
    
      printf("BN_set_word failed\\n"); 
      goto FAIL1;
    
    
    
    //这里modulus的长度选择4096,小于1024的modulus长度都是不安全的,容易被破解
    if(0==RSA_generate_key_ex(rsa,4096,exponent,NULL))  
    
       printf("RSA_generate_key_ex failed\\n"); 
       goto FAIL;      
    
    char* cipherstr = NULL;
    //分配一段空间用于存储加密后的数据,这个空间的大小由RSA_size函数根据rsa算出
    cipherstr = malloc(RSA_size(rsa)); 
    if(cipherstr==NULL)
    
       printf("malloc cipherstr buf failed\\n");
       goto FAIL1;
    
   //下面是实际的加密过程,最后一个参数padding type,有以下几种。    
/*
RSA_PKCS1_PADDINGPKCS #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.
*/  
  //这里首先用公钥进行加密,选择了RSA_PKCS1_PADDING

  if(RSA_size(rsa)!=RSA_public_encrypt(strlen(originstr)+1,originstr,cipherstr,rsa,RSA_PKCS1_PADDING))
    
       printf("encryption failure\\n");
        goto FAIL2;
    
    printf("the original string is %s\\n",originstr);
    printf("the encrypted string is %s\\n",cipherstr);


    //Now, let's decrypt the string with private key
    //下面来用私钥解密,首先需要一个buffer用于存储解密后的数据,这个buffer的长度要足够(小于RSA_size(rsa))
    //这里分配一个长度为250的字符数组,应该是够用的。
    char decrypted_str[250];
    int decrypted_len;
    if(-1=(decrypted_len=RSA_private_decrypt(256,cipherstr,decrypted_str,rsa,RSA_PKCS1_PADDING)))
    
       printf("decryption failure\\n");
        goto FAIL2;
    
    printf("decrypted string length is %d,decryped_str is %s\\n",decrypted_len,decrypted_str);
FAIL2:
      free(cipherstr);
FAIL1:
    BN_free(exponent);
FAIL:
   RSA_free(rsa);
   return 0;

以上是源代码,下面使用下面的编译命令在源码所在路径下生成可执行文件
    gcc *.c -o openssl_test -lcrypto -ldl -L/usr/local/ssl/lib -I/usr/local/ssl/include
其中,-lcrypto和-ldl是必须的,前者是OpenSSL中的加密算法库,后者是用于成功加载动态库。

本回答被提问者采纳

OpenSSL PHP RSA 加密:在客户端使用哪个库解密?

【中文标题】OpenSSL PHP RSA 加密:在客户端使用哪个库解密?【英文标题】:OpenSSL PHP RSA Encryption: Which library to use to decrypt on client side? 【发布时间】:2012-02-06 04:05:17 【问题描述】:

我开发了一个桌面应用程序 (.NET 2.0),它需要从运行 php/mysql 的服务器获取一些信息。服务器端的提供商决定使用 openssl_private_encrypt 方法进行加密,并为我提供了一个 publickey.pem 文件。我不擅长 php/mysql,但我知道如果我使用 asp .net 不会有任何不同。

我的问题是如何解密 .NET 2.0 应用程序中的私有加密数据。我所有使用带有公钥的 RSACrypoServiceProvider 的尝试都被证明是不成功的。

我偶然发现了 ManagedOpenSSL 库,但这也不好。

我确信 *** 的许多人都会做类似的事情,如果知道他们是如何做到的,那就太好了。

提前感谢您的所有帮助。

【问题讨论】:

【参考方案1】:

.NET 使用 OpenSSL 不支持的 XML 格式的密钥。我的建议是使用phpseclib, a pure PHP RSA implementation 生成密钥对 - 或至少将现有密钥对转换为 XML。

【讨论】:

谢谢纽伯特。但是,生成密钥对意味着我要求服务器管理员使用我生成的私钥,我认为他们不会接受这样的请求。我将在下面发布答案。但是,我认为经过几个小时的打击和试验后,我设法让它工作了。我使用了 BouncyCastle,然后进行了一些尝试,设法弄明白了。【参考方案2】:

这是我用来让它工作的!

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            string responseFromServerEnc = string.Empty;

            byte[] data = null;

            if (HttpStatusCode.OK == response.StatusCode)
            
                MemoryStream memoryStream = new MemoryStream(0x10000);

                using (Stream responseStream =            request.GetResponse().GetResponseStream())
                
                    byte[] buffer = new byte[0x1000];
                    int bytes;
                    while ((bytes = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                    
                        memoryStream.Write(buffer, 0, bytes);
                    

                    data = memoryStream.ToArray();
                

                response.Close();
            


            const string pubKey = "-----BEGIN PUBLIC KEY-----\n key from .pem file \n-----END PUBLIC KEY-----";
            PemReader pem = new PemReader(new StringReader(pubKey));
            RsaKeyParameters bcp = (RsaKeyParameters)pem.ReadObject();

            string responseFromServer = Encoding.UTF8.GetString(Decrypt(data,bcp));

responseFromServerEnc 是加密消息,responseFromServer 被正确解密。

【讨论】:

以上是关于如何利用OpenSSL库进行RSA加密和解密的主要内容,如果未能解决你的问题,请参考以下文章

用openssl库RSA加密解密

OPENSSL RSA加密与解密

php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密

利用openSSL库AES模块加密

PHP 使用openssl 进行加密 解密

openssl rsa 可以用私钥加密 公钥解密吗