我正在开发一个Web应用程序,使用户能够通过私人消息进行通信,这只是整个系统的一部分。开发过程中的主要重点是保护用户的隐私,我认为这应该是每个软件开发人员的主要职责之一。特别是当您考虑到过去几年中有害的数据泄漏时。

我已经阅读了很多有关端到端加密的文章,而著名的消息传递应用程序(如Whatsapp则使用端到端)加密以保护其用户隐私。我想使我的服务器和应用程序对正在传输的消息的内容了解为零。

当您在用户设备上安装了应用程序时,我从理论上知道如何存储和保护私有数据。用户设备上的按键。但是在我的特殊情况下,用户设备上不会安装任何可执行文件。他们正在通过浏览器和安全的https连接访问Web应用程序。这个事实使我很头疼。我什至无法想象如何在此客户端环境中永久且安全地存储私钥。因此,我考虑过将密钥以安全的方式存储在服务器上,但这是我的矛盾,当考虑到我必须假定潜在的对手接管了服务器,数据库等的控制权时,...整个机器都在运行,并且“关键存储库已打开”。

前几天,我想在StackOverflow上提问,如果您想了解更多有关我绝望的方式的信息。保护应用程序机密,例如加密密钥和其他敏感数据。经过长时间的讨论,我被引荐到这个StackExchange密码学论坛。

所以我想问您而不关注任何特殊的编程语言:“在何处以及如何将私钥存储在Web应用程序中以进行私人消息传递使用网络浏览器?”。提前谢谢!

评论

如果您绑定到浏览器,那么对于用户而言,实际上没有任何好的和可理解的解决方案。您可以使用客户端证书,但是我怀疑您可以使用它们来加密/解密TLS握手之外的内容(客户端证书的UI也很烂)。就安全性而言,最好的选择是浏览器扩展(但这会带来其他问题)。问题还在于如何将加密代码提供给用户? JS?然后,您也可以保留密钥,就像理论上那样,可以使用恶意JS转储用户秘密。

顺便说一句:欢迎来到Cryptography.SE :)也许看看一个有点相关的项目:Mailvelope(浏览器中的PGP存在类似问题)。当然:+1实际询问“我有一个浏览器,想做E2E,但我怎么能呢?”看起来对其他人具有很大的可重用性。而且我还可以问:这应该是仅实时的还是“异步”通信?

@SEJPM感谢您的欢迎:)我开始思考如何解决此问题而又不产生比浏览器和https支持更多的系统要求。我也考虑过使用浏览器扩展,但这对于我的大多数用户来说不是一个可接受的解决方案。客户端JavaScript代码必须经过认证,不能像您已经提到的那样被更改,这真令人讨厌,以至于很难通过标准工具(例如浏览器)来实现良好的安全性以保护用户隐私,因此应该已经存在解决方案[..]也许我监督了...?

我认为在考虑加密之前,您必须解决的问题是确保加密的代码安全交付。这意味着您必须使用服务器提供的代码(因为要最大程度地减少用户负担),必须执行代码验证,必须确保如果服务器受到破坏,则代码不会获得机密,并且必须确保该代码不能被篡改。

存储密钥的最安全方法是根本不存储密钥;为每个消息使用从每个对话的不同密钥派生的不同密钥,以最大程度地保护隐私。

#1 楼

您可能需要考虑使用Web加密API在Web浏览器中进行客户端加密。然后,您可以使用webcrypto api创建密钥对,并使用Indexed DB存储存储包含用户私钥且.extractable属性设置为false的CryptoKey对象。这样,私钥只能用于在浏览器中解密和/或签名消息,而不能被读取(即使通过浏览器中的客户端脚本进行读取)。

有关更多信息,请参见:


https://pomcor.com/2017/06/02/keys-in-browser/
https://www.w3.org/TR/WebCryptoAPI /
https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Crypto_API
https://www.w3.org/TR/IndexedDB/
https: //www.boxcryptor.com/zh-CN/blog/post/building-an-app-with-webcrypto-in-2016/
https://gist.github.com/saulshanabrook/b74984677bccd08b028b30d9968623f5
https ://blog.engelke.com/2014/09/19/saving-cryptographic-keys-in-the-browser/


#2 楼

提到我提出的问题:“在Web应用程序中何处以及如何将私钥存储在Web浏览器中以进行私人消息传递?”这意味着我想找到一种防弹机制,以永久存储和保护Web浏览器中的公钥,以进行端到端的加密消息传递,而无需执行以下操作:


web浏览器
HTTPS支持
javascript
浏览器中的永久存储

我不得不遗憾地接受,我的问题没有答案(绝对安全)。

我想通过提供评论部分讨论的摘要来证明此声明的正确性,并参考一些外部资源来了解目标环境中的薄弱环节。



将私钥存储在Cookie中-这种方法非常简单,但也涉及一些安全问题。首先,如果“请求的URL在cookie中定义的相同域和路径内”,则在每个http请求内发送一个cookie。私钥。客户端与服务器之间的通信通过HTTPS进行保护,但是如果服务器受到威胁,则私钥就会泄漏。与在Cookie中存储机密有关的下一个问题是,如果Cookie过期或通过浏览器设置或用户本人删除了,则私钥将永远丢失。

存储加密的私钥怎么办?在Cookie中以及加密的私钥在安全的客户端数据存储设备上的备份?

好吧,这是一个选择。假设用户可以使用AES加密私钥,并在用户脑海中记住一个强密码。然后,即使Cookie在运行受到破坏的应用程序的情况下通过安全线路传输到服务器,对手也无法使用加密密钥完成任何操作。而且,如果Cookie过期或从浏览器中删除,则用户可以通过其外部备份将其还原。在撰写本文时,我们可以认为我们已经解决了问题。我将向您展示我们不幸的是,但是,在为您提供生动的示例之前,我在研究过程中发现了一个网站(但不幸的是,我丢失了URI),为什么即使加密和解密也要传输私钥?越过安全线根本不合理。想象一下,您已经为自己制作了一些非常私人的图片,您已经使用强大的密码和安全的加密机制对这些图片进行了加密,任何人都可以在接下来的几百万年内解密这些图片,但是您不会将这些加密的文件发送到您的朋友,因为您会对其中一位朋友解密图片的风险感到不安。将这些加密的私钥传输到服务器时,您还应该感到不舒服。



客户端javascript加密-在编写此答案时,有不同的javascript加密库,其中最高级的是“斯坦福Javascript加密库(SJCL)”,该库可用于加密数据,例如本例中的私钥。有关使用javascript进行客户端加密的问题是,攻击者可能通过受感染的服务器或跨脚本攻击来注入恶意javascript代码。您不能对javascript文件签名(至少不能对问题系统要求签名),也不能验证整个文档是否可信。因此,攻击者可以在用户私钥被加密之前或通过用户密码解密时窃取用户私钥。为了进一步说明,我将引用@ArtjomB提供的URI。 Java密码术被认为有害


至此,我已经提供了足够严重的安全性问题,以至于对具有上述要求的问题的任何进一步讨论都是毫无意义的。但是为了完整起见,我将看一下注释中讨论的进一步解决方法。


浏览器插件-浏览器插件与上面列出的系统要求不匹配。有关浏览器插件的进一步说明,请参阅(Java密码学被认为有害)。Web存储API-比存储在cookie中更好的解决方案,因为脱机内容无需随每个http请求传输值,但仍然容易受到恶意javascript和xss的攻击。

结论:鉴于上面列出的系统要求,没有安全的方法来完成我所要求的。 JavaScript不适合用作客户端加密的语言(请参阅Java密码学认为有害),并且在撰写本文时,还没有为此目的设计浏览器。

评论


$ \ begingroup $
文章已经过时了。您可以使用tls,window.crypto和更新的浏览器功能(例如csp和子资源完整性)来验证脚本。您还可以使用IIFE生成密钥并定义以后添加的脚本不可用的接口,或者使用密封的Worker防止任意代码更改sjcl代码。最后,如果您使用用户提示的密码(+ b / scrypt)来输入aes,则可以将ct存储在localStorage中,而不必担心。
$ \ endgroup $
–丹达维斯
16年5月26日在21:08



$ \ begingroup $
我在评论中添加了一些链接,并且可以放大任何问题区域,但是有很多内容需要讨论。除非您向其他用户显示其他用户的内容,否则XSS是不可能的。要保护聊天消息,请使用清除功能和https,然后90%的攻击媒介就会消失。然后,在页面中添加CSP HTTP标头,并在所有非现场