|
1 | 1 | #!/usr/bin/env python
|
2 | 2 |
|
| 3 | +import argparse |
3 | 4 | import sys
|
| 5 | +import time |
4 | 6 |
|
5 | 7 | from hashlib import sha256
|
6 | 8 | from binascii import hexlify, unhexlify
|
@@ -139,6 +141,16 @@ def get_pos_y_for_x(pubkey_x, yneg=0):
|
139 | 141 | if pub_key_x is not None: OpenSSL.BN_free(pub_key_x)
|
140 | 142 | if pub_key_y is not None: OpenSSL.BN_free(pub_key_y)
|
141 | 143 |
|
| 144 | +def ec_decompress(pubkey, curve='secp256k1'): |
| 145 | + if pubkey[0] == '\x02' or pubkey[0] == '\x03': |
| 146 | + yneg = ord(pubkey[0]) & 1 |
| 147 | + pubkey = "\x04" + pubkey[1:] + get_pos_y_for_x(pubkey[1:], yneg=yneg) |
| 148 | + elif pubkey[0] == '\x04': |
| 149 | + pass |
| 150 | + else: |
| 151 | + raise Exception("Unrecognised pubkey format: %s" % (pubkey,)) |
| 152 | + return pubkey |
| 153 | + |
142 | 154 | class Onion(object):
|
143 | 155 | HMAC_LEN = 32
|
144 | 156 | PKEY_LEN = 32
|
@@ -282,48 +294,52 @@ def __init__(self, msgs, pubkeys):
|
282 | 294 | msgenc += hmac_sha256(hmacs[i], msgenc)
|
283 | 295 | self.onion = msgenc
|
284 | 296 |
|
285 |
| -def decode_from_file(f): |
286 |
| - keys = [] |
287 |
| - msg = "" |
288 |
| - for ln in f.readlines(): |
289 |
| - if ln.startswith(" * Keypair "): |
290 |
| - w = ln.strip().split() |
291 |
| - idx = int(w[2].strip(":")) |
292 |
| - priv = unhexlify(w[3]) |
293 |
| - pub = unhexlify(w[4]) |
294 |
| - assert idx == len(keys) |
295 |
| - keys.append(ecc.ECC(privkey=priv, pubkey=pub, curve='secp256k1')) |
296 |
| - elif ln.startswith(" * Message:"): |
297 |
| - msg = unhexlify(ln[11:].strip()) |
298 |
| - elif ln.startswith("Decrypting"): |
299 |
| - pass |
300 |
| - else: |
301 |
| - print ln |
302 |
| - assert ln.strip() == "" |
303 |
| - |
304 |
| - assert msg != "" |
305 |
| - for k in keys: |
306 |
| - o = OnionDecrypt(msg, k) |
307 |
| - o.decrypt() |
308 |
| - print o.msg |
309 |
| - msg = o.fwd |
310 |
| - print "done" |
| 297 | +def generate(args): |
| 298 | + server_keys = [] |
| 299 | + msgs = [] |
| 300 | + for k in args.pubkeys: |
| 301 | + k = unhexlify(k) |
| 302 | + msgs.append("Message for %s..." % (hexlify(k[1:21]),)) |
| 303 | + k = ec_decompress(k) |
| 304 | + server_keys.append(k) |
| 305 | + o = OnionEncrypt(msgs, server_keys) |
| 306 | + sys.stdout.write(o.onion) |
| 307 | + return |
| 308 | + |
| 309 | +def decode(args): |
| 310 | + msg = sys.stdin.read() |
| 311 | + key = ecc.ECC(privkey=unhexlify(args.seckey), |
| 312 | + pubkey=ec_decompress(unhexlify(args.pubkey)), |
| 313 | + curve='secp256k1') |
| 314 | + o = OnionDecrypt(msg, key) |
| 315 | + o.decrypt() |
| 316 | + #sys.stderr.write("Message: \"%s\"\n" % (o.msg,)) |
| 317 | + want_msg = "Message for %s..." % (args.pubkey[2:42]) |
| 318 | + if o.msg != want_msg + "\0"*(Onion.MSG_LEN - len(want_msg)): |
| 319 | + raise Exception("Unexpected message: \"%s\" (wanted: %s)" % (o.msg, want_msg)) |
| 320 | + |
| 321 | + sys.stdout.write(o.fwd) |
| 322 | + |
| 323 | +def main(argv): |
| 324 | + parser = argparse.ArgumentParser(description="Process some integers.") |
| 325 | + sp = parser.add_subparsers() |
| 326 | + p = sp.add_parser("generate") |
| 327 | + p.add_argument("pubkeys", nargs='+', help="public keys of recipients") |
| 328 | + p.set_defaults(func=generate) |
| 329 | + |
| 330 | + p = sp.add_parser("decode") |
| 331 | + p.add_argument("seckey", help="secret key for router") |
| 332 | + p.add_argument("pubkey", help="public key for router") |
| 333 | + p.set_defaults(func=decode) |
| 334 | + |
| 335 | + args = parser.parse_args(argv) |
| 336 | + |
| 337 | + return args.func(args) |
| 338 | + |
| 339 | + |
| 340 | + |
311 | 341 |
|
312 | 342 | if __name__ == "__main__":
|
313 |
| - if len(sys.argv) > 1 and sys.argv[1] == "generate": |
314 |
| - if len(sys.argv) == 3: |
315 |
| - n = int(sys.argv[2]) |
316 |
| - else: |
317 |
| - n = 20 |
318 |
| - servers = [ecc.ECC(curve='secp256k1') for _ in range(n)] |
319 |
| - server_pubs = [s.get_pubkey() for s in servers] |
320 |
| - msgs = ["Howzit %d..." % (i,) for i in range(n)] |
321 |
| - |
322 |
| - o = OnionEncrypt(msgs, server_pubs) |
323 |
| - |
324 |
| - for i, s in enumerate(servers): |
325 |
| - print " * Keypair %d: %s %s" % ( |
326 |
| - i, hexlify(s.privkey), hexlify(s.get_pubkey())) |
327 |
| - print " * Message: %s" % (hexlify(o.onion)) |
328 |
| - else: |
329 |
| - decode_from_file(sys.stdin) |
| 343 | + main(sys.argv[1:]) |
| 344 | + sys.exit(0) |
| 345 | + |
0 commit comments