Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
Support Ed25519 in kh2reg.py.
Browse files Browse the repository at this point in the history
  • Loading branch information
sgtatham committed Mar 25, 2016
1 parent 5e884cf commit c722b2f
Showing 1 changed file with 42 additions and 3 deletions.
45 changes: 42 additions & 3 deletions contrib/kh2reg.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def strtolong(s):
bytes = struct.unpack(">%luB" % len(s), s)
return reduce ((lambda a, b: (long(a) << 8) + long(b)), bytes)

def strtolong_le(s):
"Convert arbitrary-length little-endian binary data to a Python long"
bytes = reversed(struct.unpack(">%luB" % len(s), s))
return reduce ((lambda a, b: (long(a) << 8) + long(b)), bytes)

def longtohex(n):
"""Convert long int to lower-case hex.
Expand Down Expand Up @@ -173,10 +178,44 @@ def __init__(self, msg):
keyparams = [curvename] + map (strtolong, [x,y])

elif sshkeytype == "ssh-ed25519":
# FIXME: these are always stored point-compressed, which
# requires actual maths
raise KeyFormatError("can't convert ssh-ed25519 yet, sorry")
keytype = sshkeytype

if len(subfields) != 2:
raise KeyFormatError("wrong number of subfields in blob")
if subfields[0] != sshkeytype:
raise KeyFormatError("key type mismatch ('%s' vs '%s')"
% (sshkeytype, subfields[0]))
# Key material y, with the top bit being repurposed as
# the expected parity of the associated x (point
# compression).
y = strtolong_le(subfields[1])
x_parity = y >> 255
y &= ~(1 << 255)

# Standard Ed25519 parameters.
p = 2**255 - 19
d = 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3

# Recover x^2 = (y^2 - 1) / (d y^2 + 1).
#
# With no real time constraints here, it's easier to
# take the inverse of the denominator by raising it to
# the power p-2 (by Fermat's Little Theorem) than
# faffing about with the properly efficient Euclid
# method.
xx = (y*y - 1) * pow(d*y*y + 1, p-2, p) % p

# Take the square root, which may require trying twice.
x = pow(xx, (p+3)/8, p)
if pow(x, 2, p) != xx:
x = x * pow(2, (p-1)/4, p) % p
assert pow(x, 2, p) == xx

# Pick the square root of the correct parity.
if (x % 2) != x_parity:
x = p - x

keyparams = [x, y]
else:
raise UnknownKeyType(sshkeytype)

Expand Down

0 comments on commit c722b2f

Please sign in to comment.