首页 > 解决方案 > 基于字符串(或 uuid)生成人类可区分的图片

问题描述

Tl;Dr:我正在创建一个应用程序:两个或多个用户之间的端到端加密聊天,需要快速方便的方式来直观地检查中间人的缺失

应用程序背后的想法:

  1. AliceBob前端应用程序生成 RSA公钥+私钥(使用了很棒的jsencrypt库)
  2. AliceBob前端应用程序向服务器应用程序发送请求,因此服务器为 Alice 和 Bob 生成唯一 ID(实际上是一个 UUID)。
  3. AliceBob前端应用程序生成链接QR 码,在 url 的哈希部分包含他们的公钥和他们的 ID,因此它不会在打开时发送到服务器。
  4. 然后链接QR-code的照片可以通过第三方渠道(不受保护)发送,并且开放允许 Alice 和 Bob 前端应用程序将他们的对应项添加到“联系人列表”(所有这些都发生在前端)
  5. Alice的应用程序在从Bob的应用程序接收到公钥和 ID 后,使用公钥加密消息并将其发送到服务器,并指定Bob 的 ID
  6. Bob询问服务器“我的 ID 是否有新消息?”,并在收到服务器的消息后,用他的私钥解密。
  7. 服务器在任何时候都没有得到私钥或公钥。它只是生成ID并在由javascript前端加密的ID之间传递自己的消息,无法读取它,并在前端收到消息后删除消息。

问题:

Alice 和 Bob 只接受 ID 和公钥,因此,没有办法简单快速地区分它们之间是否存在 ManInTheMiddle,因为 UUID 与某些 SHA-hash 不同,通常看起来非常相似。随后生成的 uuid 可能仅存在单个字符的差异,而且人眼很难识别这种差异。

想要的解决方案:

我需要某种完全确定性的 UUID(或从该 UUID 生成的字符串)的可视化,并且可以通过人眼快速识别差异。

某种图片,用户的“头像”会很棒。

由于 UUID 有128 位数据,我需要一些使用大部分数据的算法。

我试过的:

  1. 头像生成工具https://getavataaars.com/ - 允许创建头像图片,基于 10 个参数,每个参数包含多个选项,因此,如果我将所有这些参数相乘,我得到:35*7*6*8*9*12*12*12*12*7= 15.362.887.680 -> 34 位数据。,在我看来,太少了。但是创建头像的想法对我来说很好。

  2. 头像生成工具https://8biticon.com - 与之前类似,有5*4*65*26*36*32= 38.937.600 -> 26 位数据

  3. Identicon http://identicon.net - 生成具有不同颜色的 5x5 二进制图片。例如33554432*amount of colors,如果有所有“网络颜色”(216),则将有33554432*216= 大约33 位数据。我知道,可以使用更多的颜色,但是添加到列表中的颜色越多,它们就越难以区分。另外,这个图标没有任何意义,看起来像罗夏墨迹,在浏览器标签切换之间(在第三方服务中的 Alice 消息和“安全应用程序”中实际生成的图标之间)不容易记住

  4. https://jdenticon.com/ - 我实际上无法计算,这个算法可以生成多少张图像,但它有一个像以前一样的缺陷。从某种意义上说,美丽的图案有时无法相互识别。

  5. Telegram 使用四个表情符号图标序列对其进行加密呼叫。我发现,Unicode 标准中有 3521 种情绪,所以,四个图标会给出:3521*3521*3521*3521= 153.696.543.348.481 = 47 bits of data,这种方法使用更多的数据位,然后是头像,并且没有那么糟糕的易用性被人类认可。如果这个表情符号可以加入某种“故事”,识别会很有效,但是只有四个不同的非链接图片,就像我使用提到的头像服务生成(例如)四个头像一样把它们放在一起。

  6. 我尝试制作图像生成器,每个像素都由单字节指定,因此,128 位数据或 16 字节很容易转换为 4x4 像素化图片,但是,它看起来像视觉噪音,无法与其他图片区分开来.

  7. 我想创建一些 UUID 的文本表示,例如,使用随机组合的四个单词,但看起来像一个“故事”,如“<what?> <who?> <Making what?> <with who?>”。比如“蓝枪骑鸭”、“搞笑锤得丸”等等。但是我需要再次创建形容词、名词、动词和名词的列表,选择适合公式的那些。而且我怀疑我是否可以通过这种方法获得第二位数据。

我错过了什么吗?

也许还有其他一些我还没有找到的算法?

也许我不需要使用所有 128 位,而只需创建一个较小的散列?我已经阅读了关于截断哈希的问题,并且截断 UUID 有很多严重的问题(因此,如果使用截断,则必须制作 UUID 的散列,而不是“按原样”使用它)

我认为应该有一些“分形”算法,由源数据初始化会产生绝对独特的画面。例如,在 Mandelbrot 分形中,4D 坐标的微小差异构成了完全不同的画面。但是在 Mandelbrot 的情况下,有很多坐标可以构成普通的单色正方形,因此,为了利用它,我必须创建一些分形 4D 空间的“意义区域图”。

此外,基于公钥的图像

我认为,基于用户 ID 构建图像是不够的,因为,更危险的情况是 ManInTheMiddle 可以以某种方式替代公钥,因此,由这个 Evil 密钥加密的消息可以被 Evil 私钥解密。但是构建公钥图像有保存问题,增加公钥的大小(它可能大约 1K 字节长),所以要从公钥制作图像,我肯定必须得到它的 sha256(或其他)散列,并从哈希字符串构建图像,我们将返回起点。

标签: javascriptencryptionavatarman-in-the-middleavatar-generation

解决方案


回答我自己的问题。

经过大量的实验,我决定使用可以在https://getavataaars.com/找到的头像引擎(实际上,它是 VanillaJS 版本:https ://github.com/HB0N0/AvataaarsJs )

最后我制作了一个测试版的加密聊天应用程序:https ://cryptboard.io/


推荐阅读