这是通过 Google 和安全显示的第一页
所有实现中的漏洞让我感到畏缩,所以我
发布此内容是为了添加有关其他人加密的信息,因为它
已经7 Years从原来的帖子。我持有一个硕士在
计算机工程并花了很多时间学习和学习
密码学,所以我投入我的两分钱让互联网成为
更安全的地方。
另外,请注意,对于给定的情况,许多实现可能是安全的
情况,但为什么要使用这些并可能意外地做出一个
错误?使用可用的最强大的工具,除非您有
具体原因不去。总的来说,我强烈建议使用图书馆和
如果可以的话,远离细节。
2018 年 4 月 5 日更新:我重写了一些部分,使它们更容易理解,并更改了推荐的库Jasypt http://www.jasypt.org/ to Google 的新库 Tink https://github.com/google/tink/,我建议完全删除Jasypt http://www.jasypt.org/从现有的设置。
Foreword
我将在下面概述安全对称加密的基础知识,并指出当人们使用标准 Java 库自己实现加密时我在网上看到的常见错误。如果您想跳过所有细节,请运行至Google 的新库 Tink https://github.com/google/tink/将其导入您的项目并使用 AES-GCM 模式进行所有加密,您将是安全的。
现在,如果您想了解有关如何在 Java 中加密的具体细节,请继续阅读:)
分组密码
首先,您需要选择一个对称密钥分组密码。分组密码是一种用于创建伪随机性的计算机功能/程序。伪随机性是假随机性,除了量子计算机之外,没有任何计算机能够区分它和真正的随机性。分组密码就像密码学的构建块,当与不同的模式或方案一起使用时,我们可以创建加密。
现在关于当今可用的分组密码算法,请确保NEVER, 我重复NEVER use DES http://en.wikipedia.org/wiki/Data_Encryption_Standard,我什至会说永远不要使用3DES http://en.wikipedia.org/wiki/3DES。甚至斯诺登的美国国家安全局发布的版本也能够验证真正尽可能接近伪随机的唯一分组密码是AES 256 http://en.wikipedia.org/wiki/Advanced_Encryption_Standard。还有 AES 128;区别在于 AES 256 在 256 位块中工作,而 AES 128 在 128 位块中工作。总而言之,尽管已发现一些弱点,但 AES 128 仍被认为是安全的,但 256 却非常可靠。
有趣的事实DES http://en.wikipedia.org/wiki/Data_Encryption_Standard早在国家安全局成立之初就被美国国家安全局打破,并实际上保守了几年的秘密。尽管有些人仍然声称3DES http://en.wikipedia.org/wiki/3DES是安全的,有相当多的研究论文发现并分析了其弱点3DES http://en.wikipedia.org/wiki/3DES.
加密模式
当您采用分组密码并使用特定方案时,就会创建加密,以便将随机性与密钥相结合,从而创建只要您知道密钥即可可逆的东西。这称为加密模式。
以下是加密模式和最简单的模式(称为 ECB)的示例,以便您可以直观地了解正在发生的情况:
您在网上最常见的加密模式如下:
欧洲央行 CTR、CBC、GCM
除了列出的模式之外,还存在其他模式,研究人员一直致力于寻找新模式来改善现有问题。
Now let's move on to implementations and what is secure. NEVER use ECB this is bad at hiding repeating data as shown by the famous Linux penguin https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation.![Linux Penguin Example](https://i.stack.imgur.com/X67ZV.jpg)
在Java中实现时,请注意,如果使用以下代码,则默认设置ECB模式:
Cipher cipher = Cipher.getInstance("AES");
...危险这是一个漏洞!不幸的是,这种情况在 StackOverflow 和在线教程和示例中随处可见。
随机数和 IV
为了响应欧洲央行模式中发现的问题,创建了也称为 IV 的公告。我们的想法是,我们生成一个新的随机变量并将其附加到每个加密中,这样当您加密两条相同的消息时,它们就会不同。这背后的美妙之处在于 IV 或随机数是公共知识。这意味着攻击者可以访问此内容,但只要他们没有您的密钥,他们就无法利用这些知识做任何事情。
我会看到的常见问题是人们会将 IV 设置为静态值,就像代码中的固定值一样。这就是 IV 的陷阱,当您重复一次时,您实际上会危及整个加密的安全性。
生成随机 IV
SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
Note:SHA1 已损坏,但我找不到如何在这个用例中正确实现 SHA256,所以如果有人想破解这个并更新它那就太棒了!此外,SHA1 攻击仍然是非常规的,因为在一个巨大的集群上可能需要几年的时间才能破解。在这里查看详细信息。 https://shattered.io/
点击率实施
CTR 模式不需要填充。
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
CBC实施
如果您选择实现 CBC 模式,请使用 PKCS7Padding 执行以下操作:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
CBC 和 CTR 漏洞以及为什么应该使用 GCM
尽管 CBC 和 CTR 等其他一些模式是安全的,但它们会遇到攻击者可以翻转加密数据、在解密时更改其值的问题。假设您加密了一条假想的银行消息“Sell 100”,您的加密消息看起来像“eu23ng”,攻击者将一位更改为“eu53ng”,当解密您的消息时,它突然变成“Sell 900”。
为了避免这种情况,大多数互联网都使用 GCM,每次您看到 HTTPS 时,他们可能都在使用 GCM。 GCM 使用哈希对加密消息进行签名,并检查以验证消息是否未使用此签名进行更改。
由于 GCM 的复杂性,我会避免实施它。你最好使用谷歌的新库 Tink https://github.com/google/tink/因为如果你不小心重复 IV,你就会泄露 GCM 箱中的密钥,这是最终的安全缺陷。新的研究人员正在致力于开发 IV 重复抵抗加密模式,即使您重复 IV,密钥也不会处于危险之中,但这尚未成为主流。
现在,如果您确实想实现 GCM,这里有一个链接到一个很好的 GCM 实现 https://gist.github.com/praseodym/f2499b3e14d872fe5b4a。但是,我无法确保安全性或是否正确实施,但它奠定了基础。另请注意,GCM 中没有填充。
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
密钥与密码
另一个非常重要的注意事项是,当涉及到密码学时,密钥和密码不是同一件事。密码学中的密钥需要具有一定量的熵和随机性才能被认为是安全的。这就是为什么您需要确保使用正确的加密库来为您生成密钥。
因此,您实际上可以在这里执行两种实现,第一个是使用在这个 StackOverflow 线程用于随机密钥生成 https://stackoverflow.com/questions/18228579/how-to-create-a-secure-random-aes-key-in-java。此解决方案使用安全随机数生成器从头开始创建可供您使用的密钥。
另一个不太安全的选项是使用用户输入,例如密码。我们讨论的问题是密码没有足够的熵,所以我们必须使用PBKDF2 https://en.wikipedia.org/wiki/PBKDF2,一种获取密码并对其进行强化的算法。这里有一个我喜欢的 StackOverflow 实现 https://stackoverflow.com/a/27928435/2607972。然而,Google Tink 库内置了所有这些功能,您应该利用它。
安卓开发者
这里需要指出的重要一点是,你的 android 代码是可逆向工程的,大多数情况下大多数 java 代码也是如此。这意味着如果您在代码中以纯文本形式存储密码。黑客可以轻松检索它。通常,对于这些类型的加密,您需要使用非对称加密等。这超出了本文的范围,因此我将避免深入探讨。
An 2013年有趣的读物 https://cs.ucsb.edu/%7Echris/research/doc/ccs13_cryptolint.pdf:指出 Android 中 88% 的加密实现做得不正确。
最后的想法
我再次建议避免直接实现用于加密的 java 库并使用谷歌天克 https://github.com/google/tink/,这将为您省去麻烦,因为他们在正确实现所有算法方面确实做得很好。即使这样,也要确保检查 Tink github 上提出的问题、到处弹出的漏洞。
如果您有任何问题或反馈,请随时发表评论!
安全性总是在变化,您需要尽力跟上它:)