javascript - 基于字符串(或 uuid)生成人类可区分的图片
问题描述
Tl;Dr:我正在创建一个应用程序:两个或多个用户之间的端到端加密聊天,需要快速方便的方式来直观地检查中间人的缺失
应用程序背后的想法:
- Alice和Bob前端应用程序生成 RSA公钥+私钥(使用了很棒的jsencrypt库)
- Alice和Bob前端应用程序向服务器应用程序发送请求,因此服务器为 Alice 和 Bob 生成唯一 ID(实际上是一个 UUID)。
- Alice和Bob前端应用程序生成链接和QR 码,在 url 的哈希部分包含他们的公钥和他们的 ID,因此它不会在打开时发送到服务器。
- 然后链接或QR-code的照片可以通过第三方渠道(不受保护)发送,并且开放允许 Alice 和 Bob 前端应用程序将他们的对应项添加到“联系人列表”(所有这些都发生在前端)
- Alice的应用程序在从Bob的应用程序接收到公钥和 ID 后,使用公钥加密消息并将其发送到服务器,并指定Bob 的 ID。
- Bob询问服务器“我的 ID 是否有新消息?”,并在收到服务器的消息后,用他的私钥解密。
- 服务器在任何时候都没有得到私钥或公钥。它只是生成ID并在由javascript前端加密的ID之间传递自己的消息,无法读取它,并在前端收到消息后删除消息。
问题:
Alice 和 Bob 只接受 ID 和公钥,因此,没有办法简单快速地区分它们之间是否存在 ManInTheMiddle,因为 UUID 与某些 SHA-hash 不同,通常看起来非常相似。随后生成的 uuid 可能仅存在单个字符的差异,而且人眼很难识别这种差异。
想要的解决方案:
我需要某种完全确定性的 UUID(或从该 UUID 生成的字符串)的可视化,并且可以通过人眼快速识别差异。
某种图片,用户的“头像”会很棒。
由于 UUID 有128 位数据,我需要一些使用大部分数据的算法。
我试过的:
头像生成工具https://getavataaars.com/ - 允许创建头像图片,基于 10 个参数,每个参数包含多个选项,因此,如果我将所有这些参数相乘,我得到:
35*7*6*8*9*12*12*12*12*7
= 15.362.887.680 -> 34 位数据。,在我看来,太少了。但是创建头像的想法对我来说很好。头像生成工具https://8biticon.com - 与之前类似,有
5*4*65*26*36*32
= 38.937.600 -> 26 位数据Identicon http://identicon.net - 生成具有不同颜色的 5x5 二进制图片。例如
33554432*amount of colors
,如果有所有“网络颜色”(216),则将有33554432*216
= 大约33 位数据。我知道,可以使用更多的颜色,但是添加到列表中的颜色越多,它们就越难以区分。另外,这个图标没有任何意义,看起来像罗夏墨迹,在浏览器标签切换之间(在第三方服务中的 Alice 消息和“安全应用程序”中实际生成的图标之间)不容易记住https://jdenticon.com/ - 我实际上无法计算,这个算法可以生成多少张图像,但它有一个像以前一样的缺陷。从某种意义上说,美丽的图案有时无法相互识别。
Telegram 使用四个表情符号图标序列对其进行加密呼叫。我发现,Unicode 标准中有 3521 种情绪,所以,四个图标会给出:
3521*3521*3521*3521
= 153.696.543.348.481 = 47 bits of data,这种方法使用更多的数据位,然后是头像,并且没有那么糟糕的易用性被人类认可。如果这个表情符号可以加入某种“故事”,识别会很有效,但是只有四个不同的非链接图片,就像我使用提到的头像服务生成(例如)四个头像一样把它们放在一起。我尝试制作图像生成器,每个像素都由单字节指定,因此,128 位数据或 16 字节很容易转换为 4x4 像素化图片,但是,它看起来像视觉噪音,无法与其他图片区分开来.
我想创建一些 UUID 的文本表示,例如,使用随机组合的四个单词,但看起来像一个“故事”,如“<what?> <who?> <Making what?> <with who?>”。比如“蓝枪骑鸭”、“搞笑锤得丸”等等。但是我需要再次创建形容词、名词、动词和名词的列表,选择适合公式的那些。而且我怀疑我是否可以通过这种方法获得第二位数据。
我错过了什么吗?
也许还有其他一些我还没有找到的算法?
也许我不需要使用所有 128 位,而只需创建一个较小的散列?我已经阅读了关于截断哈希的问题,并且截断 UUID 有很多严重的问题(因此,如果使用截断,则必须制作 UUID 的散列,而不是“按原样”使用它)
我认为应该有一些“分形”算法,由源数据初始化会产生绝对独特的画面。例如,在 Mandelbrot 分形中,4D 坐标的微小差异构成了完全不同的画面。但是在 Mandelbrot 的情况下,有很多坐标可以构成普通的单色正方形,因此,为了利用它,我必须创建一些分形 4D 空间的“意义区域图”。
此外,基于公钥的图像
我认为,基于用户 ID 构建图像是不够的,因为,更危险的情况是 ManInTheMiddle 可以以某种方式替代公钥,因此,由这个 Evil 密钥加密的消息可以被 Evil 私钥解密。但是构建公钥图像有保存问题,增加公钥的大小(它可能大约 1K 字节长),所以要从公钥制作图像,我肯定必须得到它的 sha256(或其他)散列,并从哈希字符串构建图像,我们将返回起点。
解决方案
回答我自己的问题。
经过大量的实验,我决定使用可以在https://getavataaars.com/找到的头像引擎(实际上,它是 VanillaJS 版本:https ://github.com/HB0N0/AvataaarsJs )
最后我制作了一个测试版的加密聊天应用程序:https ://cryptboard.io/
推荐阅读
- angular - Angular 6 元素和从 angular.json 导出样式
- android - 一旦您不小心丢失了密码,您能否再次签署您的 APK,我的笔记本电脑死了?
- java - Java Play SBT 中的 IntelliJ 更新后项目名称无效
- c# - FileSystemWatcher 特定事件
- python - pip install pyswisseph 在 Windows 10 上出现错误
- python - 在烧瓶中使用 recaptcha 时输入密码无效
- java - Spring transactions not working + JAX WS + JDBC
- jquery - 推特引导模式背后的时间选择器
- angular - 订阅流后如何返回数据?
- python - 给定代码中的错误是什么?