我应该使用哪些Java加密算法?

12
我正在开发一个需要加密存储二进制信息的程序。不幸的是,我似乎找不到一个资源来解释哪些加密方案最适合不同的应用程序。
由于加密很复杂,而我又不是专家,所以我决定使用一个称为Jasypt的库,该库包装了Java内置的加密函数。为了确定可用的算法,我编写了一些单元测试。
第一个测试调用Jasypt的AlgorithmRegistry.getAllPBEAlgorithms()函数,并列出所有可用的加密算法:
PBEWITHHMACSHA1ANDAES_128
PBEWITHHMACSHA1ANDAES_256
PBEWITHHMACSHA224ANDAES_128
PBEWITHHMACSHA224ANDAES_256
PBEWITHHMACSHA256ANDAES_128
PBEWITHHMACSHA256ANDAES_256
PBEWITHHMACSHA384ANDAES_128
PBEWITHHMACSHA384ANDAES_256
PBEWITHHMACSHA512ANDAES_128
PBEWITHHMACSHA512ANDAES_256
PBEWITHMD5ANDDES
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
PBEWITHSHA1ANDRC2_128
PBEWITHSHA1ANDRC2_40
PBEWITHSHA1ANDRC4_128
PBEWITHSHA1ANDRC4_40

在运行时,如果您尝试使用某种算法,但该算法由于某些原因不受支持或违反了Java的加密规则,则Jasypt会抛出EncryptionOperationNotPossibleException异常。有趣的是,如果我尝试使用每个“可用”的算法来加密然后解密一些任意数据,并仅打印不抛出该异常的算法,我会得到这个精简列表:
PBEWITHMD5ANDDES
PBEWITHSHA1ANDDESEDE
PBEWITHSHA1ANDRC2_128
PBEWITHSHA1ANDRC2_40
PBEWITHSHA1ANDRC4_128
PBEWITHSHA1ANDRC4_40

可用算法的列表可以通过引入BouncyCastle JCE并执行Security.addProvider(new BouncyCastleProvider())进行注册来扩展。 如果我在执行此操作后重复之前的测试,则可以获得更多的算法选择:
PBEWITHMD2ANDDES
PBEWITHMD5AND128BITAES-CBC-OPENSSL
PBEWITHMD5AND192BITAES-CBC-OPENSSL
PBEWITHMD5AND256BITAES-CBC-OPENSSL
PBEWITHMD5ANDDES
PBEWITHMD5ANDRC2
PBEWITHSHA1ANDDES
PBEWITHSHA1ANDDESEDE
PBEWITHSHA1ANDRC2
PBEWITHSHA1ANDRC2_128
PBEWITHSHA1ANDRC2_40
PBEWITHSHA1ANDRC4_128
PBEWITHSHA1ANDRC4_40
PBEWITHSHA256AND128BITAES-CBC-BC
PBEWITHSHA256AND192BITAES-CBC-BC
PBEWITHSHA256AND256BITAES-CBC-BC
PBEWITHSHAAND128BITAES-CBC-BC
PBEWITHSHAAND128BITRC2-CBC
PBEWITHSHAAND128BITRC4
PBEWITHSHAAND192BITAES-CBC-BC
PBEWITHSHAAND2-KEYTRIPLEDES-CBC
PBEWITHSHAAND256BITAES-CBC-BC
PBEWITHSHAAND3-KEYTRIPLEDES-CBC
PBEWITHSHAAND40BITRC2-CBC
PBEWITHSHAAND40BITRC4
PBEWITHSHAANDIDEA-CBC
PBEWITHSHAANDTWOFISH-CBC

很不幸,我现在不知道这些算法中哪一个最适合我的应用程序。我有一种感觉,AES是正确的选择,并且看起来PBEWITHSHA256AND256BITAES-CBC-BC是具有最长密钥长度的AES实现,但我不知道去哪里确认这个猜想。
这些方案中哪些提供了最高的安全级别,哪些存在明显的安全问题?
编辑:我希望能够分发我的代码,而不需要结束用户安装无限制密码文件,因为这几乎肯定超出了不那么精通技术的用户的能力范围。我真正想要的是在不使用无限制强度管辖区文件的情况下获得最强的加密。

不要使用封装库来做出所有正确的决策。请阅读http://blog.slaks.net/2015-11-18/common-crypto-pitfalls/。 - SLaks
1
我已经修改了问题,直接解释哪种方案提供“最高安全级别”。要求离线解释/指导是不相关的,而要求“最佳”则是主观的。这两者都是关闭问题的原因。 - Maarten Bodewes
你不需要使用库,使用Java API也不是太难。这是我的示例 - https://gist.github.com/zhong-j-yu/9d23c850e580d60ddd46 - ZhongYu
1
@bayou.io 是的,你需要。因为你的代码存在漏洞,它没有使用常规的消息认证码(MAC),而是使用了加密哈希。如果你将其用于身份验证,可能会容易受到填充预言攻击的威胁。不要使用注释作为答案,特别是因为我们无法对其进行投票。 - Maarten Bodewes
1
@bayou.io 你也在使用ECB模式。你以前有创建过加密包装库吗?如果没有,请不要将它们发布为答案。 - Maarten Bodewes
1
@MaartenBodewes -- 如果我没有先暴露我的无知,我怎么能向您学习呢? :) - ZhongYu
1个回答

9
首先,您应该从Oracle*安装无限制的加密文件。这样做后,您应该减少EncryptionOperationNotPossibleException,并且更高的安全级别应该变得可用。
此外,为了实现最高级别的加密,我根本不会使用JaSypt,因为它似乎没有提供任何密文的完整性检查或身份验证。对于仅保密性来说,这似乎并不重要。但在实践中,您需要根据威胁模型进行检查。
如果您决定使用JaSypt(我个人不喜欢),您应该选择PBEWITHHMACSHA512ANDAES_256作为最高级别可能性。确保您理解PBKDF2和工作因素(迭代次数,例如setKeyObtentionIterations
您不需要Bouncy Castle。AES被认为是安全的;所有Bouncy Castle所做的事情 - 对于使用JaSypt的示例 - 就是添加模糊密码。在上面的列表中,除了AES之外的所有内容都比AES不安全。
* 这是一个旧答案,通常不再需要无限制的加密扩展

问题在于,我希望能够分发我的代码,而不需要最终用户安装无限制的加密文件,因为这几乎肯定超出了不那么精通技术的用户的能力范围。我真正想要的是最强大的加密,而不使用无限制强度管辖区文件。也许我应该编辑问题来表达这一点。 - MusikPolice
是的,你应该这样做。你使用的运行时环境没有默认提供AES 128算法吗? - Maarten Bodewes
我使用 Oracle 的标准 Java 8 JDK 运行程序。它有可用的 AES 128 算法,但实际使用时总是出现异常。 - MusikPolice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接