Compact xchacha20-poly1305

This commit is contained in:
Juhani Krekelä 2020-06-25 12:16:37 +03:00
parent 08afb17745
commit d9363f3b69
2 changed files with 25 additions and 8 deletions

View File

@ -4,23 +4,27 @@ 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<<n&0xffffffff|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):
def ccb(k,c,n,f):
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)))
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)[:32])
def enc(a,k,n,p):c=bytes(chacha20(k,1,n,p));return c+tag(a,k,n,c)
def dec(a,k,n,e):
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)

19
test.py
View File

@ -1,4 +1,4 @@
import compact_chapoly
import compact_xchapoly
import compact_ecdh_curve25519
def test_chacha20_poly1305():
@ -11,10 +11,22 @@ def test_chacha20_poly1305():
for test_vector in test_vectors:
key, nonce, plaintext, ad, ciphertext, tag = map(bytes.fromhex, test_vector)
assert compact_chapoly.enc(ad, key, nonce, plaintext) == ciphertext + tag
assert compact_chapoly.dec(ad, key, nonce, ciphertext + tag) == plaintext
assert compact_xchapoly.cpe(ad, key, nonce, plaintext) == ciphertext + tag
assert compact_xchapoly.cpd(ad, key, nonce, ciphertext + tag) == plaintext
print('chacha20-poly1305: Ok')
def test_xchacha_poly1305():
test_vectors = [
('808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f', '404142434445464748494a4b4c4d4e4f5051525354555657', '4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e', '50515253c0c1c2c3c4c5c6c7', 'bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52e', 'c0875924c1c7987947deafd8780acf49'),
('808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f', '404142434445464748494a4b4c4d4e4f5051525354555657', '4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e', '50515253c0c1c2c3c4c5c6c7', 'bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52e', 'c0875924c1c7987947deafd8780acf49')
]
for test_vector in test_vectors:
key, nonce, plaintext, ad, ciphertext, tag = map(bytes.fromhex, test_vector)
assert compact_xchapoly.enc(ad, key, nonce, plaintext) == ciphertext + tag
assert compact_xchapoly.dec(ad, key, nonce, ciphertext + tag) == plaintext
print('xchacha20-poly1305: Ok')
def test_ecdh_curve25519():
alice_sk = bytes.fromhex('77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a')
alice_pk = compact_ecdh_curve25519.pubkey(alice_sk)
@ -27,4 +39,5 @@ def test_ecdh_curve25519():
if __name__ == '__main__':
test_chacha20_poly1305()
test_xchacha_poly1305()
test_ecdh_curve25519()