用于校验和(例如SHA)的可视化算法

4
我想生成类似于VisualHostKey的SHA校验和。但它应该适用于任何十六进制校验和。
生成的工件可以是ASCII艺术、2D彩色调色板,或者只是PNG中的一些随机垃圾。个人喜欢VisualHostKey的方法,但我也接受建议。
这个想法是为了能够快速识别两个校验和是否相同,只使用人眼即可。当面对一堆总和时,快速找到您正在寻找的那个。

1
你很难将近160位的内容压缩成一张图片,以便于记忆和区分。 - CodesInChaos
相关概念:Identicons,例如独角兽形式的 http://unicornify.appspot.com/。 - CodesInChaos
1
哎呀,@CodeInChaos,你让我看到这个东西真是太丢人了 :) 不过这种方法还是很有趣的,尽管对我来说有点太多天哪!!!小马宝莉!!!了。 - Maarten Bodewes
2个回答

0

您可以直接使用实际的OpenSSH VisualHostKey代码,该代码位于OpenSSH源代码中的key.c文件中的key_fingerprint_randomart()函数中。该算法相当简单,可以将任何字节数组作为输入。在OpenSSH中,输入是密钥的加密哈希值;您也可以这样做。

(如在OpenSSH源代码中定义的那样,该函数还需要一个指向密钥结构本身的指针,但这仅用于在图片顶部打印密钥的类型和大小。)

事实上,由于该代码是自由许可的,因此让我在此处包含一份副本。这是从OpenSSH 6.1中提取的,$OpenBSD: key.c,v 1.99 2012/05/23 03:28:28 djm Exp $:

/*
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
 * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Draw an ASCII-Art representing the fingerprint so human brain can
 * profit from its built-in pattern recognition ability.
 * This technique is called "random art" and can be found in some
 * scientific publications like this original paper:
 *
 * "Hash Visualization: a New Technique to improve Real-World Security",
 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
 * Techniques and E-Commerce (CrypTEC '99)
 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
 *
 * The subject came up in a talk by Dan Kaminsky, too.
 *
 * If you see the picture is different, the key is different.
 * If the picture looks the same, you still know nothing.
 *
 * The algorithm used here is a worm crawling over a discrete plane,
 * leaving a trace (augmenting the field) everywhere it goes.
 * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls
 * makes the respective movement vector be ignored for this turn.
 * Graphs are not unambiguous, because circles in graphs can be
 * walked in either direction.
 */

/*
 * Field sizes for the random art.  Have to be odd, so the starting point
 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
 * Else pictures would be too dense, and drawing the frame would
 * fail, too, because the key type would not fit in anymore.
 */
#define FLDBASE         8
#define FLDSIZE_Y       (FLDBASE + 1)
#define FLDSIZE_X       (FLDBASE * 2 + 1)
static char *
key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
{
        /*
         * Chars to be used after each other every time the worm
         * intersects with itself.  Matter of taste.
         */
        char    *augmentation_string = " .o+=*BOX@%&#/^SE";
        char    *retval, *p;
        u_char   field[FLDSIZE_X][FLDSIZE_Y];
        u_int    i, b;
        int      x, y;
        size_t   len = strlen(augmentation_string) - 1;

        retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));

        /* initialize field */
        memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
        x = FLDSIZE_X / 2;
        y = FLDSIZE_Y / 2;

        /* process raw key */
        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;
                }
        }

        /* mark starting point and end point*/
        field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
        field[x][y] = len;

        /* fill in retval */
        snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
        p = strchr(retval, '\0');

        /* output upper border */
        for (i = p - retval - 1; i < FLDSIZE_X; i++)
                *p++ = '-';
        *p++ = '+';
        *p++ = '\n';

        /* output content */
        for (y = 0; y < FLDSIZE_Y; y++) {
                *p++ = '|';
                for (x = 0; x < FLDSIZE_X; x++)
                        *p++ = augmentation_string[MIN(field[x][y], len)];
                *p++ = '|';
                *p++ = '\n';
        }

        /* output lower border */
        *p++ = '+';
        for (i = 0; i < FLDSIZE_X; i++)
                *p++ = '-';
        *p++ = '+';

        return retval;
}

它似乎与OpenSSH代码的其余部分没有显著的依赖关系,除了const Key *k参数外,该参数仅在一个行中作为key_type()key_size()函数(或宏?)的参数使用。非标准类型u_charu_int似乎只是unsigned charunsigned int的别名,而xcalloc()函数似乎只是标准calloc()的替代或包装。


0
通常,这是通过创建一个接受种子的图像生成函数来实现的。然后,您对一些数据进行哈希处理,然后使用结果来初始化您的图像生成器。这将防止它在PNG中生成随机垃圾,并为您提供可区分的内容。

你的回答太笼统了,在我看来完全没有用。有趣的部分是如何以一种人类可以记住和区分的方式将尽可能多的信息放入图像中。 - CodesInChaos
你是否期望我提供一个完整的函数和代码示例作为答案?如果是这样,那么你要求的是相当多的代码和对首先找出函数的认真投入。这需要很多工作,而且据我所知,它并不是一些已经发表并广泛采用的东西。在我看来,整个过程除非你有一组固定的图像和映射哈希值,否则就不切实际。 - Michael J. Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接