diff --git a/compact_chapoly.py b/compact_chapoly.py new file mode 100644 index 0000000..42d2698 --- /dev/null +++ b/compact_chapoly.py @@ -0,0 +1,28 @@ +def u(b): + n=0 + for i in range(len(b)):n|=b[i]<<(i*8) + return n +unu=lambda n,l:bytes(n>>i&255 for i in range(0,l,8)) +add=lambda x,y:x+y&0xffffffff +rotl=lambda x,n:x<>32-n +def qr(a,b,c,d):a=add(a,b);d^=a;d=rotl(d,16);c=add(c,d);b^=c;b=rotl(b,12);a=add(a,b);d^=a;d=rotl(d,8);c=add(c,d);b^=c;b=rotl(b,7);return a,b,c,d +def ccb(k,c,n): + s=[0x61707865,0x3320646e,0x79622d32,0x6b206574,u(k[:4]),u(k[4:8]),u(k[8:12]),u(k[12:16]),u(k[16:20]),u(k[20:24]),u(k[24:28]),u(k[28:]),c,u(n[:4]),u(n[4:8]),u(n[8:])] + o=s[:] + def x(a,b,c,d):s[a],s[b],s[c],s[d]=qr(s[a],s[b],s[c],s[d]) + for _ in range(10):x(0,4,8,12);x(1,5,9,13);x(2,6,10,14);x(3,7,11,15);x(0,5,10,15);x(1,6,11,12);x(2,7,8,13);x(3,4,9,14) + return b''.join(unu(add(o[i],s[i]),32)for i in range(len(s))) +cd=lambda a,b:a//b if a%b==0 else a//b+1 +def chacha20(k,c,n,m): + for i in range(cd(len(m),64)):yield from(a^b for a,b in zip(m[i*64:i*64+64],ccb(k,c+i,n))) +def poly1305(m,k): + r=bytearray(k[:16]);r[3]&=15;r[7]&=15;r[11]&=15;r[15]&=15;r[4]&=252;r[8]&=252;r[12]&=252;r=u(r);s=u(k[16:]);P=2**130-5;a=0 + for i in range(cd(len(m),16)):a=(a+u(m[i*16:i*16+16]+b'\x01'))*r%P + return unu(a+s,128) +p16=lambda x:b'\x00'*(-len(x)%16) +tag=lambda a,k,n,c:poly1305(b''.join((a,p16(a),c,p16(c),unu(len(a),64),unu(len(c),64))),ccb(k,0,n)[:32]) +def enc(a,k,i,f,p):c=bytes(chacha20(k,1,f+i,p));return c+tag(a,k,f+i,c) +def dec(a,k,i,f,e): + c=e[:-16] + if not secrets.compare_digest(e[-16:],tag(a,k,f+i,c)):return None + return bytes(chacha20(k,1,f+i,c))