Main Page
Related Pages
Modules
Classes
Files
File List
File Members
drunken_bishop.c
Go to the documentation of this file.
1
/* ========================================================================== */
2
/*! \file
3
* \brief Drunken bishop randomart algorithm
4
*
5
* Copyright (c) 2015-2020 by the developers. See the LICENSE file for details.
6
*
7
* A description and analysis of this algorithm can be found here:
8
* <br>
9
* http://dirk-loss.de/sshvis/drunken_bishop.pdf
10
*
11
* If nothing else is specified, function return zero to indicate success
12
* and a negative value to indicate an error.
13
*/
14
15
16
/* ========================================================================== */
17
/* Include headers */
18
19
#include "posix.h"
/* Include this first because of feature test macros */
20
21
#include <string.h>
22
23
#include "digest.h"
24
#include "encoding.h"
25
#include "main.h"
26
27
28
/* ========================================================================== */
29
/*! \addtogroup DIGEST */
30
/*! @{ */
31
32
33
/* ========================================================================== */
34
/* Constants */
35
36
/* Message prefix for DIGEST module */
37
#define MAIN_ERR_PREFIX "DIGEST: "
38
39
40
/* ========================================================================== */
41
/* Create and print randomart image using "drunken bishop" algorithm
42
*
43
* Every 2 bits of data are translated to a move on the field. The bits are
44
* mapped to the moves in pairs with most significant byte first and least
45
* significant bit pair (of every byte) first. Example:
46
*
47
* Data fc : 94 : b0 : ... : b7
48
* Bits 11 11 11 00 : 10 01 01 00 : 10 11 00 00 : ... : 10 11 01 11
49
* | | | | | | | | | | | | | | | |
50
* Move 4 3 2 1 8 7 6 5 12 11 10 9 ... 64 63 62 61
51
*
52
* The field is initialized with SP (whitespace) and every time the bishop moves
53
* to a field its value is incremented. The value of a field is printed using
54
* the following characters:
55
*
56
* 1: .
57
* 2: o
58
* 3: +
59
* 4: =
60
* 5: *
61
* 6: B
62
* 7: O
63
* 8: X
64
* 9: @
65
* 10: %
66
* 11: &
67
* 12: #
68
* 13: /
69
* 14: ^
70
*
71
* Exceptions: The start field is marked with 'S' and the end field with 'E'.
72
*/
73
74
static
void
drunken_bishop(
const
char
* prefix,
75
const
unsigned
char
*
data
,
size_t
data_len)
76
{
77
const
char
trace[] =
" .o+=*BOX@%&#/^SE"
;
78
const
unsigned
int
trace_start = 15U;
79
const
unsigned
int
trace_end = 16U;
80
unsigned
int
field[
DIGEST_RA_X
][
DIGEST_RA_Y
];
81
size_t
x =
DIGEST_RA_X
/ (size_t) 2;
82
size_t
y =
DIGEST_RA_Y
/ (size_t) 2;
83
size_t
x_lim =
DIGEST_RA_X
- (size_t) 1;
84
size_t
y_lim =
DIGEST_RA_Y
- (size_t) 1;
85
size_t
i;
86
unsigned
int
ii;
87
unsigned
int
move[4];
88
89
/* Initialize field */
90
for
(i = 0; i <
DIGEST_RA_Y
; ++i)
91
{
92
for
(ii = 0; (size_t) ii <
DIGEST_RA_X
; ++ii) { field[ii][i] = 0; }
93
}
94
field[x][y] = trace_start;
95
96
/* Split data into 2bit groups */
97
for
(i = 0; i < data_len; ++i)
98
{
99
for
(ii = 0; ii < 4; ++ii)
100
{
101
/* Extract direction */
102
move[ii] = ((
unsigned
int)
data
[i] & (3U << ii * 2U)) >> ii * 2U;
103
104
/* Move on field */
105
switch
(move[ii])
106
{
107
case
0U:
108
{
109
if
(x) { --x; }
110
if
(y) { --y; }
111
break
;
112
}
113
case
1U:
114
{
115
if
(x_lim > x) { ++x; }
116
if
(y) { --y; }
117
break
;
118
}
119
case
2U:
120
{
121
if
(x) { --x; }
122
if
(y_lim > y) { ++y; }
123
break
;
124
}
125
case
3U:
126
{
127
if
(x_lim > x) { ++x; }
128
if
(y_lim > y) { ++y; }
129
break
;
130
}
131
default
:
132
{
133
PRINT_ERROR
(
"Bishop was too drunk (bug)"
);
134
break
;
135
}
136
}
137
138
/* Update field content */
139
if
(14U > field[x][y]) { field[x][y] += 1U; }
140
}
141
}
142
field[x][y] = trace_end;
143
144
/* Print top line */
145
printf(
"%s+"
, prefix);
146
for
(x = 0; x <
DIGEST_RA_X
; ++x) { printf(
"-"
); }
147
printf(
"+\n"
);
148
/* Print field */
149
for
(y = 0; y <
DIGEST_RA_Y
; ++y)
150
{
151
printf(
"%s|"
, prefix);
152
for
(x = 0; x <
DIGEST_RA_X
; ++x) { printf(
"%c"
, trace[field[x][y]]); }
153
printf(
"|\n"
);
154
}
155
/* Print bottom line */
156
printf(
"%s+"
, prefix);
157
for
(x = 0; x <
DIGEST_RA_X
; ++x) { printf(
"-"
); }
158
printf(
"+\n"
);
159
160
return
;
161
}
162
163
164
/* ========================================================================== */
165
/*! \brief Create randomart image of a key
166
*
167
* \param[in] prefix Prefix to prepend for each output line
168
* \param[in] buf Pointer to data buffer
169
* \param[in] len Length of data in buffer
170
*
171
* The data from \e buf is hashed with the SHA2-256 algorithm to create a
172
* fingerprint. The first 16 bytes of this fingerprint are used to create a
173
* randomart image with the drunken bishop algorithm.
174
*
175
* \return
176
* - 0 on success
177
* - Negative value on error
178
*/
179
180
int
digest_randomart
(
const
char
* prefix,
const
char
* buf,
size_t
len)
181
{
182
int
res = -1;
183
unsigned
char
md[
DIGEST_SHA2_256_LEN
];
184
const
char
* fingerprint = NULL;
185
186
/* Calculate SHA2-256 hash of data */
187
res =
digest_sha2_256
(buf, len, md);
188
if
(!res)
189
{
190
res =
enc_mime_encode_base64
(&fingerprint, (
const
char
*) md,
191
DIGEST_SHA2_256_LEN
);
192
if
(!res)
193
{
194
printf(
"%sKey fingerprint is SHA256:%s\n"
, prefix, fingerprint);
195
/*
196
* Create randomart
197
*
198
* Use with 16 bytes of data (resulting in 64 moves of the bishop,
199
* matching a 17x9 field size).
200
*/
201
drunken_bishop(prefix, md, 16);
202
}
203
}
204
enc_free
((
void
*) fingerprint);
205
206
/* Check for error */
207
if
(res) {
PRINT_ERROR
(
"Creating randomart image failed"
); }
208
209
return
(res);
210
}
211
212
213
/*! @} */
214
215
/* EOF */
enc_free
void enc_free(void *p)
Free an object allocated by encoding module.
Definition:
encoding.c:8868
DIGEST_RA_X
#define DIGEST_RA_X
Field width: 17 units.
Definition:
digest.h:24
digest_randomart
int digest_randomart(const char *prefix, const char *buf, size_t len)
Create randomart image of a key.
Definition:
drunken_bishop.c:180
PRINT_ERROR
#define PRINT_ERROR(s)
Prepend module prefix and print error message.
Definition:
main.h:19
data
struct core_data data
Global data object (shared by all threads)
Definition:
core.c:242
DIGEST_SHA2_256_LEN
#define DIGEST_SHA2_256_LEN
256 bit
Definition:
digest.h:19
enc_mime_encode_base64
int enc_mime_encode_base64(const char **enc, const char *data, size_t len)
Encode binary data to base64.
Definition:
encoding.c:4744
digest_sha2_256
int digest_sha2_256(const char *text, size_t text_len, unsigned char *md)
Secure Hash Algorithm SHA2-256.
Definition:
digest.c:182
DIGEST_RA_Y
#define DIGEST_RA_Y
Field height: 9 units.
Definition:
digest.h:25
Generated at 2024-04-27 using