Search code examples
javascriptencryptionavatarman-in-the-middleavatar-generation

Generate human-distinguishable picture based on string (or uuid)


Tl;Dr: I'm creating an application: end-to-end encrypted chat between two or more users, and need fast and convinient way to visually check for an absense of man-in-the-middle

The idea behind an app:

  1. Alice and Bob frontend app generates RSA public+private keys (with use of awesome jsencrypt library)
  2. Alice and Bob frontend app send request to server app, so server generates unique ID for Alice and Bob (actually an UUID).
  3. Alice and Bob frontend app generates link and QR-code, containing their public keys and their IDs in the hash-part of the url, so it not gonna be sent to server on opening.
  4. Link or QR-code's photo then could be sent by third-party channel (non-protected), and, being open allows Alice and Bob frontend app add their counterpart to "contact list" (all of that is happening on frontend side)
  5. Alice's application, after receiving the public key and ID from Bob's application, encrypts the message with public key and sends it to the server, specifying Bob's ID.
  6. Bob ask server "are there any new messages for my ID?", and after receiving message from server, decrypts it by his private key.
  7. Server not getting private nor public keys at any point. It just generate ID and pass through itself messages between IDs encrypted by javascript frontend, not being able to read it, and deleting message just after it was recieved by frontend.

The problem:

Alice and Bob accept only ID and public key, so, there are no way to simply and fast distinguish, are there any ManInTheMiddle between them, because UUID, unlike some SHA-hashes usually looks pretty similar. Sequently generated uuids could differ by just single character, and are not so easy for human eye to recongize that difference.

The wanted solution:

I need some kind of visualisation of UUID (or some string, generated from that UUID) that is fully determenistic, and is fast to recognize differencies by human eye.

Some kind of picture, user's "avatar" would be great.

As UUID has 128 bit of data, I need some algorythm that is using most of it.

What I've tried:

  1. Avatar generation tool https://getavataaars.com/ - allows to create avatar picture, based on 10 parameters each contains several options so, if I multiply all of them I get: 35*7*6*8*9*12*12*12*12*7 = 15.362.887.680 -> 34 bits of data., to my opinion, it's too little. But the idea of creating avatar looking good for me.

  2. Avatar generation tool https://8biticon.com - similar to previous, has 5*4*65*26*36*32 = 38.937.600 -> 26 bits of data

  3. Identicon http://identicon.net - generates a 5x5 binary picture with different colors. Gives 33554432*amount of colors, for example, if there are all "web colors" (216), there would be 33554432*216 = about 33 bits of data. I know, that more colors can be used, but they became less distinguishable the more they added to list. Also, this icons have no meaning, looking like a rorschach spot, and couldnt be easily memorized between browser tab switching (between Alice message in third-party service and actual generated icon in "the secure app")

  4. https://jdenticon.com/ - I cant actually count, how many images could be generated by this algorythm, but it hase a flaw like previous. In a sence, beautiful patterns sometimes couldn't be recognized from each other.

  5. Telegram on it's encrypted calls using sequence of four emoji icons. As I found, there are 3521 emotions in Unicode standard, so, four icons would give: 3521*3521*3521*3521 = 153.696.543.348.481 = 47 bits of data, this method uses more bits of data, then avatars, and has not-so-bad easiness of recognition by human. If this emoticons could be joined in some kind of "story", recognition would be much effecive, but then there are just four different non-linked pictures, it the save as if I use mentioned avatar services to generate (for example) four avatars and put them rogether.

  6. I tried to make image generator, there every pixel specified by single byte, so, 128 bits of data, or 16 bytes are easily converted to 4x4 pixelated picture, but, it looking like visual noise, and couldn't be distingushed with other picture.

  7. I thought of creating some textual representation of the UUID, for example, using four words combined randomly, but looking like a "Story" like "<what?> <who?> <Making what?> <with who?>". For example "blue gunicorn riding a duck", "funny hammer acquiring a pill" and so on. But I'll need to create lists of adjectives, nouns, verbs, and nouns again, selecting the ones suitable for the formula. And I have doubts that I can get anouth bits of data by this method.

Am I missing something?

Maybe there are some other algorythms out there, that I didn't found yet?

Maybe I don't need to use all of 128 bits, and just create a smaller hash? I've read about the problem with tructating the hash, and truncating the UUID has much serious problem (so, if truncating would by used, it's neccesary to make hash of UUID, not using it "as is")

I think that there should be some "fractal" algorythm, that, being initialized by source data would henerate absolutely unique picture. For example, In Mandelbrot fractal, little differents in 4D-coordinates make absolutely different picture. But in case of Mandelbrot, there are lots of coordinates that make plain single-color square, so, to make use of it, I have to create some "map of meaning areas" of the fractal 4D-space.

Also, image based of public key

I think, that building image based on user ID is not enough, because, more dangerous situation is there ManInTheMiddle somehow could substitute public key, so, message encrypted by this Evil key could be decrypted by Evil private key. But building image of public key has the save problems, adding the size of public key (it could be about 1K-byte long), so to make an image from public key I definetly have to get sha256 (or other) hash of it, and build image from the hash string, there we are returning to the starting point.


Solution

  • Answering my own question.

    After lots of experiments I've decided to use avatar engine that can be found at https://getavataaars.com/ (actually, it's VanillaJS version: https://github.com/HB0N0/AvataaarsJs)

    And finally I made a beta-version of encrypted chat application: https://cryptboard.io/

    Published it's source code for anyone: https://github.com/MihanEntalpo/cryptboard.io