rsa不对称加密使用总结

963 阅读2分钟

为什么要使用Rsa

在前后端交互时,敏感信息需要加密,因为需要选择一种算法。那么要采用什么算法?

  • md5,对称加密,密钥需要被打包前端工程中,存在泄漏的风险;此外,md5加密不能得到原始的明文,对于要得到原始明文的需求不符合
  • rsa,非对称加密,前端使用公钥加密,后端使用私钥解密;不存在泄漏风险。

实战运用Rsa

生成rsa密钥对

# 生成私钥
openssl genrsa -out live_rsa_private_key.pem 2048

# 生成公钥
openssl rsa -in live_rsa_private_key.pem -pubout -out live_rsa_public_key.pem

前端加密

安装加密模块

npm i jsencrypt

加密明文

import JSEncrypt from 'jsencrypt'

PublicKey = `MFwwDQYJKoZIhvcNAQEBBQADSwAwSslsld==`
const encrypt = new JSEncrypt()
encrypt.setPublicKey(PublicKey)

const raw_password = "123456"
const password = encrypt.encrypt(raw_password)

后端解密

设置私钥环境变量

image-20211231165403778

安装rsa依赖包

pip install rsa

读取私钥并解密

import base64
import binascii
import os

import rsa

from rsa import PrivateKey

# 自定义的公共模块
from common.exceptions import DecryptFailed, EncryptError

# 从环境变量中读取私钥
def read_private_key_from_env() -> PrivateKey:
    sep = '-----'
    # PRIVATE_KEY 环境变量名
    raw_key: str = os.getenv('PRIVATE_KEY')
    if not raw_key:
        raise ValueError('Private key not found in environment variable.')
    private_key_str_list = raw_key.split(sep=sep)
    if len(private_key_str_list) != 5:
        raise ValueError('Invalid private key format')
    _, begin, private_key_value, end, _ = private_key_str_list
    # reformat the key
    """
-----BEGIN RSA PRIVATE KEY-----
xxx
-----END RSA PRIVATE KEY-----
    """
    parsed_key = '\n'.join([f'{sep}{begin}{sep}', private_key_value.replace(" ", ""), f'{sep}{end}{sep}'])
    return PrivateKey.load_pkcs1(parsed_key.encode())

# 传入公钥加密后的字段和私钥
# 返回解密后字段
def decrypt(encrypted: str, pri_key: str) -> str:
    """Decrypts a message using the private key.
    """
    try:
        cipher_text: bytes = base64.b64decode(encrypted)
        b: bytes = rsa.decrypt(cipher_text, pri_key)
        s = b.decode()
        return s
    except rsa.pkcs1.DecryptionError:
        raise DecryptFailed(message='Password/token decrypt failed.')
    except binascii.Error:
        raise EncryptError(message='Password/token encrypted string should be base64 encoded')
        

Rsa“陷阱”

加密长度限制

image-20211231170031004

  • 加密长度为53明文,成功

    image-20211231170128168

  • 加密长度为54的明文,失败

    image-20211231170222452

经过查阅资料得知,RSA加密算法对明文长度是有限制。

具体计算公式:加密公钥/8 - 11 = 最长加密明文长度

套入公式,512bit支持的最长明文长度是:512/8 - 11 = 53

也就是说512bit的公钥,最长只能加密长度为53的明文。

但如果超过了53,怎么办?

  • 把公钥的长度增大,例如变长到2048,那么明文最长就能支持到245,但也会增加一些解密性能的损耗

那长度245还是还是不够?

  • 分段加密,把明文按照245长度切分为多段,然后再分别加密再拼接。因为加密后的明文是固定长度的,解密的时候,按照固定长度切割,分段解密即可

总结

  • 使用Rsa算法解密时,需要注意明文的长度,超过限制时,可以增加公钥的位数和分段解密解决
  • 目前512bit的加密已经不安全,推荐使用1024bit以上的公钥,但也不宜过大,2048bit已经足够安全,否则会给解密带来更大的压力