zoukankan      html  css  js  c++  java
  • 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中使用做相反的操作。

     
     
  • 相关阅读:
    对万网主机全部使用独立Ip的猜疑
    对windows8在PC上的前景不看好
    漂浮广告代码3
    <!DOCTYPE> 标签一点点问题
    wordpress模板中用到的条件判断语句例1
    不错的漂浮广告代码2
    autoRST Automated TCP RST Exploit
    菜单项说明以提示弹出
    JIRA安装和破解
    谈组装对象以及对象生存期管理
  • 原文地址:https://www.cnblogs.com/mingzhang/p/13906418.html
Copyright © 2011-2022 走看看