1

159 lines
3.8 KiB
Python

from browser import document, alert
import base64
import hashlib
_version = 2
def execLayerSeq(layers, msg, key, decode=False):
# Make sure to reverse layers for decoding
if decode:
for layer in layers[::-1]:
msg, key = layer.decode(msg, key)
else:
for layer in layers:
msg, key = layer.encode(msg, key)
return msg
class BitshiftLayer(object):
def encode(self, file, key):
# Encode once to allow for binary data
file = base64.b85encode(file.encode())
output = ""
# Iterate and shift
for i, byte in enumerate(file):
# Mod the current bit
output += chr(byte ^ key[i%len(key) - 1])
# Mod the key
key.append(i%key[0])
# Final encoding
output = base64.b85encode(output.encode())
# Return as string
return (output.decode(), key)
def decode(self, file, key):
# Decode the file to shifted bytes
try:
file = base64.b85decode(file.strip().encode())
except:
return ("INVALID DATA", key)
output = ""
for i, byte in enumerate(file):
# Unmod the current byte
mod = byte ^ key[i%len(key) - 1]
if mod not in range(0x110000):
mod = 0
output += chr(mod)
# Mod the current key
key.append(i%key[0])
# Pull the resulting b64 back to binary if needed
# This may fail due to "incorrect padding" from a wrong key
# Just return some random text in this case for now
try:
output = base64.b85decode(output.encode()).decode()
except:
output = output
# Return as bytes
return (output, key)
class DataHeaderLayer(object):
def encode(self, file, key):
version = _version
fdl = len(file)
base = 85
# Construct header
header = []
header.append(version)
header += list((fdl & 0xFFFFFFFF).to_bytes(4, 'big'))
header += list((base & 0xFFFFFFFF).to_bytes(2, 'big'))
header = base64.b64encode(bytes(header)).decode()
return (header + file, key)
def decode(self, file, key):
# Header is the first 12 chars
header = file[:12]
file = file[12:]
try:
header = base64.b64decode(header.encode())
except:
return ("INVALID DATA", key)
header = bytes(header)
version = header[0]
# Conversion failed if the version is incorrect
if version != _version:
return ("INVALID DATA", key)
fdl = header[:5][1:]
fdl = int.from_bytes(fdl, byteorder='big')
# Chop off possible extra data
file = file[:fdl]
return (file, key)
def key2shifts(key: str) -> list:
output = []
for char in key:
output.append(ord(char))
return output
crypt_layers = [
DataHeaderLayer(),
BitshiftLayer()
]
def encode(file, key):
return execLayerSeq(crypt_layers, file, key)
def decode(file, key):
return execLayerSeq(crypt_layers, file, key, decode=True)
tx = encode("Hello", key2shifts("123"))
# alert("test:" + tx)
def doShiftDemo(_):
do_encode = bool(document["encode"].checked)
if do_encode:
key = document["key"].value
msg = document["msg"].value
new_msg = encode(msg, key2shifts(key))
document["msg"].value = new_msg
else:
key = document["key"].value
msg = document["msg"].value
new_msg = decode(msg, key2shifts(key))
document["msg"].value = new_msg
document["shift-button"].bind("click", doShiftDemo)
# Set the button
document["shift-button"].innerHTML = "Run Shift2"
document["shift-button"].disabled = False