指定模数与公钥指数的Javax Crypto RSA加密输出随机问题
现象成因
你调用Cipher.getInstance("RSA")时没有指定完整的「加密算法/工作模式/填充规则」,在Oracle JDK、OpenJDK等主流JDK实现中,该写法默认等价于RSA/ECB/PKCS1Padding。
PKCS1Padding 填充规则设计时就加入了随机数逻辑:加密前会在明文前拼接一段随机生成的填充字节,再整体做RSA运算。即使明文、公钥完全相同,每次加密使用的随机填充值不同,最终输出的密文自然不同。这是RSA的标准安全设计,目的是避免攻击者通过密文对比直接判断两段密文是否对应相同明文,降低明文被爆破的风险。
固定加密结果的实现方案
注意:固定加密结果会破坏RSA的抗重放、抗明文比对安全特性,仅推荐在测试、离线计算等非生产场景使用。
有两种常用实现方式:
- 方式1:指定固定随机源的填充模式
保留原有PKCS1填充规则,初始化Cipher时传入固定种子的SecureRandom实例,保证每次加密生成的填充值完全一致,不需要额外处理明文长度,修改成本最低。
代码修改示例:// 其余代码和原有逻辑完全一致,仅修改cipher初始化逻辑 // 构造固定种子的SecureRandom,种子值可自定义,只要固定不变即可 SecureRandom fixedRandom = SecureRandom.getInstance("SHA1PRNG"); fixedRandom.setSeed("自定义固定种子".getBytes()); cipher.init(Cipher.ENCRYPT_MODE, publ, fixedRandom); - 方式2:使用无填充模式
显式指定无填充的RSA算法,此时加密过程不会加入任何随机数据,相同明文和公钥加密结果必然相同。但需要你自行保证明文长度和密钥模数长度完全对齐,不足部分手动补充固定值(如全0),否则会抛出加密长度异常。
代码修改示例:// 修改Cipher初始化参数,其余逻辑需自行补充明文字节对齐处理 Cipher cipher= Cipher.getInstance("RSA/ECB/NoPadding");
内容的提问来源于stack exchange,提问作者Programmer S
相关产品推荐
相关产品推荐

