在密文为公共的Java中加密消息的最佳方式



我正在用Java编写一个应用程序,在该应用程序中,用户必须能够共享加密消息,并且通信仅通过一个所有数据都公开可见的数据库进行。

要求大致如下:

  • 每个用户都可以向公共数据库发布一些信息(例如公钥),但只能发布一次
  • 其他用户必须能够为目标用户加密消息并在同一数据库上公开发布
  • 预期收件人必须能够解密邮件,但其他用户都不能解密
  • 加密必须足够强大,任何看似合理的暴力计算都不应该能够解密消息(现在或将来)
  • 消息的长度是任意的,但通常很小(比如短电子邮件、推特等)
  • 必须易于在常规Java中实现(如果需要,像BouncyCastle这样的库也可以)
  • 用户已经拥有用于数字签名的Ed25519密钥对(如有必要)

什么加密算法或算法组合最适合满足这些要求?我假设某种形式的非对称加密算法,每个用户都有一个公钥/私钥对,但欢迎其他想法。我肯定想避免";滚动您自己的加密货币";不过陷阱。。。。

您(几乎)总是推出自己的协议。这通常就是黑客的所在。

现在,如果你要推出自己的算法(就像在中一样,你可以避免,比如说,AES-256,并自己写一些东西。我们只会用"OhWowThisIsTheBestSecurityEvar"的重复应用程序对每个字节进行异或,这就像一个一次性的pad对,无法破解!-这种想法就是整个"不要推出你自己的加密货币"模因的意义所在。不要这样做。

即使你使用现成的"协议",也很容易把它搞砸并造成漏洞。协议端(如何使用加密算法)本质上不容易抽象为一个单一的、难以滥用甚至不可能滥用的预构建库。

所以,滚你自己的吧。协议即

这在这里看起来几乎微不足道,但事实并非如此。基本工作是使用公共/私有密钥加密,以通常的方式,使用对称加密(例如AES-256)加密消息,生成随机IV随机密钥,并将两者存储在DB中,但密钥是加密存储的-使用公共/私人密钥加密进行加密。

从本质上讲,这足以满足您的需求。但是,重放攻击呢?可能过于热心或难以置信,但如果我能把东西写进你的数据库呢?我可以回放消息:存储完全相同的加密字节球,但具有不同的时间戳,你会认为这是真实的。

这正是其中一个协议问题:如果将时间戳、发件人等所有都包含在要加密的blob内,这会有所帮助-你希望重播攻击是无害的,通常,如果消息(包括元数据)完全相同,它应该是。也许吧。通常这取决于用户的期望以及他们使用它的目的。毕竟,没有完美的加密货币。但是,如果这是不可接受的,也有解决方案,尽管简单的方法只是确保没有人对数据库具有原始SQL级别的写访问权限。

如果你的系统被"黑客入侵",它几乎总是在第二级的"协议"位。我可以打电话给您的服务台并对用户进行个性化设置吗?我可以说我丢了密码,然后邮寄一个新密码给我,然后"直接"破解用户的电子邮件吗?我可以在他们的电脑里放一个键盘记录程序吗?也许在停车场周围乱扔一些装有RAT蠕虫的U盘;一个专门为找到他们的密钥文件而编写的RAT蠕虫,在输入该密钥文件的密码时抓住他们,并将其全部发送给我?没有一个"现成的java库"可以保护您免受这些攻击。你不能在"我真的不知道我在做什么,但我至少知道我不知道,所以我会确保找到一个社区和专家推荐的图书馆,并尽我所能遵循它的手册,我肯定会没事的!"-一种时尚。如果你认真对待,就不会。

你可能应该使用的一些算法:

  • BouncyCastle支持ElGamal,一种公钥/私钥加密方案。这个想法是所有用户都有一个公钥和私钥;服务器知道公钥(以及所有按需用户;你的服务器是他们的交换所,必须保证真相,也就是说,如果你去:"这是用户Foo的公钥",你就保证这是真的,并且可能保证用户Foo在你网站上的个人信息是正确的他们他们用护照表明身份吗?什么私钥只有他们知道。您需要手动推出某种无效方案。也许用户可以指定其他一些用户,然后他们就有权使自己的密钥无效。这个想法是,如果用户觉得他们的私钥被泄露了,他们会要求他们的一个好友登录并向系统进行身份验证,并告诉系统将你的公钥标记为不再有效,无法进行任何进一步的通信。

  • 请注意,如果您想将Ed25519密钥对用于上述担保系统,则必须找到使用该密钥对的方法。

  • 使用AES-256和您的平面jane基本new SecureRandom()为您想要存储在系统中的每个消息生成一个密钥。要存储消息,您需要获取数据,生成随机密钥,使用该密钥和AES-256算法加密数据,存储加密数据,然后使用ElGamal和用户的公钥加密密钥,并存储该密钥。为了解密这些数据,用户获取(用他们的公钥加密的)密钥数据(可以是公共的)和加密的数据(也是公共的),并且可以通过首先使用他们的私钥+ElGamal来导出随机生成的AES-256密钥,然后使用它来撤消他们端的作业。你不会用ElGamal加密整个消息;这很慢,而且不是常见的方法。AES-256速度极快。但对称。除了算法(将是AES-256)外,您还需要"块模式"one_answers"填充模式"进行加密。块模式可能应该是GCM;您可以阅读CBC;这已经过时了(更糟、更慢)。绝对不要选择欧洲央行,这是直接不安全的。像往常一样,划水可能并不重要,取决于很多因素。

  • 你没有提到签名。如果用户";Foo";想要向用户"发送消息;条形图";在某种程度上,除了巴尔,没有人能读到它,他们所要做的就是以上。但如果他们这样做了;条形图";完全不知道是谁发送的。GCM有一些内置的MAC支持,这就是你需要标记消息的方式,发送者可以证明他们实际上是发送者,也可以标记日期和时间,尽管这并不容易;基本上,作为服务器,你会在任何消息上标记"我,服务器,法令,你必须相信我,这在这个时间点存在于数据库中,并且最近出现;不管怎样。已签名,服务器"。

这将为您提供一些术语(MAC、GCM、AES-256、ElGamal、Bouncy Castle、签名等),以便在互联网上搜索和阅读。

听起来您正在开发一个聊天系统。

要满足您的要求,您需要将两个加密系统结合起来。

第一个是Diffie-Hellman密钥交换-简而言之:各方生成一个私钥/公钥对。公钥存储在服务器上。如果我试图向Bob发送消息,我正在使用您的数据库";Bob"并获取他的公钥。接下来,我生成一个";共享秘密";使用我的私钥和Bob的公钥,这个共享密钥通常有32字节长。

现在,第二阶段开始了——我正在用AES算法加密我的消息(最好的算法可以是"GCM"模式),并将加密的消息(编码为Base64字符串)保存在您的公共数据库中(当然,任何提示对方是我)。

第三阶段:Bob从Michael那里得到了加密的消息。现在Bob正在数据库中搜索Michael的公钥,用他(Bob)的私钥和Michael的公钥构建共享密钥。某种魔法会发生——共享的秘密与我用于加密的密钥相同。现在Bob可以解密我的消息了。

请注意:小心风险,因为如果Bob丢失了他的私钥(可能存储在他偷来的智能手机上),他将不再为他阅读任何信息,因此需要备份他的私钥。

最新更新