RSA公私鑰加密過程中,關於pkcs1和pkcs8兩種格式秘鑰加解密的問題


最近在項目中遇到RSA的公私鑰加密的事情,在選擇公私鑰類型時候遇到了問題,多方面查詢資料和驗證之后找到解決方式,再次分享一下過程。

問題背景

先說一下問題背景,對接客戶項目,用到參數傳輸時候涉及到的公私鑰加密,加密方式是RSA的加解密方式,對方項目是Java項目,Java的項目默認是使用pkcs8的公私鑰類型。我本地項目是用python的,但是python的項目中RSA加解密方式都是pkcs1格式的公私鑰,所以我這邊生成的公私鑰,給到客戶那邊客戶用不了。而且也不確定兩種格式的公私鑰加密后是否有問題,就網上找了一些處理方式。

下面說一下自己的解決路線:

1.先定好加解密的方式,對方公鑰加密,我這邊私鑰解密

2.其次是解決公私鑰格式問題,網上查了一下,pkcs1和pkcs8的格式,兩種格式的公私鑰只是算法和填充方式不一樣,那么公私鑰加解密的原理應該以一樣的。而且兩個類型的可以互轉

3.那么嘗試一下,先生成一對pkcs1的公私鑰,然后轉成pkcs8的格式,同一對秘鑰的兩種格式類型

pkcs1的公私鑰
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAIn9bvxsW/MhAO80QOcmF/tjhTRTTNlxCEsR7tx/g1YYJ0SlwIp7lFwL
JUqAzaZjyk9HQc0tOq9dIJRKoBJeMHTeejBJyOXq8OGRq//YCJqUkf+hcRv7KMRI
3iEdnGzysG7xyhzl/+JO3SAzOSiS4YixdQ/STzCU+VfTPxVkm6MhAgMBAAE=
-----END RSA PUBLIC KEY-----

-----BEGIN RSA PRIVATE KEY-----
MIICYAIBAAKBgQCJ/W78bFvzIQDvNEDnJhf7Y4U0U0zZcQhLEe7cf4NWGCdEpcCK
e5RcCyVKgM2mY8pPR0HNLTqvXSCUSqASXjB03nowScjl6vDhkav/2AialJH/oXEb
+yjESN4hHZxs8rBu8coc5f/iTt0gMzkokuGIsXUP0k8wlPlX0z8VZJujIQIDAQAB
AoGAEpoy0x68iptBZ/3wXfj5tK8m7vXn30xopM4nGFysVPfum0eJHGIqjvoFrfSN
RMghJuzhRwq45Zk1YihpLX1JNJpHbOsLDMClQQHIXN1WIC6xiKNFzDd0syNNhpPy
Das4+p8HR7wytDE8T+WR3z0y6TCi9plATpjFDJ6Yb5+avb0CRQDTCuwMVvx8iTnb
ux8Hk9Vn+meFOyyz5lGcaWssmnJmZFRQLS+awKR1xVJEJAxNDc42JH/32LvEfiez
7/UZNcszHbGw0wI9AKdioR1JBnZYpkk20kLrzFJsYUuzcKAe79qCNRHbSnIY9Yy4
GitIcW15MeeRJkIcS4Ww8YXIlBeIOC8DuwJEKbRz1zBtbtLTaze8Nwwg1Q5n3K1H
9TkjkYxHkKXoy5EyFDIJwUQme9uFmU+iWqvKv2pRG5Jp8LeZcvaNcfDueeh5T98C
PQCkvzbElDOAGBDSztp0c5FPLs00rRCVCN4auz1wrd3AH0DPmARpxYuerEKqIPr+
5sqOc3HEs37PCowB+jECRFTHpKz0nLMItN83HW+RWgqawuIs26RQh3OXhMK8Bajz
XMIcd4sqUbT4T5vSW3XxM1rHcY0qo+D+LVRRFSBv8CmqFuTy
-----END RSA PRIVATE KEY-----

 然后轉換成pkcs8格式的公私鑰

PKCS8的公私鑰
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ/W78bFvzIQDvNEDnJhf7Y4U0
U0zZcQhLEe7cf4NWGCdEpcCKe5RcCyVKgM2mY8pPR0HNLTqvXSCUSqASXjB03now
Scjl6vDhkav/2AialJH/oXEb+yjESN4hHZxs8rBu8coc5f/iTt0gMzkokuGIsXUP
0k8wlPlX0z8VZJujIQIDAQAB
-----END PUBLIC KEY-----

-----BEGIN PRIVATE KEY-----
MIICegIBADANBgkqhkiG9w0BAQEFAASCAmQwggJgAgEAAoGBAIn9bvxsW/MhAO80
QOcmF/tjhTRTTNlxCEsR7tx/g1YYJ0SlwIp7lFwLJUqAzaZjyk9HQc0tOq9dIJRK
oBJeMHTeejBJyOXq8OGRq//YCJqUkf+hcRv7KMRI3iEdnGzysG7xyhzl/+JO3SAz
OSiS4YixdQ/STzCU+VfTPxVkm6MhAgMBAAECgYASmjLTHryKm0Fn/fBd+Pm0rybu
9effTGikzicYXKxU9+6bR4kcYiqO+gWt9I1EyCEm7OFHCrjlmTViKGktfUk0mkds
6wsMwKVBAchc3VYgLrGIo0XMN3SzI02Gk/INqzj6nwdHvDK0MTxP5ZHfPTLpMKL2
mUBOmMUMnphvn5q9vQJFANMK7AxW/HyJOdu7HweT1Wf6Z4U7LLPmUZxpayyacmZk
VFAtL5rApHXFUkQkDE0NzjYkf/fYu8R+J7Pv9Rk1yzMdsbDTAj0Ap2KhHUkGdlim
STbSQuvMUmxhS7NwoB7v2oI1EdtKchj1jLgaK0hxbXkx55EmQhxLhbDxhciUF4g4
LwO7AkQptHPXMG1u0tNrN7w3DCDVDmfcrUf1OSORjEeQpejLkTIUMgnBRCZ724WZ
T6Jaq8q/alEbkmnwt5ly9o1x8O556HlP3wI9AKS/NsSUM4AYENLO2nRzkU8uzTSt
EJUI3hq7PXCt3cAfQM+YBGnFi56sQqog+v7myo5zccSzfs8KjAH6MQJEVMekrPSc
swi03zcdb5FaCprC4izbpFCHc5eEwrwFqPNcwhx3iypRtPhPm9JbdfEzWsdxjSqj
4P4tVFEVIG/wKaoW5PI=
-----END PRIVATE KEY-----

  

准備好這些之后,就開始我的驗證之路。

先用pkcs1的公鑰,用python加密,生成加密字符串

 1 import rsa
 2 import base64
 3 
 4 def create_keys():  # 生成公鑰和私鑰
 5     (pubkey, privkey) = rsa.newkeys(1024)
 6     #輸出公鑰文件
 7     pub = pubkey.save_pkcs1()
 8     with open('public.pem', 'wb+')as f:
 9         f.write(pub)
10     # 輸出私鑰文件
11     pri = privkey.save_pkcs1()
12     with open('private.pem', 'wb+')as f:
13         f.write(pri)
14 
15 #RSA加密,加密文本為base64的字符串
16 def encrypt(strs):
17     with open('public.pem', 'rb') as publickfile:
18         pub = publickfile.read()
19     pubkey = rsa.PublicKey.load_pkcs1(pub)
20     crypt_text = rsa.encrypt(strs.encode('utf8'), pubkey)
21     encrypt_str = str(base64.b64encode(crypt_text), encoding="utf-8")
22     return encrypt_str  # 加密后的密文
23 
24 #RSA解密,輸入字符為base64字符
25 def decrypt(decrypt_content):
26     with open('private.pem', 'rb') as privatefile:
27         pri = privatefile.read()
28     privkey = rsa.PrivateKey.load_pkcs1(pri)
29     strs = base64.b64decode(decrypt_content)
30     decrypt_str = rsa.decrypt(strs, privkey).decode('utf-8')  # 注意,這里如果結果是bytes類型,就需要進行decode()轉化為str
31     return decrypt_str
32 
33 
34 if __name__ == '__main__':
35     #create_keys()
36     strs = 'helloello'
37     enstr = encrypt(strs)
38     #destr = decrypt(enstr)
39     print(enstr)
40     #print(destr)

 

然后生成加密串:

Lp8gB2t8feRuV9PLEJcWVApQqrD9TJ7j7nqVoebhCgGtOZpqD+63S1w8lcSMl1dFz+h9c6I2505v1kA8bwrEDFsoJmxaukEjbDH//u8KW+HWOzkZeNGxTpN1XBoNIG3RxHPvOINVByTnfnaFY5VB0L2hqAamr53bvrxKLeVaJ4Y=

 

之后用Java環境,用轉換后的pkcs8格式的私鑰解密

package com.credits.duiba.NBZX;

import com.credits.duiba.service.BuildTool;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class RsaEncrypt {

    /**
     * 加密公鑰
     * */
    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ/W78bFvzIQDvNEDnJhf7Y4U0U0zZcQhLEe7cf4NWGCdEpcCKe5RcCyVKgM2mY8pPR0HNLTqvXSCUSqASXjB03nowScjl6vDhkav/2AialJH/oXEb+yjESN4hHZxs8rBu8coc5f/iTt0gMzkokuGIsXUP0k8wlPlX0z8VZJujIQIDAQAB";

    /**
     * 解密私鑰
     * */
   private static final String PRIVATE_KEY = "MIICegIBADANBgkqhkiG9w0BAQEFAASCAmQwggJgAgEAAoGBAIn9bvxsW/MhAO80QOcmF/tjhTRTTNlxCEsR7tx/g1YYJ0SlwIp7lFwLJUqAzaZjyk9HQc0tOq9dIJRKoBJeMHTeejBJyOXq8OGRq//YCJqUkf+hcRv7KMRI3iEdnGzysG7xyhzl/+JO3SAzOSiS4YixdQ/STzCU+VfTPxVkm6MhAgMBAAECgYASmjLTHryKm0Fn/fBd+Pm0rybu9effTGikzicYXKxU9+6bR4kcYiqO+gWt9I1EyCEm7OFHCrjlmTViKGktfUk0mkds6wsMwKVBAchc3VYgLrGIo0XMN3SzI02Gk/INqzj6nwdHvDK0MTxP5ZHfPTLpMKL2mUBOmMUMnphvn5q9vQJFANMK7AxW/HyJOdu7HweT1Wf6Z4U7LLPmUZxpayyacmZkVFAtL5rApHXFUkQkDE0NzjYkf/fYu8R+J7Pv9Rk1yzMdsbDTAj0Ap2KhHUkGdlimSTbSQuvMUmxhS7NwoB7v2oI1EdtKchj1jLgaK0hxbXkx55EmQhxLhbDxhciUF4g4LwO7AkQptHPXMG1u0tNrN7w3DCDVDmfcrUf1OSORjEeQpejLkTIUMgnBRCZ724WZT6Jaq8q/alEbkmnwt5ly9o1x8O556HlP3wI9AKS/NsSUM4AYENLO2nRzkU8uzTStEJUI3hq7PXCt3cAfQM+YBGnFi56sQqog+v7myo5zccSzfs8KjAH6MQJEVMekrPScswi03zcdb5FaCprC4izbpFCHc5eEwrwFqPNcwhx3iypRtPhPm9JbdfEzWsdxjSqj4P4tVFEVIG/wKaoW5PI=";
    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /** */
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /** */
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;


    public static void main(String[] args) throws Exception {
     String ss2 = "FlR/doGGhzsry2zGDfaYWxIL5fmMiIvVIktAGSRgYSLpZ26IoXcYAm6rC1jGR3d3UJESFrsHz17lxujvZHAgKpfMziNw0ADWcney3AGVlQ0B7hW5jLSiE3q+NQ3xJokfmeT9XPHM0stHd4n+57jYKxrGFqjTsLzjNzl9+4wpxc0=";
        System.out.println("解密= "+decrypt( ss2,PRIVATE_KEY ));


    }

    /**
     * RSA公鑰加密
     *
     * @param str       加密字符串
     * @param publicKey 公鑰
     * @return 密文
     * @throws Exception 加密過程中的異常信息
     */
    public static String encrypt(String str, String publicKey) {
        String result = "";
        try {
            // 將Base64編碼后的公鑰轉換成PublicKey對象
            byte[] buffer = Base64.decodeBase64(publicKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            PublicKey rsaPublic = keyFactory.generatePublic(keySpec);
            // 加密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, rsaPublic);
            byte[] inputArray = str.getBytes();
            int inputLength = inputArray.length;
            System.out.println("加密字節數:" + inputLength);
            // 標識
            int offSet = 0;
            byte[] resultBytes = {};
            byte[] cache = {};
            while (inputLength - offSet > 0) {
                if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);
                    offSet += MAX_ENCRYPT_BLOCK;
                } else {
                    cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                    offSet = inputLength;
                }
                resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
                System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
            }
            result = Base64.encodeBase64String(resultBytes);
        } catch (Exception e) {
            System.out.println("rsaEncrypt error:" + e.getMessage());
        }
        return result;
    }

    /**
     * RSA私鑰解密
     *
     * @param str        加密字符串
     * @param privateKey 私鑰
     * @return 銘文
     * @throws Exception 解密過程中的異常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception {
        byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = inputByte.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 對數據分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(inputByte, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(inputByte, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        String result = out.toString();
        out.close();

        return result;
    }

}

  驗證之后,可以正常,說明可以,不再另行測試

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM