RSA 非对称加密之 PKCS8 格式秘钥

本贴最后更新于 689 天前,其中的信息可能已经斗转星移

前言:前两篇博客写了RSA非对称加密的PKCS1格式秘钥的加密与解密,后面收到很多同学来问自己公司用的是PKCS8格式的秘钥,要如何加密解密。今天咱们就来解决这个问题。

一、前期准备工作

1、安装第三方库

pip install pycryptodome

2、将公钥,私钥分别存入.pem的文件

公钥文件内容如下:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI4/D
ai9lgfbeLswLcRQPubuSeoh9uQf6Ud5GC1Lr5AMwvSLgKtUdVUQG34hvswJmDdsQ
X0LpLtokKsVdD3mFNstLd4euR9FpMausvvObjQETkXC1OpI4b1x/b2qPr0S0xKtY3Ay
97lmB6LTrZ6L8AKFdI13xQjpPhv7dXTO4SbTAgMBAAECgYA/Mgwjd3b8LqlIoHL00K
HhfuQfvM8vMm41brsrBIEPAlxqwL99XpxyGiHcu6lEhM63cMT3hQC+sgnzuChYh6u
jungAAk8cFeBn6zqyTO3VHHxGiN4ElmPUhnAzicrIciVcapsWZmCGLB1Xs9KLOY4ixlI
qOZKTV9wGRpeQepOyIQJBAMkUX2cNo/ESbaSrP76UQFzg4urzcB5Cb+U1Ggz7LW
OfRs5NCPjCge+uAXc12WlG5/x23Mpjm8Dde6x+dlFgwIcCQQC1GQQYf+uwUzPVN
7FNpK/cl3UoGRFSd0EUdkEfKQYOrA3Zmvvpbr/YO0fPGekc83wOfJzYCMpxAiRG9xK
WpXZVAkEArdl1Wo4KjiVWsqZ06HsY4rR0vJpY93CNeehda5fG+Hj/KOKlvR2+ZdFV5x
GhtUnezQKfhkR0p11Wzh5Qga9bBQJAW/nhl6PYi0wmpiLL/RgobUvLJ9tbbdu9hOvud
Sn7tpXxztQlH1CtROAOv4N0XszW8/CcJCiK0Mx6qkQv/6z3pQJAG5RKpafYJRVJCIhNyt
ZFAoayZ07m+TT14I2aWErGSYuEHif1mTC5vH5bDJsYXh30TWZ4ebT78gXJhkVehZ4xLQ==
-----END PRIVATE KEY-----

私钥文件内容如下:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOPw2ovZYH23i7M
C3EUD7m7knqIfbkH+lHeRgtS6+QDML0i4CrVHVVEBt+Ib7MCZg3bEF9C6S7aJCrFXQ
95hTbLS3eHrkfRaTGrrL7zm40BE5FwtTqSOG9cf29qj69EtMSrWNwMve5Zgei062ei/ACh
XSNd8UI6T4b+3V0zuEm0wIDAQAB
-----END PUBLIC KEY-----

二、秘钥加载方式

方式一:读取.pem文件

import traceback
import base64
from Crypto.PublicKey import RSA
#Crypto模块中的pkcs1_v1_5就是pkcs8的格式的秘钥
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_Cipher
#从文件读取公钥、私钥
private_key = RSA.import_key(open('privkeyzj.pem').read())
public_key = RSA.import_key(open('pubkeyzj.pem').read())

方式二:秘钥作为参数传递

import traceback
import base64
from Crypto.PublicKey import RSA
#Crypto模块中的pkcs1_v1_5就是pkcs8的格式的秘钥
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_Cipher

class RSACrypto(object):
    #秘钥作为参数传递
    def __init__(self, private_key=None, public_key=None):
        privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\n{}\r\n-----END RSA PRIVATE KEY-----'.format(private_key).encode()
        publicKey = '-----BEGIN RSA PUBLIC KEY-----\r\n{}\r\n-----END RSA PUBLIC KEY-----'.format(public_key).encode()
        self.private_key = RSA.importKey(privateKey)
        self.public_key = RSA.importKey(publicKey)

三、分对称加密与解密

import traceback
import base64
from Crypto.PublicKey import RSA
#Crypto模块中的pkcs1_v1_5就是pkcs8的格式的秘钥
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_Cipher

class RSACrypto(object):
    def __init__(self, private_key=None, public_key=None):
        # 秘钥从文件读取
        self.private_key = RSA.import_key(open('privkeyzj.pem').read())
        self.public_key = RSA.import_key(open('pubkeyzj.pem').read())
        self.max_encode_len,self.max_decode_len=self.choice_channel()

    # 预加密,获取模值
    def choice_channel(self):
        try:
            msg='test'
            models_dict={'64': 512, '128': 1024, "512": 2048}
            pk = PKCS1_v1_5_Cipher.new(key=self.public_key)
            encrypt_text = pk.encrypt(msg.encode())  # 进行加密
            result = base64.b64encode(encrypt_text).decode()  # 加密通过base64进行编码
            decode_str = base64.b64decode(result)
            max_decode_len = len(decode_str)
            key_size=models_dict['{}'.format(max_decode_len)]
            max_encode_len=int(key_size/8-11)
            #print('初始化获取的模值:',max_encode_len,max_decode_len)
            return max_encode_len,max_decode_len
        except Exception as e:
            print(traceback.print_exc(),e)

    # 公钥加密
    # 初始化公钥--初始化加密方法--加密字符串编码encode()--加密方法加密--加密后进行base64编码---完成
    # 公钥分段加密(在用)
    def to_encrypt_section(self,msg):
        try:
            # 加密的 plaintext = max_len 最大长度是 证书key位数/8 - 11, 例如1024 bit的证书,被加密的串最长 1024/8 - 11=117,加密得到的密文长度,却恰恰是密钥的长度
            pk = PKCS1_v1_5_Cipher.new(key=self.public_key)
            if len(msg) <= self.max_encode_len:
                encrypt_text = pk.encrypt(msg.encode())  # 进行加密
                result = base64.b64encode(encrypt_text).decode()  # 加密通过base64进行编码
                return result
            else:
                encrypt_text = []
                for i in range(0, len(msg), self.max_encode_len):
                    cont = msg[i: (i + self.max_encode_len)]
                    encrypt_text.append(pk.encrypt(message=cont.encode()))
                encrypt_data = b''.join(encrypt_text)
                # base64 编码
                result = base64.b64encode(s=encrypt_data).decode()
                return result
        except Exception as e:
            print(traceback.print_exc(),e)

    #分段解密
    def to_decrypt_section(self,msg):
        try:
            decode_str = base64.b64decode(msg)
            decode_msg=PKCS1_v1_5_Cipher.new(key=self.private_key)
            #max_decode_len = 128
            if len(decode_str) <= self.max_decode_len:
                text = decode_msg.decrypt(decode_str, 'DecryptError')
                return text.decode()  # 解密出来的是字节码格式,decodee转换为字符串
            else:
                text = []
                for i in range(0,len(decode_str),self.max_decode_len):
                    cont=decode_str[i: (i + self.max_decode_len)]
                    data = decode_msg.decrypt(ciphertext=cont, sentinel='to_decrypt_section_error')
                    text.append(data)
                decrypt_text=b''.join(text)
                result=decrypt_text.decode()
                return result
        except Exception as e:
            print(traceback.print_exc(),e)

if __name__ == '__main__':
    cl=RSACrypto() #初始化秘钥
    str1='123456'
    decodestr=cl.to_encrypt_section(msg=str1)
    print("加密后:",decodestr)
    str2 = cl.to_decrypt_section(msg=decodestr)
    print("解密后:",str2)

输出
加密后 hP7xEyAGRu/MZjKncRLDzkIo39J6fcWmnKtjhrMVZxTlbWmoqZ3GSte0IUoz7/Sba83m7LjX/8cnPVRZi4K6g4uHBnven0O4QpLlQftTRRTJjWpEUjSBNRMf+IqHBCNgjdlB0W6keKla1z7UlB9WNZUC0uIwJgiFUU7ayEyluhs=
解密后 123456

四、总结

1、企业常用非对称秘钥格式PKCS1和PKCS8

2、PKCS1格式秘钥和PKCS8格式秘钥只是秘钥格式不一样,加密方式是一样的

3、加密细节详解请参考上两篇文章

回帖
请输入回帖内容 ...