99 lines
2.4 KiB
Python
99 lines
2.4 KiB
Python
|
import base64
|
||
|
import sys
|
||
|
import argparse
|
||
|
|
||
|
def urlsafe_b64encode_no_pad(b: bytes) -> str:
|
||
|
"""
|
||
|
Removes any `=` used as padding from the encoded string.
|
||
|
"""
|
||
|
return base64.urlsafe_b64encode(b).decode().rstrip("=")
|
||
|
|
||
|
|
||
|
def urlsafe_b64decode_no_pad(s: str) -> bytes:
|
||
|
"""
|
||
|
Adds back in the required padding before decoding.
|
||
|
"""
|
||
|
padding = 4 - (len(s) % 4)
|
||
|
s = s + ("=" * padding)
|
||
|
return base64.urlsafe_b64decode(s)
|
||
|
|
||
|
|
||
|
def do_value(args):
|
||
|
|
||
|
key = urlsafe_b64decode_no_pad(args.key)
|
||
|
|
||
|
print("key:", key.hex())
|
||
|
|
||
|
|
||
|
def dist(key1: bytes, key2: bytes) -> bytes:
|
||
|
distance = bytearray(len(key1))
|
||
|
for n in range(len(key1)):
|
||
|
distance[n] = key1[n] ^ key2[n]
|
||
|
|
||
|
return bytes(distance)
|
||
|
|
||
|
|
||
|
def do_distance(args):
|
||
|
|
||
|
key1 = urlsafe_b64decode_no_pad(args.key1)
|
||
|
key2 = urlsafe_b64decode_no_pad(args.key2)
|
||
|
|
||
|
print("key1:", key1.hex())
|
||
|
print("key2:", key2.hex())
|
||
|
|
||
|
distance = dist(key1, key2)
|
||
|
print("dist:", distance.hex())
|
||
|
|
||
|
def keycmp(key1: bytes, key2: bytes) -> int:
|
||
|
for n in range(len(key1)):
|
||
|
if key1[n] < key2[n]:
|
||
|
return -1
|
||
|
if key1[n] > key2[n]:
|
||
|
return 1
|
||
|
return 0
|
||
|
|
||
|
def do_closer(args):
|
||
|
|
||
|
key = urlsafe_b64decode_no_pad(args.key)
|
||
|
near = urlsafe_b64decode_no_pad(args.near)
|
||
|
far = urlsafe_b64decode_no_pad(args.far)
|
||
|
|
||
|
print(" key:", key.hex())
|
||
|
print("near:", near.hex())
|
||
|
print(" far:", far.hex())
|
||
|
|
||
|
distance_near = dist(key, near)
|
||
|
distance_far = dist(key, far)
|
||
|
|
||
|
print(" dn:", distance_near.hex())
|
||
|
print(" df:", distance_far.hex())
|
||
|
|
||
|
c = keycmp(distance_near, distance_far)
|
||
|
print(" cmp:", c)
|
||
|
|
||
|
def main():
|
||
|
parser = argparse.ArgumentParser()
|
||
|
subparsers = parser.add_subparsers(required=True)
|
||
|
|
||
|
parser_value = subparsers.add_parser('value')
|
||
|
parser_value.add_argument('key', type=str)
|
||
|
parser_value.set_defaults(func=do_value)
|
||
|
|
||
|
parser_value = subparsers.add_parser('distance')
|
||
|
parser_value.add_argument('key1', type=str)
|
||
|
parser_value.add_argument('key2', type=str)
|
||
|
parser_value.set_defaults(func=do_distance)
|
||
|
|
||
|
parser_value = subparsers.add_parser('closer')
|
||
|
parser_value.add_argument('key', type=str)
|
||
|
parser_value.add_argument('near', type=str)
|
||
|
parser_value.add_argument('far', type=str)
|
||
|
parser_value.set_defaults(func=do_closer)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
args.func(args)
|
||
|
|
||
|
sys.exit(0)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|