Skip to content

Instantly share code, notes, and snippets.

@parsa
Created April 1, 2023 00:15
Show Gist options
  • Save parsa/ec92bf07ddedec09d487553a0fc67f77 to your computer and use it in GitHub Desktop.
Save parsa/ec92bf07ddedec09d487553a0fc67f77 to your computer and use it in GitHub Desktop.
Drunken Bishop
# https://codegolf.stackexchange.com/questions/59670/the-drunken-bishop
def h(f):
# Alias 17 because it gets used enough times for this to save bytes
w = 17
h = 9
# Input parsing
s = [f"{int(g,16)>>s&3:02b}" for g in f.split(":") for s in (0, 2, 4, 6)]
# Room setup
r = [0] * w * h
p = 76
# Apply movements
for d in s:
r[p] += 1
p += (-(p % w != 0), p % w != 16)[int(d[1])] + (
-w * (p // w != 0),
w * (p // w != 8),
)[int(d[0])]
r[76] = 15 # Set start position
r[p] = 16 # Set end position
# Display result
b = "+" + "-" * w + "+"
print(b)
i = 0
while i < w * h:
print(f"|{''.join(' .o+=*BOX@%&#/^SE'[c]for c in r[i:i+w])}|")
i += w
print(b)
h("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48")
drunken_bishop("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48", "md5")
h("b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b")
drunken_bishop("b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b", "md5")
h("05:1e:1e:c1:ac:b9:d1:1c:6a:60:ce:0f:77:6c:78:47")
drunken_bishop("05:1e:1e:c1:ac:b9:d1:1c:6a:60:ce:0f:77:6c:78:47", "md5")
# https://stackoverflow.com/questions/30082230/a-command-to-display-a-a-keys-randomart-image-from-a-fingerprint/41208301#41208301
#!/usr/bin/env python
# NOTE: Requires Python 3+
# usage: drunken_bishop.py [-h] [--mode {md5,sha256}] fingerprint
#
# Generate randomart from fingerprint
#
# positional arguments:
# fingerprint
#
# optional arguments:
# -h, --help show this help message and exit
# --mode {md5,sha256}, -m {md5,sha256}
import argparse
import base64
def simulate_bishop_stumbles(steps):
field = [[0] * 17 for _ in range(9)]
start_position = (4, 8)
direction_map = {
"00": (-1, -1),
"01": (-1, 1),
"10": (1, -1),
"11": (1, 1),
}
def clip_at_walls(x, y):
return min(max(x, 0), 8), min(max(y, 0), 16)
pos = start_position
for step in steps:
x, y = pos
field[x][y] += 1
dx, dy = direction_map[step]
pos = clip_at_walls(x + dx, y + dy)
x, y = start_position
field[x][y] = 15
x, y = pos
field[x][y] = 16
return field
def get_steps(fingerprint_bytes):
return [
"{:02b}".format(b >> s & 3) for b in fingerprint_bytes for s in (0, 2, 4, 6)
]
def print_randomart(atrium, hash_mode):
# Symbols for the number of times a position is visited by the bishop
# White space means that the position was never visited
# S and E are the start and end positions
value_symbols = " .o+=*BOX@%&#/^SE"
print("+---[ n/a ]----+")
for row in atrium:
symbolic_row = [value_symbols[visits] for visits in row]
print("|" + "".join(symbolic_row) + "|")
print("+" + ("[" + hash_mode.upper() + "]").center(17, "-") + "+")
def get_bytes(fingerprint, hash_mode):
if hash_mode == "md5":
return [int(i, 16) for i in fingerprint.split(":")]
elif hash_mode == "sha256":
missing_padding = 4 - (len(fingerprint) % 4)
fingerprint += "=" * missing_padding
return base64.b64decode(fingerprint)
raise RuntimeError("Unsupported hashing mode: {}".format(hash_mode))
def get_argparser():
parser = argparse.ArgumentParser(description="Generate randomart from fingerprint")
parser.add_argument("--mode", "-m", choices=["md5", "sha256"], default="sha256")
parser.add_argument("fingerprint", type=str)
return parser
def drunken_bishop(fingerprint, hash_mode):
fingerprint_bytes = get_bytes(fingerprint, hash_mode)
steps = get_steps(fingerprint_bytes)
atrium_state = simulate_bishop_stumbles(steps)
print_randomart(atrium_state, hash_mode)
# if __name__ == "__main__":
# parser = get_argparser()
# args = parser.parse_args()
# drunken_bishop(args.fingerprint, args.mode)
# drunken_bishop("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48", "md5")
drunken_bishop("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48", "md5")
# drunken_bishop("uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s", "sha256")
# Ported from https://github.com/openssh/openssh-portable/blob/f703757234a5c585553e72bba279b255a272750a/sshkey.c#L1005-L1100
import base64
FLDSIZE_X = 17
FLDSIZE_Y = 9
def get_bytes(fingerprint, hash_mode):
if hash_mode == "md5":
return [int(i, 16) for i in fingerprint.split(":")]
elif hash_mode == "sha256":
missing_padding = 4 - (len(fingerprint) % 4)
fingerprint += "=" * missing_padding
return base64.b64decode(fingerprint)
raise RuntimeError("Unsupported hashing mode: {}".format(hash_mode))
def fingerprint_randomart(alg, dgst_raw):
# Chars to be used after each other every time the worm intersects with itself.
# Matter of taste.
augmentation_string = " .o+=*BOX@%&#/^SE"
retval = " " * (FLDSIZE_X + 3) * (FLDSIZE_Y + 2)
# Initialize field
field = [[0] * FLDSIZE_Y for _ in range(FLDSIZE_X)]
x = FLDSIZE_X // 2
y = FLDSIZE_Y // 2
# Process raw key
for input in dgst_raw:
for b in range(4):
# Evaluate 2 bit, rest is shifted later
x += 1 if input & 0x1 else -1
y += 1 if input & 0x2 else -1
# Assure we are still in bounds
x = max(0, min(x, FLDSIZE_X - 1))
y = max(0, min(y, FLDSIZE_Y - 1))
# Augment the field
if field[x][y] < len(augmentation_string) - 2:
field[x][y] += 1
input = input >> 2
# Mark starting point and end point
field[FLDSIZE_X // 2][FLDSIZE_Y // 2] = len(augmentation_string) - 1
field[x][y] = len(augmentation_string) - 0
# Assemble title
title = "[ n/a ]"
# Assemble hash ID
hash_id = f"[{alg}]"
# Output upper border
p = 0
retval = "+" + "-" * ((FLDSIZE_X - len(title)) // 2) + title + "-" * ((FLDSIZE_X - len(title)) // 2) + "+\n"
# Output content
for y in range(FLDSIZE_Y):
retval += "|"
for x in range(FLDSIZE_X):
retval += augmentation_string[min(field[x][y], len(augmentation_string) - 1)]
retval += "|\n"
# Output lower border
retval += "+" + "-" * ((FLDSIZE_X - len(hash_id)) // 2) + hash_id + "-" * ((FLDSIZE_X - len(hash_id)) // 2) + "+"
return retval
dgst_raw = get_bytes("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48", "md5")
k = "0"
print(fingerprint_randomart("MD5", dgst_raw))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment