import secrets u=lambda b:sum(b[i]<<(i*8)for i in range(len(b))) 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,f): if c>=1<<32: raise ValueError 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[:] if f:o=[0]*16 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,0))) 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,0)[:32]) def cpe(a,k,n,p):c=bytes(chacha20(k,1,n,p));return c+tag(a,k,n,c) def cpd(a,k,n,e): c=e[:-16] if not secrets.compare_digest(e[-16:],tag(a,k,n,c)):return None return bytes(chacha20(k,1,n,c)) def hchacha20(k,n):s=ccb(k,u(n[:4]),n[4:],1);return s[:16]+s[48:] def enc(a,k,n,p):k=hchacha20(k, n[:16]);n=b'\x00'*4+n[16:];return cpe(a,k,n,p) def dec(a,k,n,c):k=hchacha20(k, n[:16]);n=b'\x00'*4+n[16:];return cpd(a,k,n,c)