Monorepo for Tangled
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174package randomart
/* * 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. */
import ( "os")
func MAX(a, b int) int { if a > b { return a } return b}
func MIN(a, b int) int { if a < b { return a } return b}
/* * 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. */const ( FLDBASE = 8 FLDSIZE_Y = (FLDBASE + 1) FLDSIZE_X = (FLDBASE*2 + 1))
func FromString(str string) string { ch := make(chan byte)
go func() { defer close(ch) for _, v := range []byte(str) { ch <- v } }() return key_fingerprint_randomart(ch)}
func FromFile(file *os.File) string { ch := make(chan byte)
go func() { defer close(ch) // TODO make input a 1 element byte array input := make([]byte, 1) nread, err := file.Read(input) for err == nil && nread > 0 { ch <- input[0] nread, err = file.Read(input) } }() return key_fingerprint_randomart(ch)}
func key_fingerprint_randomart(ch chan byte) string { /* * Chars to be used after each other every time the worm * intersects with itself. Matter of taste. */ augment_string := " .o+=*BOX@%&#/^SE" var field [FLDSIZE_X][FLDSIZE_Y]byte len_aug := len(augment_string) - 1 var retval [(FLDSIZE_X + 3) * (FLDSIZE_Y + 2)]byte
/* initialize field */ x := FLDSIZE_X / 2 y := FLDSIZE_Y / 2
/* process raw key */ for input, ok := <-ch; ok; input, ok = <-ch { /* each byte conveys four 2-bit move commands */ for b := 0; b < 4; b++ { /* evaluate 2 bit, rest is shifted later */ if input&0x1 > 0 { x += 1 } else { x += -1 }
if input&0x2 > 0 { y++ } else { y-- }
/* 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 int(field[x][y]) < len_aug-2 { field[x][y]++ } input = input >> 2 } }
/* mark starting point and end point*/ field[FLDSIZE_X/2][FLDSIZE_Y/2] = byte(len_aug - 1) field[x][y] = byte(len_aug)
i := 0 retval[i] = '+' i++
/* output upper border */ for x := 0; x < FLDSIZE_X; x++ { retval[i] = '-' i++ } retval[i] = '+' i++ retval[i] = '\n' i++
/* output content */ for y := 0; y < FLDSIZE_Y; y++ { retval[i] = '|' i++ for x := 0; x < FLDSIZE_X; x++ { retval[i] = augment_string[MIN(int(field[x][y]), len_aug)] i++ } retval[i] = '|' i++ retval[i] = '\n' i++ }
/* output lower border */ retval[i] = '+' i++ for j := 0; j < FLDSIZE_X; j++ { retval[i] = '-' i++ } retval[i] = '+' i++
return string(retval[0:i])}