基于密码生成RSA私钥用于私密信使是否合理?
方案可行性与实现问题分析
核心思路的合理性
你的核心想法——客户端本地生成RSA密钥对,仅将公钥上传服务器,让服务器无法接触明文消息——是端到端加密的正确方向,理论上能达成服务器无法获取消息内容的目标。但你的具体密钥生成实现存在致命缺陷,完全不符合RSA的安全要求,不能直接使用。
当前代码的严重问题
- p和q必须是大素数:RSA的核心要求是p、q为两个足够大的不同素数,但你用SHA-256哈希生成的数值几乎不可能是素数,用这种参数构造的RSA密钥毫无安全性可言,任何人都能轻易破解。
- 密钥长度严重不足:SHA-256生成的哈希仅256位,就算p、q是素数,最终生成的密钥也只有512位——如今512位RSA早已被完全破解,至少需要2048位,推荐使用4096位密钥。
- 私钥参数错误:
RSA.construct的第三个参数应该是私钥的d值,而非(p-1)*(q-1)(这是欧拉函数φ(n)),你直接传入这个值会导致私钥无效,根本无法完成解密操作。
改进建议
- 正确生成标准RSA密钥对:不要手动构造p、q,直接用成熟密码库的标准方法生成符合安全要求的密钥对:
from Crypto.PublicKey import RSA # 生成2048位RSA密钥对,采用通用的65537作为公钥指数 key = RSA.generate(2048, e=65537) privateKey = key.exportKey('PEM') publicKey = key.publickey().exportKey('PEM')
- 密码派生密钥的正确方式:如果要让用户通过密码恢复密钥(比如换设备后重新生成私钥),不能直接用哈希生成RSA参数,应该用**密码派生函数(KDF)**从密码生成对称密钥,再用该密钥加密私钥后存储(本地或加密后上传服务器):
import hashlib from Crypto.PublicKey import RSA from Crypto.Cipher import AES from Crypto.Protocol.KDF import PBKDF2 from Crypto.Random import get_random_bytes password = "mysecretstring" # 生成随机盐,需和加密后的私钥一同保存 salt = get_random_bytes(16) # 用PBKDF2派生对称密钥,迭代次数建议不低于100000次 symmetric_key = PBKDF2(password, salt, dkLen=32, count=100000, hmac_hash_module=hashlib.sha256) # 生成标准RSA密钥对 rsa_key = RSA.generate(2048) private_key = rsa_key.exportKey('PEM') # 用对称密钥加密私钥,需保存的内容:ciphertext、tag、nonce、salt cipher = AES.new(symmetric_key, AES.MODE_GCM) ciphertext, tag = cipher.encrypt_and_digest(private_key)
- nonce的合理运用:服务器返回的nonce应用于后续身份验证或会话密钥协商,确保每次会话的密钥唯一,避免重放攻击。
总结
你的端到端加密核心思路是正确的,但当前的密钥生成实现完全不符合RSA安全标准,必须改用成熟密码库的标准方法生成密钥;若要绑定密码与密钥,需使用专业的KDF方案,绝不能手动构造RSA的核心参数。
内容的提问来源于stack exchange,提问作者SCcagg5
相关产品推荐
相关产品推荐

