summaryrefslogtreecommitdiff
path: root/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'key.c')
-rw-r--r--key.c117
1 files changed, 116 insertions, 1 deletions
diff --git a/key.c b/key.c
index 06b15d65c..484b97f67 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.69 2007/07/12 05:48:05 ray Exp $ */ 1/* $OpenBSD: key.c,v 1.78 2008/07/07 23:32:51 stevesk Exp $ */
2/* 2/*
3 * read_bignum(): 3 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -11,6 +11,7 @@
11 * 11 *
12 * 12 *
13 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 13 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
14 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
14 * 15 *
15 * Redistribution and use in source and binary forms, with or without 16 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions 17 * modification, are permitted provided that the following conditions
@@ -35,9 +36,11 @@
35 36
36#include "includes.h" 37#include "includes.h"
37 38
39#include <sys/param.h>
38#include <sys/types.h> 40#include <sys/types.h>
39 41
40#include <openssl/evp.h> 42#include <openssl/evp.h>
43#include <openbsd-compat/openssl-compat.h>
41 44
42#include <stdarg.h> 45#include <stdarg.h>
43#include <stdio.h> 46#include <stdio.h>
@@ -171,6 +174,7 @@ key_equal(const Key *a, const Key *b)
171 default: 174 default:
172 fatal("key_equal: bad key type %d", a->type); 175 fatal("key_equal: bad key type %d", a->type);
173 } 176 }
177 /* NOTREACHED */
174} 178}
175 179
176u_char* 180u_char*
@@ -294,6 +298,114 @@ key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
294 return retval; 298 return retval;
295} 299}
296 300
301/*
302 * Draw an ASCII-Art representing the fingerprint so human brain can
303 * profit from its built-in pattern recognition ability.
304 * This technique is called "random art" and can be found in some
305 * scientific publications like this original paper:
306 *
307 * "Hash Visualization: a New Technique to improve Real-World Security",
308 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
309 * Techniques and E-Commerce (CrypTEC '99)
310 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
311 *
312 * The subject came up in a talk by Dan Kaminsky, too.
313 *
314 * If you see the picture is different, the key is different.
315 * If the picture looks the same, you still know nothing.
316 *
317 * The algorithm used here is a worm crawling over a discrete plane,
318 * leaving a trace (augmenting the field) everywhere it goes.
319 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
320 * makes the respective movement vector be ignored for this turn.
321 * Graphs are not unambiguous, because circles in graphs can be
322 * walked in either direction.
323 */
324
325/*
326 * Field sizes for the random art. Have to be odd, so the starting point
327 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
328 * Else pictures would be too dense, and drawing the frame would
329 * fail, too, because the key type would not fit in anymore.
330 */
331#define FLDBASE 8
332#define FLDSIZE_Y (FLDBASE + 1)
333#define FLDSIZE_X (FLDBASE * 2 + 1)
334static char *
335key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
336{
337 /*
338 * Chars to be used after each other every time the worm
339 * intersects with itself. Matter of taste.
340 */
341 char *augmentation_string = " .o+=*BOX@%&#/^SE";
342 char *retval, *p;
343 u_char field[FLDSIZE_X][FLDSIZE_Y];
344 u_int i, b;
345 int x, y;
346 size_t len = strlen(augmentation_string) - 1;
347
348 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
349
350 /* initialize field */
351 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
352 x = FLDSIZE_X / 2;
353 y = FLDSIZE_Y / 2;
354
355 /* process raw key */
356 for (i = 0; i < dgst_raw_len; i++) {
357 int input;
358 /* each byte conveys four 2-bit move commands */
359 input = dgst_raw[i];
360 for (b = 0; b < 4; b++) {
361 /* evaluate 2 bit, rest is shifted later */
362 x += (input & 0x1) ? 1 : -1;
363 y += (input & 0x2) ? 1 : -1;
364
365 /* assure we are still in bounds */
366 x = MAX(x, 0);
367 y = MAX(y, 0);
368 x = MIN(x, FLDSIZE_X - 1);
369 y = MIN(y, FLDSIZE_Y - 1);
370
371 /* augment the field */
372 field[x][y]++;
373 input = input >> 2;
374 }
375 }
376
377 /* mark starting point and end point*/
378 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
379 field[x][y] = len;
380
381 /* fill in retval */
382 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
383 p = strchr(retval, '\0');
384
385 /* output upper border */
386 for (i = p - retval - 1; i < FLDSIZE_X; i++)
387 *p++ = '-';
388 *p++ = '+';
389 *p++ = '\n';
390
391 /* output content */
392 for (y = 0; y < FLDSIZE_Y; y++) {
393 *p++ = '|';
394 for (x = 0; x < FLDSIZE_X; x++)
395 *p++ = augmentation_string[MIN(field[x][y], len)];
396 *p++ = '|';
397 *p++ = '\n';
398 }
399
400 /* output lower border */
401 *p++ = '+';
402 for (i = 0; i < FLDSIZE_X; i++)
403 *p++ = '-';
404 *p++ = '+';
405
406 return retval;
407}
408
297char * 409char *
298key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) 410key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
299{ 411{
@@ -311,6 +423,9 @@ key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
311 case SSH_FP_BUBBLEBABBLE: 423 case SSH_FP_BUBBLEBABBLE:
312 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); 424 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
313 break; 425 break;
426 case SSH_FP_RANDOMART:
427 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
428 break;
314 default: 429 default:
315 fatal("key_fingerprint_ex: bad digest representation %d", 430 fatal("key_fingerprint_ex: bad digest representation %d",
316 dgst_rep); 431 dgst_rep);