Java 默认加密/AES 行为

Posted

技术标签:

【中文标题】Java 默认加密/AES 行为【英文标题】:Java default Crypto/AES behavior 【发布时间】:2011-09-09 15:00:48 【问题描述】:

有谁知道默认的 Java 加密行为是干什么用的:

SecretKeySpec localSecretKeySpec = new SecretKeySpec(arrayOfByte, "AES");
Cipher localCipher = Cipher.getInstance("AES");

具体来说,我希望了解这些类如何生成 IV,以及仅指定“AES”时的默认加密模式是什么。谢谢。

【问题讨论】:

不要引用我的话,但这很容易取决于提供者。您确实希望始终指定操作模式和填充算法。不这样做会导致很多问题...... 你真的能接受这些答案之一吗?你最近的问题是不久前的,所以你应该还在。 【参考方案1】:

这些细节是特定于提供商的,依赖默认模式和填充可能非常危险。如果您对当前与 Java 捆绑的默认提供程序使用的值感兴趣,您将不得不寻找相关算法的源代码。例如,它用于 RSA 算法的默认值是here。此外,Java™ Cryptography Architecture (JCA) Reference Guide 有相当多的信息可以回答你们中的一些其他问题。

【讨论】:

【参考方案2】:

对于 Oracle JDK 7(已测试),AES 的默认密码是 AES/ECB/PKCS5Padding。 Java 安全文档没有提到这一点(http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#algspec),必须做一些 JUnit 测试才能找到.

【讨论】:

我可以确认,当仅请求 AES 时,1.6.0_31 也使用 AES/ECB/PKCS5Padding。通过加密约 10MB 的 /dev/urandom 各种组合进行测试。 我已经搜索了好几个小时了!谢谢! @Jesse - Cipher.getAlgorithm() 应该返回您正在使用的内容。请参阅 Java 的 Standard Algorithm Name Documentation。 非常感谢您。几个小时以来,我一直在寻找解决方案。如果你想在 C# 中解密用 Java 加密的东西,不要忘记将块大小设置为 128,因为 Java 遵循特定的 AES 标准。 @jww Cipher.getAlgorithm() 在这样请求时仍返回“AES”(OpenJDK 11)。变量com.sun.crypto.provider.CipherCore.cipherpadding 揭示了执行doFinal 时的实际设置。【参考方案3】:

详细信息因提供商而异。 JCA Reference Guide 表示:

(创建密码对象)如果未指定模式或填充,则使用模式和填充方案的特定于提供程序的默认值。例如,SunJCE 提供程序使用 ECB 作为默认模式,PKCS5Padding 作为 DES、DES-EDE 和 Blowfish 密码的默认填充方案。这意味着对于 SunJCE 提供程序:Cipher.getInstance("DES") 和 Cipher.getInstance("DES/ECB/PKCS5Padding") 是等效的语句。

我将始终使用完整的形式(算法/模式/填充),不仅因为我认为在实现中省略此类“细节”是不好的做法,而且还因为实现了独立于所选提供者的密文(通常为存储/传输加密,然后无法确定稍后/另一端将使用相同的提供者)。

【讨论】:

【参考方案4】:

这取决于提供者。不同的提供者可能有不同的默认参数。这是 Java 8 的链接。

https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#ciphertrans

javax.crypto.Cipher.getInstance(String transformation) 工厂 方法使用以下形式的转换生成密码 算法/模式/填充。如果省略模式/填充,则 SunJCE 和 SunPKCS11 提供者使用 ECB 作为默认模式和 PKCS5Padding 作为许多对称密码的默认填充。

建议使用完全指定 算法、模式和填充,而不是依赖默认值。

注意:ECB 适用于单个数据块,并且可以 并行化,但一般不应用于多个块 数据。

因此,您不应只使用 AES,而应指定模式和填充。此外,虽然 getInstance 方法可以为提供者提供另一个参数,但不建议这样做,因为

应用程序与可能不可用的特定提供程序绑定 关于其他 Java 实现

【讨论】:

这应该是公认的答案,因为它链接到文档中提到它的确切位置。不幸的是,我没有检查所有答案,所以我自己花了一段时间才找到那段。它在 Java 6 文档版本中不存在,但自 Java 7 以来就存在。

以上是关于Java 默认加密/AES 行为的主要内容,如果未能解决你的问题,请参考以下文章

[转]AES加密遇到的问题

使用 aes_256_cbc 密码加密时的默认 IV 是啥?

Java 环境下使用 AES 加密的特殊问题处理

默认情况下启用 AES-NI 内在函数?

如何使用 AES 加密创建 Java 密钥库 (.jks) 文件

Java AES/GCM/NoPadding 加密在 doFinal 之后不会增加 IV 的计数器