Download Decipher/cmac.py from sae8d/topo: direct link, hf CLI and curl.
- Browser
- Download file 1.78 kB
-
https://huggingface.co/spaces/sae8d/topo/resolve/main/Decipher/cmac.py
- Command line
-
hf download hf://spaces/sae8d/topo/Decipher/cmac.py
-
curl -L -o cmac.py https://huggingface.co/spaces/sae8d/topo/resolve/main/Decipher/cmac.py
1.78 kB
| from typing import Callable | |
| BLOCK_SIZE = 16 # 128 bit for Twofish | |
| def xor_bytes(a: bytes, b: bytes) -> bytes: | |
| return bytes(x ^ y for x, y in zip(a, b)) | |
| def left_shift_one(bitstring: bytes) -> bytes: | |
| out = bytearray(len(bitstring)) | |
| carry = 0 | |
| for i in reversed(range(len(bitstring))): | |
| new = (bitstring[i] << 1) & 0xFF | |
| out[i] = new | carry | |
| carry = (bitstring[i] & 0x80) >> 7 | |
| return bytes(out) | |
| def generate_subkeys(encrypt_block: Callable[[bytes], bytes]): | |
| const_rb = 0x87 | |
| zero = bytes(BLOCK_SIZE) | |
| L = encrypt_block(zero) | |
| K1 = left_shift_one(L) | |
| if L[0] & 0x80: | |
| K1 = xor_bytes(K1, b'\x00' * 15 + bytes([const_rb])) | |
| K2 = left_shift_one(K1) | |
| if K1[0] & 0x80: | |
| K2 = xor_bytes(K2, b'\x00' * 15 + bytes([const_rb])) | |
| return K1, K2 | |
| def pad(block: bytes) -> bytes: | |
| padded = block + b'\x80' | |
| return padded + b'\x00' * (BLOCK_SIZE - len(padded)) | |
| class CMAC: | |
| def __init__(self, encrypt_block: Callable[[bytes], bytes]): | |
| self.encrypt_block = encrypt_block | |
| self.K1, self.K2 = generate_subkeys(encrypt_block) | |
| def digest(self, data: bytes) -> bytes: | |
| if len(data) == 0: | |
| last = xor_bytes(pad(b''), self.K2) | |
| blocks = [] | |
| else: | |
| blocks = [data[i:i+BLOCK_SIZE] for i in range(0, len(data), BLOCK_SIZE)] | |
| if len(blocks[-1]) == BLOCK_SIZE: | |
| last = xor_bytes(blocks[-1], self.K1) | |
| blocks = blocks[:-1] | |
| else: | |
| last = xor_bytes(pad(blocks[-1]), self.K2) | |
| blocks = blocks[:-1] | |
| X = bytes(BLOCK_SIZE) | |
| for block in blocks: | |
| X = self.encrypt_block(xor_bytes(X, block)) | |
| return self.encrypt_block(xor_bytes(X, last)) | |