Created
April 1, 2023 00:15
-
-
Save parsa/ec92bf07ddedec09d487553a0fc67f77 to your computer and use it in GitHub Desktop.
Drunken Bishop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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