Графический fingerprint ключей
UPD: вариант от вездесущего ЛЛео https://lleo.me/dnevnik/2023/10/05 (https://github.com/lleokaganov/identicon-js)
Предыстория
С некоторых пор в ssh появилась возможность проверять не только числовой fingerprint ключа, но и псевдографический.
Выглядит это так:
$ ssh-keygen -lv -f .ssh/id_rsa.tmp 2048 e6:70:70:9d:c3:37:b2:f2:0a:55:19:3a:87:8e:19:ed .ssh/id_rsa.tmp.pub (RSA) +--[ RSA 2048]----+ | . | | . = + | | o * X o | | O + = . | | + E . | | * o | | . . . | | . . | | . | +-----------------+
Практика показывает, что отличить отпечатки друг от друга по таким картинкам намного проще. Разумеется, сверять одинаковые отпечатки лучше по самом отпечаткам (а ещё лучше проверять сами ключи, всё равно для надёжности надо запускать diff).
Итак, решается две схожие задачи:
- Имея перед глазами два отпечатка, с высокой долей уверенности сказать, что они одинаковые
Имея перед глазами один отпечаток с высокой долей уверенности сказать, что он тот же, что был вчера
Вторую задачу -- я только что проверил -- это метод решает на отлично.
Задача
- Дано
- Числовой fingerprint: число длиной, допустим, от 12 до 32 байтов
- Необходимо получить
- Графический fingerprint: картинку (2 варианта размера: 64x64 и произвольного, но не очень большого)
- Условия
-
- Картинка должна быть хорошо узнаваема без сличения с оригиналом
- Графические отпечатка разных ключей должны быть очевидно разными, вплоть до того, что один трудно было бы спутать с другим даже без сличения
- Замечание 1
- Имеющийся псевдографический алгоритм хорош как минимум с трёх сторон:
- Даёт хорошо различимый контур на "гладком" фоне
- Содержит элементы различной формы
- Содержит "опорные" буквы, которые можно запомнить (в примере: "EXO")
- Замечание 2
- Не следует слишком увлекаться играми с цветом: дальтонизм в лёгкой форме намного более распространён, чем кажется.
Приложение
Код ssh-keygen: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/key.c?annotate
- Алгоритм рисования псевдографического отпечатка (печатается в сокращении):
char *augmentation_string = " .o+=*BOX@%&#/^SE"; for (i = 0; i < dgst_raw_len; i++) { int input; /* each byte conveys four 2-bit move commands */ input = dgst_raw[i]; for (b = 0; b < 4; b++) { /* evaluate 2 bit, rest is shifted later */ x += (input & 0x1) ? 1 : -1; y += (input & 0x2) ? 1 : -1; /* assure we are still in bounds */ x = MAX(x, 0); y = MAX(y, 0); x = MIN(x, FLDSIZE_X - 1); y = MIN(y, FLDSIZE_Y - 1); /* augment the field */ if (field[x][y] < len - 2) field[x][y]++; input = input >> 2; }