通用技术 rsa 不对称加密使用总结

花菜 · 2022年01月04日 · 最后由 花菜 回复于 2022年01月09日 · 3452 次阅读

为什么要使用 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-20220105103427682

安装 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 已经足够安全,否则会给解密带来更大的压力
共收到 5 条回复 时间 点赞

有个图,丢了么

回复

哪个位置?

花菜 回复

在我这儿看,四张图都是 png-123456....,显示不到图片

提一点:MD5 不是对称加密
你自己都写了:“md5 加密不能得到原始的明文”
这还能叫对称加密?

lazyBoy 回复

嗯,md5 应该叫不可逆加密。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册