58 lines
1.3 KiB
Python
58 lines
1.3 KiB
Python
"""Curve25519/ed25519 helpers.
|
|
|
|
Sourced from https://github.com/warner/python-pure25519/blob/master/pure25519/basic.py
|
|
"""
|
|
# pylint: disable = invalid-name
|
|
Q = 2 ** 255 - 19
|
|
L = 2 ** 252 + 27742317777372353535851937790883648493
|
|
|
|
|
|
def _inv(x):
|
|
return pow(x, Q - 2, Q)
|
|
|
|
|
|
d = -121665 * _inv(121666)
|
|
I = pow(2, (Q - 1) // 4, Q) # noqa: E741
|
|
|
|
|
|
def _xrecover(y):
|
|
xx = (y * y - 1) * _inv(d * y * y + 1)
|
|
x = pow(xx, (Q + 3) // 8, Q)
|
|
if (x * x - xx) % Q != 0:
|
|
x = (x * I) % Q
|
|
if x % 2 != 0:
|
|
x = Q - x
|
|
return x
|
|
|
|
|
|
def _isoncurve(P):
|
|
x = P[0]
|
|
y = P[1]
|
|
return (-x * x + y * y - 1 - d * x * x * y * y) % Q == 0
|
|
|
|
|
|
class NotOnCurve(Exception):
|
|
"""Raised when point fall off the curve."""
|
|
|
|
|
|
def _decodepoint(unclamped: int):
|
|
clamp = (1 << 255) - 1
|
|
y = unclamped & clamp # clear MSB
|
|
x = _xrecover(y)
|
|
if bool(x & 1) != bool(unclamped & (1 << 255)):
|
|
x = Q - x
|
|
P = [x, y]
|
|
if not _isoncurve(P):
|
|
raise NotOnCurve("decoding point that is not on curve")
|
|
return P
|
|
|
|
|
|
def is_on_curve(s: bytes) -> bool:
|
|
"""Verify the bytes s is a valid point on curve or not."""
|
|
unclamped = int.from_bytes(s, byteorder="little")
|
|
try:
|
|
_ = _decodepoint(unclamped)
|
|
except NotOnCurve:
|
|
return False
|
|
else:
|
|
return True
|