您可以直接使用实际的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 $
:
#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)
{
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));
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
x = FLDSIZE_X / 2;
y = FLDSIZE_Y / 2;
for (i = 0; i < dgst_raw_len; i++) {
int input;
input = dgst_raw[i];
for (b = 0; b < 4; b++) {
x += (input & 0x1) ? 1 : -1;
y += (input & 0x2) ? 1 : -1;
x = MAX(x, 0);
y = MAX(y, 0);
x = MIN(x, FLDSIZE_X - 1);
y = MIN(y, FLDSIZE_Y - 1);
if (field[x][y] < len - 2)
field[x][y]++;
input = input >> 2;
}
}
field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
field[x][y] = len;
snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
p = strchr(retval, '\0');
for (i = p - retval - 1; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
*p++ = '\n';
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';
}
*p++ = '+';
for (i = 0; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
return retval;
}
它似乎与OpenSSH代码的其余部分没有显著的依赖关系,除了const Key *k
参数外,该参数仅在一个行中作为key_type()
和key_size()
函数(或宏?)的参数使用。非标准类型u_char
和u_int
似乎只是unsigned char
和unsigned int
的别名,而xcalloc()
函数似乎只是标准calloc()
的替代或包装。