RSA加解密,密钥对生成,加密与签名

密钥格式常用的有PKCS1和PKCS8

C++使用openssl库这两种密钥格式都可以生成,生成密钥代码如下,使用不同的密钥格式生成不同的密钥:

static bool generate_key(std::string & publicKey, std::string & privateKey)
    {
        BUF_MEM *bptr = NULL;
        RSA *rsa = RSA_generate_key(1024, 65537, NULL, NULL);
        RSA *pubrsa = RSA_new();
        BIO *bmemPri = BIO_new(BIO_s_mem());
        BIO *bmemPub = BIO_new(BIO_s_mem());
        EVP_PKEY *evpKey = EVP_PKEY_new();
        if(!rsa || !pubrsa || !bmemPri || !bmemPub || !evpKey)
        {
            LLOGE("err happens
");
            if(rsa)RSA_free(rsa);
            if(pubrsa)RSA_free(pubrsa);
            if(bmemPri)BIO_free(bmemPri);
            if(bmemPub)BIO_free(bmemPub);
            if(evpKey)EVP_PKEY_free(evpKey);
            return false;
        }
        
        
        EVP_PKEY_set1_RSA(evpKey, rsa);        
        
        if(!PEM_write_bio_PKCS8PrivateKey(bmemPri, evpKey, NULL, NULL, 0, NULL, NULL))//pkcs8
        //if(!PEM_write_bio_RSAPrivateKey(bmemPri, rsa, NULL, NULL, 0, NULL, NULL))//pkcs1
        {
            LLOGE("PEM_write_bio_RSAPrivateKey error
");
            RSA_free(rsa);
            RSA_free(pubrsa);
            BIO_free(bmemPri);
            BIO_free(bmemPub);
            EVP_PKEY_free(evpKey);
            return false;
        }
        BIO_get_mem_ptr(bmemPri,&bptr);    
        if(!bptr)
        {
            LLOGE("BIO_get_mem_ptr error
");
            RSA_free(rsa);
            RSA_free(pubrsa);
            BIO_free(bmemPri);
            BIO_free(bmemPub);
            EVP_PKEY_free(evpKey);
            return false;
        }
        privateKey.assign(bptr->data, bptr->length);        
        
        unsigned char *n_b = (unsigned char *)calloc(RSA_size(rsa), sizeof(unsigned char));
        unsigned char *e_b = (unsigned char *)calloc(RSA_size(rsa), sizeof(unsigned char));

        int n_size = BN_bn2bin(rsa->n, n_b);
        int b_size = BN_bn2bin(rsa->e, e_b);

        pubrsa->n = BN_bin2bn(n_b, n_size, NULL);
        pubrsa->e = BN_bin2bn(e_b, b_size, NULL);

        
        if(!PEM_write_bio_PUBKEY(bmemPub, evpKey))//pkcs8
        //if(!PEM_write_bio_RSAPublicKey(bmemPub, pubrsa))//pkcs1
        {
            LLOGE("PEM_write_bio_RSAPublicKey error
");
            RSA_free(rsa);
            RSA_free(pubrsa);
            BIO_free(bmemPri);
            BIO_free(bmemPub);
            EVP_PKEY_free(evpKey);
            return false;    
        }
        BIO_get_mem_ptr(bmemPub,&bptr);    
        if(!bptr)
        {
            LLOGE("BIO_get_mem_ptr error
");
            RSA_free(rsa);
            RSA_free(pubrsa);
            BIO_free(bmemPri);
            BIO_free(bmemPub);
            EVP_PKEY_free(evpKey);
            return false;
        }
        std::string puKey(bptr->data, bptr->length);    
        z_pubKeyModify(puKey, publicKey);

        RSA_free(rsa);
        RSA_free(pubrsa);
        BIO_free(bmemPri);
        BIO_free(bmemPub);
        EVP_PKEY_free(evpKey);
        return true;
    }

公钥加解密代码,使用不同的公钥格式要使用不同的函数读取

    static bool public_encrypt(const std::string & pubKey, const std::string & in, std::string & out)
    {    
        std::string publicKey;
        z_pubKeyTrans(pubKey, publicKey);
        BIO *bkey = BIO_new_mem_buf((void*)publicKey.c_str(), publicKey.length());
        if(!bkey)
        {
            LLOGE("BIO_new_mem_buf error
");
            return false;
        }    
        
        EVP_PKEY *evpKey = PEM_read_bio_PUBKEY(bkey, NULL,NULL,NULL);//pkcs8
        if(!evpKey)
        {
            printf("PEM_read_bio_PUBKEY error
");
            BIO_free(bkey);
            return false;            
        }
        RSA *rsa = EVP_PKEY_get1_RSA(evpKey);        
        //RSA *rsa = PEM_read_bio_RSAPublicKey(bkey,NULL,NULL,NULL);//pkcs1
        if(!rsa)
        {
            LLOGE("PEM_read_bio_RSAPublicKey error
");
            BIO_free(bkey);
            EVP_PKEY_free(evpKey);
            return false;
        }
        
        if((int)in.length() > RSA_size(rsa) - 11) // RSA_PKCS1_PADDING RSA_size(rsa) - 11
        {
            LLOGE("public_encrypt, in string to long, max encrypt text len[%d]
", RSA_size(rsa) - 11);
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }    
            
        char *encryptBuf = (char *)malloc(RSA_size(rsa) + 1);
        if(!encryptBuf)
        {
            LLOGE("malloc error
");
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }    
        memset(encryptBuf, 0, RSA_size(rsa) + 1);

        int encryptLen = RSA_public_encrypt(in.length(), (unsigned char *)in.c_str(), (unsigned char*)encryptBuf, rsa, RSA_PKCS1_PADDING);
        if (encryptLen < 0) {
            LLOGE("RSA_public_encrypt error
");
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            free(encryptBuf);
            return false;
        }

        BIO_free(bkey);
        RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        
        //base64 encode
        BIO *b64 = BIO_new(BIO_f_base64());
        BIO *bmem = BIO_new(BIO_s_mem());

        b64 = BIO_push(b64, bmem);
        
        if(BIO_write(b64, encryptBuf, encryptLen) < 0)
        {
            LLOGE("BIO_write error
");
            BIO_free_all(b64);
            free(encryptBuf);
            return false;
        }
        BIO_flush(b64);
        
        BUF_MEM *bptr = NULL;
        BIO_get_mem_ptr(b64,&bptr);    
        if(!bptr)
        {
            LLOGE("BIO_get_mem_ptr error
");
            BIO_free_all(b64);
            free(encryptBuf);
            return false;
        }
        out.assign(bptr->data, bptr->length);

        BIO_free_all(b64);        
        free(encryptBuf);

        return true;    
    }
    static bool public_decrypt(const std::string & pubKey, const std::string & in, std::string & out)
    {
        std::string publicKey;
        z_pubKeyTrans(pubKey, publicKey);        
        BIO *b64 = BIO_new(BIO_f_base64());
        BIO *bkey = BIO_new_mem_buf((void*)publicKey.c_str(), publicKey.length());
        BIO *bmem = BIO_new_mem_buf((void*)in.c_str(), in.length());
        
        if(!bkey || !b64 || !bmem)
        {
            LLOGE("error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            return false;
        }
        
        EVP_PKEY *evpKey = PEM_read_bio_PUBKEY(bkey, NULL,NULL,NULL);//pkcs8
        if(!evpKey)
        {
            printf("PEM_read_bio_PUBKEY error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            return false;            
        }        
        //RSA *rsa = PEM_read_bio_RSAPublicKey(bkey,NULL,NULL,NULL);    //pkcs1
        RSA *rsa = EVP_PKEY_get1_RSA(evpKey);
        if(!rsa){
            LLOGE("error2
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            EVP_PKEY_free(evpKey);
            return false;        
        }
        b64 = BIO_push(b64,bmem);
        std::string encryptStr;    
        char decode[256] = {0};
        int ret = BIO_read(b64,decode,sizeof(decode));
        while(ret > 0)
        {
            encryptStr.append(decode, ret);
            memset(decode, 0, sizeof(decode));
            ret = BIO_read(b64,decode,sizeof(decode));
        }
        
        //LLOGE("encrypt len[%d]
", encryptStr.length());
        
        int rsa_len = RSA_size(rsa);
        char *decryptBuf = (char *)malloc(rsa_len + 1);
        if(!decryptBuf)
        {
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            if(rsa)RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }
        memset(decryptBuf, 0, rsa_len + 1);

        int decryptLen = RSA_public_decrypt(rsa_len, (unsigned char *)encryptStr.data(), (unsigned char*)decryptBuf, rsa, RSA_PKCS1_PADDING);
        if (decryptLen < 0) 
        {
            LLOGE("RSA_public_decrypt error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            if(rsa)RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            if(decryptBuf)free(decryptBuf);
            return false;        
        }
        out.assign(decryptBuf, decryptLen);
        
        if(bkey)BIO_free(bkey);
        if(b64)BIO_free(b64);
        if(bmem)BIO_free(bmem);
        if(rsa)RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        if(decryptBuf)free(decryptBuf);    
        
        return true;    
    }

私钥加解密代码,使用不同的公钥格式要使用不同的函数读取

static bool private_encrypt(const std::string & privateKey, const std::string & in, std::string & out)
    {
        BIO *bkey = BIO_new_mem_buf((void*)privateKey.c_str(), privateKey.length());
        if(!bkey)
        {
            LLOGE("BIO_new_mem_buf error
");
            return false;
        }    
        
        EVP_PKEY *evpKey = PEM_read_bio_PrivateKey(bkey,NULL,NULL,NULL);
        if(!evpKey)
        {
            LLOGE("PEM_read_bio_PrivateKey error
");
            BIO_free(bkey);
            return false;            
        }        
        RSA *rsa = EVP_PKEY_get1_RSA(evpKey);
        //RSA *rsa = PEM_read_bio_RSAPrivateKey(bkey,NULL,NULL,NULL);
        if(!rsa)
        {
            LLOGE("PEM_read_bio_RSAPrivateKey error
");
            BIO_free(bkey);
            EVP_PKEY_free(evpKey);
            return false;
        }
        
        if((int)in.length() > RSA_size(rsa) - 11) // RSA_PKCS1_PADDING RSA_size(rsa) - 11
        {
            LLOGE("public_decrypt, in string to long, max encrypt text len[%d]
", RSA_size(rsa) - 11);
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }    
            
        char *encryptBuf = (char *)malloc(RSA_size(rsa) + 1);
        if(!encryptBuf)
        {
            LLOGE("malloc error
");
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }    
        memset(encryptBuf, 0, RSA_size(rsa) + 1);

        int encryptLen = RSA_private_encrypt(in.length(), (unsigned char *)in.c_str(), (unsigned char*)encryptBuf, rsa, RSA_PKCS1_PADDING);
        if (encryptLen < 0) {
            LLOGE("RSA_private_encrypt error
");
            BIO_free(bkey);
            RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            free(encryptBuf);
            return false;
        }

        BIO_free(bkey);
        RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        
        //base64 encode
        BIO *b64 = BIO_new(BIO_f_base64());
        BIO *bmem = BIO_new(BIO_s_mem());

        b64 = BIO_push(b64, bmem);
        
        if(BIO_write(b64, encryptBuf, encryptLen) < 0)
        {
            LLOGE("BIO_write error
");
            BIO_free_all(b64);
            free(encryptBuf);
            return false;
        }
        BIO_flush(b64);
        
        BUF_MEM *bptr = NULL;
        BIO_get_mem_ptr(b64,&bptr);    
        if(!bptr)
        {
            LLOGE("BIO_get_mem_ptr error
");
            BIO_free_all(b64);
            free(encryptBuf);
            return false;
        }
        out.assign(bptr->data, bptr->length);

        BIO_free_all(b64);        
        free(encryptBuf);

        return true;        
    }
    static bool private_decrypt(const std::string & privateKey, const std::string & in, std::string & out)
    {
        BIO *b64 = BIO_new(BIO_f_base64());
        BIO *bkey = BIO_new_mem_buf((void*)privateKey.c_str(), privateKey.length());
        BIO *bmem = BIO_new_mem_buf((void*)in.c_str(), in.length());
        
        if(!bkey || !b64 || !bmem)
        {
            LLOGE("error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            return false;
        }
        
        EVP_PKEY *evpKey = PEM_read_bio_PrivateKey(bkey,NULL,NULL,NULL);//pkcs8
        if(!evpKey)
        {
            LLOGE("PEM_read_bio_PrivateKey error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            return false;            
        }            
        RSA *rsa = EVP_PKEY_get1_RSA(evpKey);        
        //RSA *rsa = PEM_read_bio_RSAPrivateKey(bkey,NULL,NULL,NULL);    //pkcs1
        if(!rsa){
            LLOGE("error2
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            EVP_PKEY_free(evpKey);
            return false;        
        }
        b64 = BIO_push(b64,bmem);
        std::string encryptStr;    
        char decode[256] = {0};
        int ret = BIO_read(b64,decode,sizeof(decode));
        while(ret > 0)
        {
            encryptStr.append(decode, ret);
            memset(decode, 0, sizeof(decode));
            ret = BIO_read(b64,decode,sizeof(decode));
        }
        
        //LLOGE("encrypt len[%d]
", encryptStr.length());
        
        int rsa_len = RSA_size(rsa);
        char *decryptBuf = (char *)malloc(rsa_len + 1);
        if(!decryptBuf)
        {
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            if(rsa)RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            return false;
        }
        memset(decryptBuf, 0, rsa_len + 1);

        int decryptLen = RSA_private_decrypt(rsa_len, (unsigned char *)encryptStr.data(), (unsigned char*)decryptBuf, rsa, RSA_PKCS1_PADDING);
        if (decryptLen < 0) 
        {
            LLOGE("RSA_private_decrypt error
");
            if(bkey)BIO_free(bkey);
            if(b64)BIO_free(b64);
            if(bmem)BIO_free(bmem);
            if(rsa)RSA_free(rsa);
            EVP_PKEY_free(evpKey);
            if(decryptBuf)free(decryptBuf);
            return false;        
        }
        out.assign(decryptBuf, decryptLen);
        
        if(bkey)BIO_free(bkey);
        if(b64)BIO_free(b64);
        if(bmem)BIO_free(bmem);
        if(rsa)RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        if(decryptBuf)free(decryptBuf);    
        
        return true;
    }
RSA结构与EVP_PKEY结构转换
RSA *rsa = EVP_PKEY_get1_RSA(evpKey);
有一系列这样的函数,带1的是要分别释放内存的。

JAVA语言生成RSA密钥对默认编码后是PKCS8格式的
import java.util.Base64;
import java.util.HashMap;
import java.util.Map; 
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher;


public class TRsaOperation
{
    public static Map<String, String> generate_key() throws Exception
    {  
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");  
        keyPairGenerator.initialize(1024);  
        KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 

        Map<String, String> keyMap = new HashMap<String, String>();  
        keyMap.put("public", yaoBase64.getEncoder().encodeToString(publicKey.getEncoded()));  
        keyMap.put("private", Base64.getEncoder().encodeToString(privateKey.getEncoded())); 

        return keyMap;  
    }
    
    public static String public_encrypt(String pubKey, String in) throws Exception
    {
        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey.getBytes())));
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(in.getBytes());
        return Base64.getEncoder().encodeToString(result);        
    }
    
    public static String public_decrypt(String pubKey, String in) throws Exception
    {
        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey.getBytes())));
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(Base64.getDecoder().decode(in.getBytes()));
        return new String(result);
    }    
    
    public static String private_encrypt(String priKey, String in) throws Exception
    {
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(priKey.getBytes())));
        Cipher cipher2 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher2.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher2.doFinal(in.getBytes());
        return Base64.getEncoder().encodeToString(result);
    }    
    
    public static String private_decrypt(String priKey, String in) throws Exception
    {

        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(priKey.getBytes())));
        Cipher cipher2 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher2.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher2.doFinal(Base64.getDecoder().decode(in.getBytes()));
        return new String(result);
    }    
}

JAVA生成的密钥与opensll生成的密钥差异

1 直接使用Base64.getEncoder().encodeToString(publicKey.getEncoded())获取到的公钥没有开始与结束标志,没有按照64字节分行,要在openssl中使用要添加开始与结束标志,按照64字节分行(添加每64字节添加‘ ’)。

2 openssl生成的公钥在java中使用做相反的操作。

 
 
原文地址:https://www.cnblogs.com/mingzhang/p/13906418.html