Skip to content

Instantly share code, notes, and snippets.

@infinity0
Last active October 14, 2015 17:53
Show Gist options
  • Save infinity0/a8a46081a29e47164603 to your computer and use it in GitHub Desktop.
Save infinity0/a8a46081a29e47164603 to your computer and use it in GitHub Desktop.
how to combine two x25519 private keys
#!/usr/bin/python3 -i
from nacl.bindings import *
from binascii import b2a_hex
BO = "little"
order_b = 2**252 + 27742317777372353535851937790883648493
order = 8 * order_b
to_canonical_i = lambda x: x & 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 | 0x4000000000000000000000000000000000000000000000000000000000000000
to_canonical = lambda s: to_canonical_i(int.from_bytes(s, byteorder=BO)).to_bytes(32, byteorder=BO)
j = crypto_box_keypair()
k = crypto_box_keypair()
assert j[0] == crypto_scalarmult_base(to_canonical(j[1]))
assert k[0] == crypto_scalarmult_base(to_canonical(k[1]))
expected = crypto_scalarmult(j[1], crypto_scalarmult_base(k[1]))
assert crypto_scalarmult(k[1], crypto_scalarmult_base(j[1])) == expected
# the above is standard DH agreement
s_mult_base = lambda i: crypto_scalarmult_base(i.to_bytes(32, BO))
s_mult = lambda i, p: crypto_scalarmult(i.to_bytes(32, BO), p)
ji = int.from_bytes(to_canonical(j[1]), byteorder=BO)
ki = int.from_bytes(to_canonical(k[1]), byteorder=BO)
mi = (ji * ki) % order
print("DH exchange between 2 values: %s" % b2a_hex(expected))
if mi != to_canonical_i(mi):
print("j*k is not a canonical secret key, so this will not work with real x25519 APIs :( try again...")
else:
assert s_mult_base(mi) == expected
print("combining 2 values, then exp: %s" % b2a_hex(s_mult_base(mi)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment