/* * 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. */ #include "randomart.h" #define FLDSIZE_Y 8 #define FLDSIZE_X FLDSIZE_Y * 2 char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len) { /* * Chars to be used after each other every time the worm * intersects with itself. Matter of taste. */ char *augmentation_string = " .o+=*BOX@%&#/^"; char *retval, *p; char field[FLDSIZE_X][FLDSIZE_Y]; unsigned int i, b; int x, y; retval = ucmalloc((FLDSIZE_X + 3) * (FLDSIZE_Y + 2)); /* initialize field */ memset(field, ' ', FLDSIZE_X * FLDSIZE_Y * sizeof(char)); x = FLDSIZE_X / 2; y = FLDSIZE_Y / 2; field[x][y] = '.'; /* 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 */ p = strchr(augmentation_string, field[x][y]); if (*++p != '\0') field[x][y] = *p; input = input >> 2; } } /* fill in retval */ p = retval; /* output upper border */ *p++ = '+'; for (i = 0; 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++ = field[x][y]; *p++ = '|'; *p++ = '\n'; } /* output lower border */ *p++ = '+'; for (i = 0; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; return retval; }