76 lines
2.2 KiB
Python
76 lines
2.2 KiB
Python
from secrets import randbelow, token_bytes
|
|
|
|
import pytest
|
|
from cryptography.hazmat.primitives.ciphers import Cipher
|
|
from cryptography.hazmat.primitives.ciphers.algorithms import ChaCha20
|
|
|
|
from randquik import cha
|
|
|
|
|
|
def test_cipherstreams_fullblocks():
|
|
"""Requests in multiple of ChaCha20 block size 64 bytes"""
|
|
key = token_bytes(32)
|
|
iv = token_bytes(16)
|
|
c0 = Cipher(ChaCha20(key, iv), None, None).encryptor()
|
|
c1 = cha.Cha(key, iv)
|
|
|
|
for i in range(2048):
|
|
N = 64 * (1 + randbelow(2048))
|
|
ct0 = c0.update(bytes(N))
|
|
ct1 = c1(bytearray(N))
|
|
assert len(ct0) == len(ct1)
|
|
assert ct0.hex() == ct1.hex(), f"{i=} {N=}"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"counter",
|
|
[
|
|
b"\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00",
|
|
b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
|
|
b"\xFF\xFF\xFF\x7F\xFF\xFF\xFF\xFF",
|
|
b"\x00\x00\x00\x80\xFF\xFF\xFF\xFF",
|
|
],
|
|
)
|
|
def test_counter_wrap(counter):
|
|
"""Tests carry handling of counter increments"""
|
|
key = bytes(32)
|
|
iv = counter + b"--------"
|
|
c0 = Cipher(ChaCha20(key, iv), None, None).encryptor()
|
|
c1 = cha.Cha(key, iv)
|
|
N = 128
|
|
ct0 = c0.update(bytes(N))
|
|
ct1 = c1(bytearray(N))
|
|
assert len(ct0) == len(ct1)
|
|
assert ct0.hex() == ct1.hex()
|
|
|
|
|
|
def test_cipherstreams_partial_updates():
|
|
"""Odd-sized requests that retain leftover buffers"""
|
|
key = token_bytes(32)
|
|
iv = token_bytes(16)
|
|
c0 = Cipher(ChaCha20(key, iv), None, None).encryptor()
|
|
c1 = cha.Cha(key, iv)
|
|
|
|
for i in range(2048):
|
|
N = 1 + randbelow(2048)
|
|
ct0 = c0.update(bytes(N))
|
|
ct1 = c1(bytearray(N))
|
|
assert len(ct0) == len(ct1)
|
|
assert ct0.hex() == ct1.hex(), f"{i=} {N=}"
|
|
|
|
|
|
def test_cipherstreams_32leftover():
|
|
"""Test the special case where the second response comes entirely from the leftover buffer"""
|
|
key = token_bytes(32)
|
|
nonce = token_bytes(12) # IETF nonce size
|
|
iv = bytes(4) + nonce
|
|
c0 = Cipher(ChaCha20(key, iv), None, None).encryptor()
|
|
c1 = cha.Cha(key, nonce)
|
|
|
|
for N in [512 - 32, 32]:
|
|
ct0 = c0.update(bytes(N))
|
|
ct1 = c1(bytearray(N))
|
|
assert len(ct0) == len(ct1)
|
|
assert ct0.hex() == ct1.hex()
|