File size: 992 Bytes
55e2289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from typing import Callable

BLOCK_SIZE = 16  # 128 bit


def inc_counter_be(counter: bytearray):
    """Incrementa un contatore big-endian a 128 bit (come Crypto++)."""
    for i in range(BLOCK_SIZE - 1, -1, -1):
        counter[i] = (counter[i] + 1) & 0xFF
        if counter[i] != 0:
            break


class CTR:
    def __init__(self, encrypt_block: Callable[[bytes], bytes], initial_counter: bytes):
        assert len(initial_counter) == BLOCK_SIZE
        self.encrypt_block = encrypt_block
        self.counter = bytearray(initial_counter)

    def process(self, data: bytes) -> bytes:
        out = bytearray()
        offset = 0

        while offset < len(data):
            keystream = self.encrypt_block(bytes(self.counter))
            inc_counter_be(self.counter)

            block = data[offset:offset + BLOCK_SIZE]
            ks = keystream[:len(block)]
            out.extend(b ^ k for b, k in zip(block, ks))
            offset += BLOCK_SIZE

        return bytes(out)