qrcrypt/compact_ecdh_curve25519.py

17 lines
867 B
Python

leu=lambda b:sum(b[i]<<(i*8)for i in range(len(b)))
p=2**255-19
decU=lambda b:leu(b[:-1]+bytes([b[-1]&127]))
mask=lambda x:sum(x>>i|x<<i for i in range(255))
def cs(s,a,b):d=mask(s)&(a^b);a=a^d;b=b^d;return a,b
def x25519(k,u):
k=bytearray(k);k[0]&=248;k[31]&=127;k[31]|=64;k=leu(k);u=decU(u)
x1=u;x2=1;z2=0;x3=u;z3=1;s=0
for t in range(254,-1,-1):kt=(k>>t)&1;s^=kt;x2,x3=cs(s,x2,x3);z2,z3=cs(s,z2,z3);s=kt;A=(x2+z2)%p;AA=pow(A,2,p);B=(x2-z2)%p;BB=pow(B,2,p);E=(AA-BB)%p;C=(x3+z3)%p;D=(x3-z3)%p;DA=(D*A)%p;CB=(C*B)%p;x3=pow((DA+CB)%p,2,p);z3=(x1*pow((DA-CB)%p,2,p))%p;x2=(AA*BB)%p;z2=(E*((AA+(121665*E)%p)%p)%p)%p
x2,x3=cs(s,x2,x3);z2,z3=cs(s,z2,z3);u=(x2*pow(z2,p-2,p))%p;return bytes(u>>i&255 for i in range(0,255,8))
pubkey=lambda sk:x25519(sk,b'\x09'+b'\x00'*31)
def ecdh(pk,sk):
k=x25519(sk,pk);o=0
for i in k:o|=i
if o==0:raise ValueError
else:return k