我需要的是加密将显示在二维条码(PDF-417)中的字符串,因此当有人想扫描它时,它将无法读取。
其他需求:
它必须足够简单,以摆脱四处窥探的人,并且对于其他有兴趣获取该数据的公司而言,易于解密。他们打电话给我们,我们告诉他们标准或给他们一些简单的密钥,然后可以用于解密。
可能这些公司可以使用不同的技术,所以最好坚持一些不依赖于某些特殊平台或技术的标准。
你有什么建议?是否有一些 Java 类在实现高安全标准方面没有太多复杂性encrypt()?decrypt()
encrypt()
decrypt()
这是通过 Google 显示的第一页,所有实现中的安全漏洞让我感到畏缩,所以我发布此内容是为了为其他人添加有关加密的信息,因为它距离原始帖子已有 7 年了。 我拥有计算机工程 硕士学位 ,并花了很多时间学习和学习密码学,所以我投入了两分钱让互联网变得更安全。 另外,请注意,对于给定的情况,很多实现可能是安全的,但为什么要使用这些并可能不小心犯错误呢?除非您有特定的理由不这样做,否则请使用您可用的最强大的工具。总的来说,如果可以的话,我强烈建议使用图书馆并远离细节。 2018 年 4 月 5 日更新: 我重写了一些部分以使其更易于理解,并将推荐的库从Jasypt 更改为Google 的新库 Tink,我建议从现有设置中完全删除Jasypt 。
这是通过 Google 显示的第一页,所有实现中的安全漏洞让我感到畏缩,所以我发布此内容是为了为其他人添加有关加密的信息,因为它距离原始帖子已有 7 年了。 我拥有计算机工程 硕士学位 ,并花了很多时间学习和学习密码学,所以我投入了两分钱让互联网变得更安全。
另外,请注意,对于给定的情况,很多实现可能是安全的,但为什么要使用这些并可能不小心犯错误呢?除非您有特定的理由不这样做,否则请使用您可用的最强大的工具。总的来说,如果可以的话,我强烈建议使用图书馆并远离细节。
2018 年 4 月 5 日更新: 我重写了一些部分以使其更易于理解,并将推荐的库从Jasypt 更改为Google 的新库 Tink,我建议从现有设置中完全删除Jasypt 。
前言
我将在下面概述安全对称加密的基础知识,并指出当人们使用标准 Java 库自行实现加密时我在网上看到的常见错误。如果您只想跳过所有细节,转到Google 的新库 Tink将其导入您的项目并使用 AES-GCM 模式进行所有加密,您将是安全的。
现在,如果您想了解有关如何在 java 中加密的详细信息,请继续阅读:)
分组密码
首先,您需要选择一个对称密钥 Block Cipher。块密码是用于创建伪随机性的计算机功能/程序。伪随机性是假随机性,除了量子计算机之外没有其他计算机能够区分它和真正的随机性。块密码就像密码学的构建块,当与不同的模式或方案一起使用时,我们可以创建加密。
现在关于今天可用的分组密码算法,确保 永远不要 ,我重复 永远不要 使用DES,我什至会说永远不要使用3DES。即使是斯诺登的 NSA 版本也能够验证真正尽可能接近 Pseudo-Random 的唯一 Block Cipher 是AES 256。还存在 AES 128;不同之处在于 AES 256 在 256 位块中工作,而 AES 128 在 128 块中工作。总而言之,尽管发现了一些弱点,但 AES 128 被认为是安全的,但 256 是可靠的。
有趣的事实DES在最初成立时就被 NSA 破解了,并且实际上保密了几年。尽管有些人仍然声称3DES是安全的,但仍有不少研究论文发现并分析了3DES的弱点。
加密模式
当您采用分组密码并使用特定方案时,就会创建加密,以便将随机性与密钥结合起来,只要您知道密钥,就可以创建可逆的东西。这称为加密模式。
这是一个加密模式的示例,也是最简单的模式,称为 ECB,以便您可以直观地了解正在发生的事情:
您最常在网上看到的加密模式如下:
欧洲央行 CTR、CBC、GCM
除了列出的模式之外,还存在其他模式,研究人员一直在努力寻找新模式来改善现有问题。
现在让我们继续讨论实现以及什么是安全的。 永远不要 使用 ECB,这在隐藏重复数据方面很糟糕,如著名的Linux penguin所示。
在 Java 中实现时,请注意,如果使用以下代码,则默认设置 ECB 模式:
Cipher cipher = Cipher.getInstance("AES");
… 危险 这是一个漏洞! 不幸的是,这在 StackOverflow 和在线教程和示例中都可以看到。
随机数和 IV
针对 ECB 模式中发现的问题,创建了也称为 IV 的公告。这个想法是我们生成一个新的随机变量并将其附加到每个加密中,这样当您加密两条相同的消息时,它们就会出现不同的结果。这背后的美妙之处在于 IV 或 nonce 是公共知识。这意味着攻击者可以访问此信息,但只要他们没有您的密钥,他们就无法利用该知识做任何事情。
我将看到的常见问题是人们会将 IV 设置为静态值,就像在他们的代码中使用相同的固定值一样。这是 IV 的陷阱,当您重复一个时,您实际上会危及整个加密的安全性。
生成随机 IV
SecureRandom randomSecureRandom = new SecureRandom(); byte[] iv = new byte[cipher.getBlockSize()]; randomSecureRandom.nextBytes(iv); IvParameterSpec ivParams = new IvParameterSpec(iv);
注意: SHA1 坏了,但我找不到如何在这个用例中正确实施 SHA256,所以如果有人想对此进行破解并更新它会很棒!此外,SHA1 攻击仍然是非常规的,因为它可能需要几年时间才能破解一个巨大的集群。在此处查看详细信息。
点击率实施
CTR 模式不需要填充。
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
CBC实施
如果您选择使用 PKCS7Padding 实现 CBC 模式,如下所示:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
CBC 和 CTR 漏洞以及为什么应该使用 GCM
尽管 CBC 和 CTR 等其他一些模式是安全的,但它们会遇到攻击者可以翻转加密数据并在解密时更改其值的问题。因此,假设您加密了一条虚构的银行消息“Sell 100”,您的加密消息看起来像“eu23ng”,攻击者将一位更改为“eu53ng”,然后在解密您的消息时突然变成“Sell 900”。
为了避免这种情况,大多数互联网都使用 GCM,每次你看到 HTTPS 时,他们可能都在使用 GCM。GCM 使用哈希对加密消息进行签名,并使用此签名检查以确认消息未被更改。
由于其复杂性,我会避免实施 GCM。你最好使用谷歌的新库 Tink,因为如果你不小心重复了 IV,你会在 GCM 的情况下危及密钥,这是最终的安全漏洞。新的研究人员正在研究抗 IV 重复加密模式,即使您重复 IV,密钥也没有危险,但这尚未成为主流。
现在,如果您确实想实现 GCM,这里是一个不错的 GCM 实现的链接。但是,我无法确保安全性,或者它是否正确实施,但它会降低基础。还要注意 GCM 没有填充。
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
密钥与密码
另一个非常重要的注意事项是,在密码学方面,密钥和密码不是一回事。密码学中的密钥需要具有一定量的熵和随机性才能被认为是安全的。这就是为什么您需要确保使用正确的密码库为您生成密钥的原因。
所以你真的有两个实现,你可以在这里做,第一个是使用在这个线程上找到的代码用于 Random Key Generation。此解决方案使用安全随机数生成器从头开始创建您可以使用的密钥。
另一个不太安全的选项是使用用户输入,例如密码。我们讨论的问题是密码没有足够的熵,所以我们必须使用PBKDF2,这是一种获取密码并加强密码的算法。这是我喜欢的实现。然而,谷歌 Tink 库已经内置了所有这些,你应该利用它。
安卓开发者
这里要指出的重要一点是知道您的 android 代码是可反向工程的,大多数情况下大多数 java 代码也是如此。这意味着如果您将密码以纯文本形式存储在代码中。黑客可以很容易地找回它。通常,对于这些类型的加密,您希望使用非对称加密等。这超出了本文的范围,因此我将避免深入研究。
2013 年的一篇有趣读物:指出 Android 中 88% 的 Crypto 实现不正确。
最后的想法
我再次建议避免直接为加密实现 java 库并使用Google Tink,因为他们确实在正确实现所有算法方面做得很好。即便如此,请务必检查 Tink github 上提出的问题,漏洞会在这里和那里弹出。
如果您有任何问题或反馈,请随时发表评论!安全总是在变化,你需要尽力跟上它:)