小编典典

如何在 Java 中加密字符串

all

我需要的是加密将显示在二维条码(PDF-417)中的字符串,因此当有人想扫描它时,它将无法读取。

其他需求:

  • 不应该复杂
  • 它不应包含 RSA、PKI 基础设施、密钥对等。

它必须足够简单,以摆脱四处窥探的人,并且对于其他有兴趣获取该数据的公司而言,易于解密。他们打电话给我们,我们告诉他们标准或给他们一些简单的密钥,然后可以用于解密。

可能这些公司可以使用不同的技术,所以最好坚持一些不依赖于某些特殊平台或技术的标准。

你有什么建议?是否有一些 Java 类在实现高安全标准方面没有太多复杂性encrypt()decrypt()


阅读 60

收藏
2022-08-17

共1个答案

小编典典

这是通过 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
所示。Linux企鹅示例

在 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 上提出的问题,漏洞会在这里和那里弹出。

如果您有任何问题或反馈,请随时发表评论!安全总是在变化,你需要尽力跟上它:)

2022-08-17