forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at master 3.7 kB view raw
1package randomart 2 3/* 4 * Draw an ASCII-Art representing the fingerprint so human brain can 5 * profit from its built-in pattern recognition ability. 6 * This technique is called "random art" and can be found in some 7 * scientific publications like this original paper: 8 * 9 * "Hash Visualization: a New Technique to improve Real-World Security", 10 * Perrig A. and Song D., 1999, International Workshop on Cryptographic 11 * Techniques and E-Commerce (CrypTEC '99) 12 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf 13 * 14 * The subject came up in a talk by Dan Kaminsky, too. 15 * 16 * If you see the picture is different, the key is different. 17 * If the picture looks the same, you still know nothing. 18 * 19 * The algorithm used here is a worm crawling over a discrete plane, 20 * leaving a trace (augmenting the field) everywhere it goes. 21 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls 22 * makes the respective movement vector be ignored for this turn. 23 * Graphs are not unambiguous, because circles in graphs can be 24 * walked in either direction. 25 */ 26 27import ( 28 "os" 29) 30 31func MAX(a, b int) int { 32 if a > b { 33 return a 34 } 35 return b 36} 37 38func MIN(a, b int) int { 39 if a < b { 40 return a 41 } 42 return b 43} 44 45/* 46 * Field sizes for the random art. Have to be odd, so the starting point 47 * can be in the exact middle of the picture, and FLDBASE should be >=8 . 48 * Else pictures would be too dense, and drawing the frame would 49 * fail, too, because the key type would not fit in anymore. 50 */ 51const ( 52 FLDBASE = 8 53 FLDSIZE_Y = (FLDBASE + 1) 54 FLDSIZE_X = (FLDBASE*2 + 1) 55) 56 57func FromString(str string) string { 58 ch := make(chan byte) 59 60 go func() { 61 defer close(ch) 62 for _, v := range []byte(str) { 63 ch <- v 64 } 65 }() 66 return key_fingerprint_randomart(ch) 67} 68 69func FromFile(file *os.File) string { 70 ch := make(chan byte) 71 72 go func() { 73 defer close(ch) 74 // TODO make input a 1 element byte array 75 input := make([]byte, 1) 76 nread, err := file.Read(input) 77 for err == nil && nread > 0 { 78 ch <- input[0] 79 nread, err = file.Read(input) 80 } 81 }() 82 return key_fingerprint_randomart(ch) 83} 84 85func key_fingerprint_randomart(ch chan byte) string { 86 /* 87 * Chars to be used after each other every time the worm 88 * intersects with itself. Matter of taste. 89 */ 90 augment_string := " .o+=*BOX@%&#/^SE" 91 var field [FLDSIZE_X][FLDSIZE_Y]byte 92 len_aug := len(augment_string) - 1 93 var retval [(FLDSIZE_X + 3) * (FLDSIZE_Y + 2)]byte 94 95 /* initialize field */ 96 x := FLDSIZE_X / 2 97 y := FLDSIZE_Y / 2 98 99 /* process raw key */ 100 for input, ok := <-ch; ok; input, ok = <-ch { 101 /* each byte conveys four 2-bit move commands */ 102 for b := 0; b < 4; b++ { 103 /* evaluate 2 bit, rest is shifted later */ 104 if input&0x1 > 0 { 105 x += 1 106 } else { 107 x += -1 108 } 109 110 if input&0x2 > 0 { 111 y++ 112 } else { 113 y-- 114 } 115 116 /* assure we are still in bounds */ 117 x = MAX(x, 0) 118 y = MAX(y, 0) 119 x = MIN(x, FLDSIZE_X-1) 120 y = MIN(y, FLDSIZE_Y-1) 121 122 /* augment the field */ 123 if int(field[x][y]) < len_aug-2 { 124 field[x][y]++ 125 } 126 input = input >> 2 127 } 128 } 129 130 /* mark starting point and end point*/ 131 field[FLDSIZE_X/2][FLDSIZE_Y/2] = byte(len_aug - 1) 132 field[x][y] = byte(len_aug) 133 134 i := 0 135 retval[i] = '+' 136 i++ 137 138 /* output upper border */ 139 for x := 0; x < FLDSIZE_X; x++ { 140 retval[i] = '-' 141 i++ 142 } 143 retval[i] = '+' 144 i++ 145 retval[i] = '\n' 146 i++ 147 148 /* output content */ 149 for y := 0; y < FLDSIZE_Y; y++ { 150 retval[i] = '|' 151 i++ 152 for x := 0; x < FLDSIZE_X; x++ { 153 retval[i] = augment_string[MIN(int(field[x][y]), len_aug)] 154 i++ 155 } 156 retval[i] = '|' 157 i++ 158 retval[i] = '\n' 159 i++ 160 } 161 162 /* output lower border */ 163 retval[i] = '+' 164 i++ 165 for j := 0; j < FLDSIZE_X; j++ { 166 retval[i] = '-' 167 i++ 168 } 169 retval[i] = '+' 170 i++ 171 172 return string(retval[0:i]) 173}