|
@ -1,6 +1,8 @@ |
|
|
#!/usr/bin/env python |
|
|
#!/usr/bin/env python |
|
|
|
|
|
|
|
|
|
|
|
import argparse |
|
|
import sys |
|
|
import sys |
|
|
|
|
|
import time |
|
|
|
|
|
|
|
|
from hashlib import sha256 |
|
|
from hashlib import sha256 |
|
|
from binascii import hexlify, unhexlify |
|
|
from binascii import hexlify, unhexlify |
|
@ -139,6 +141,16 @@ def get_pos_y_for_x(pubkey_x, yneg=0): |
|
|
if pub_key_x is not None: OpenSSL.BN_free(pub_key_x) |
|
|
if pub_key_x is not None: OpenSSL.BN_free(pub_key_x) |
|
|
if pub_key_y is not None: OpenSSL.BN_free(pub_key_y) |
|
|
if pub_key_y is not None: OpenSSL.BN_free(pub_key_y) |
|
|
|
|
|
|
|
|
|
|
|
def ec_decompress(pubkey, curve='secp256k1'): |
|
|
|
|
|
if pubkey[0] == '\x02' or pubkey[0] == '\x03': |
|
|
|
|
|
yneg = ord(pubkey[0]) & 1 |
|
|
|
|
|
pubkey = "\x04" + pubkey[1:] + get_pos_y_for_x(pubkey[1:], yneg=yneg) |
|
|
|
|
|
elif pubkey[0] == '\x04': |
|
|
|
|
|
pass |
|
|
|
|
|
else: |
|
|
|
|
|
raise Exception("Unrecognised pubkey format: %s" % (pubkey,)) |
|
|
|
|
|
return pubkey |
|
|
|
|
|
|
|
|
class Onion(object): |
|
|
class Onion(object): |
|
|
HMAC_LEN = 32 |
|
|
HMAC_LEN = 32 |
|
|
PKEY_LEN = 32 |
|
|
PKEY_LEN = 32 |
|
@ -282,48 +294,52 @@ class OnionEncrypt(Onion): |
|
|
msgenc += hmac_sha256(hmacs[i], msgenc) |
|
|
msgenc += hmac_sha256(hmacs[i], msgenc) |
|
|
self.onion = msgenc |
|
|
self.onion = msgenc |
|
|
|
|
|
|
|
|
def decode_from_file(f): |
|
|
def generate(args): |
|
|
keys = [] |
|
|
server_keys = [] |
|
|
msg = "" |
|
|
msgs = [] |
|
|
for ln in f.readlines(): |
|
|
for k in args.pubkeys: |
|
|
if ln.startswith(" * Keypair "): |
|
|
k = unhexlify(k) |
|
|
w = ln.strip().split() |
|
|
msgs.append("Message for %s..." % (hexlify(k[1:21]),)) |
|
|
idx = int(w[2].strip(":")) |
|
|
k = ec_decompress(k) |
|
|
priv = unhexlify(w[3]) |
|
|
server_keys.append(k) |
|
|
pub = unhexlify(w[4]) |
|
|
o = OnionEncrypt(msgs, server_keys) |
|
|
assert idx == len(keys) |
|
|
sys.stdout.write(o.onion) |
|
|
keys.append(ecc.ECC(privkey=priv, pubkey=pub, curve='secp256k1')) |
|
|
return |
|
|
elif ln.startswith(" * Message:"): |
|
|
|
|
|
msg = unhexlify(ln[11:].strip()) |
|
|
def decode(args): |
|
|
elif ln.startswith("Decrypting"): |
|
|
msg = sys.stdin.read() |
|
|
pass |
|
|
key = ecc.ECC(privkey=unhexlify(args.seckey), |
|
|
else: |
|
|
pubkey=ec_decompress(unhexlify(args.pubkey)), |
|
|
print ln |
|
|
curve='secp256k1') |
|
|
assert ln.strip() == "" |
|
|
o = OnionDecrypt(msg, key) |
|
|
|
|
|
o.decrypt() |
|
|
assert msg != "" |
|
|
#sys.stderr.write("Message: \"%s\"\n" % (o.msg,)) |
|
|
for k in keys: |
|
|
want_msg = "Message for %s..." % (args.pubkey[2:42]) |
|
|
o = OnionDecrypt(msg, k) |
|
|
if o.msg != want_msg + "\0"*(Onion.MSG_LEN - len(want_msg)): |
|
|
o.decrypt() |
|
|
raise Exception("Unexpected message: \"%s\" (wanted: %s)" % (o.msg, want_msg)) |
|
|
print o.msg |
|
|
|
|
|
msg = o.fwd |
|
|
sys.stdout.write(o.fwd) |
|
|
print "done" |
|
|
|
|
|
|
|
|
def main(argv): |
|
|
|
|
|
parser = argparse.ArgumentParser(description="Process some integers.") |
|
|
|
|
|
sp = parser.add_subparsers() |
|
|
|
|
|
p = sp.add_parser("generate") |
|
|
|
|
|
p.add_argument("pubkeys", nargs='+', help="public keys of recipients") |
|
|
|
|
|
p.set_defaults(func=generate) |
|
|
|
|
|
|
|
|
|
|
|
p = sp.add_parser("decode") |
|
|
|
|
|
p.add_argument("seckey", help="secret key for router") |
|
|
|
|
|
p.add_argument("pubkey", help="public key for router") |
|
|
|
|
|
p.set_defaults(func=decode) |
|
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args(argv) |
|
|
|
|
|
|
|
|
|
|
|
return args.func(args) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
if __name__ == "__main__": |
|
|
if len(sys.argv) > 1 and sys.argv[1] == "generate": |
|
|
main(sys.argv[1:]) |
|
|
if len(sys.argv) == 3: |
|
|
sys.exit(0) |
|
|
n = int(sys.argv[2]) |
|
|
|
|
|
else: |
|
|
|
|
|
n = 20 |
|
|
|
|
|
servers = [ecc.ECC(curve='secp256k1') for _ in range(n)] |
|
|
|
|
|
server_pubs = [s.get_pubkey() for s in servers] |
|
|
|
|
|
msgs = ["Howzit %d..." % (i,) for i in range(n)] |
|
|
|
|
|
|
|
|
|
|
|
o = OnionEncrypt(msgs, server_pubs) |
|
|
|
|
|
|
|
|
|
|
|
for i, s in enumerate(servers): |
|
|
|
|
|
print " * Keypair %d: %s %s" % ( |
|
|
|
|
|
i, hexlify(s.privkey), hexlify(s.get_pubkey())) |
|
|
|
|
|
print " * Message: %s" % (hexlify(o.onion)) |
|
|
|
|
|
else: |
|
|
|
|
|
decode_from_file(sys.stdin) |
|
|
|
|
|