Fx Utilities
- class vernamveil.FX(keystream_fn, block_size, vectorise, source_code='')
Bases:
object
A generic callable wrapper for key stream generator functions used in VernamVeil.
This class wraps any user-supplied or generated keystream function, providing a consistent interface for use in the VernamVeil cypher. The wrapped function must be deterministic, seed-sensitive, and type-correct.
- keystream_fn
Keystream function accepting (int | np.ndarray[tuple[int], np.dtype[np.uint64]], bytes | bytearray) and returning bytes or np.ndarray[tuple[int, int], np.dtype[np.uint8]].
- Type:
Callable
- block_size
The number of bytes returned per call.
- Type:
int
- vectorise
Whether the keystream function performs vectorised operations.
- Type:
bool
- source_code
The source code of the keystream function.
- Type:
str
Example:
fx = FX(keystream_fn, block_size=64, vectorise=False) keystream_bytes = fx(42, b"mysecretseed")
Initialise the FX wrapper.
- Parameters:
keystream_fn (Callable) – Keystream function accepting (int | np.ndarray[tuple[int], np.dtype[np.uint64]], bytes | bytearray) and returning bytes or np.ndarray[tuple[int, int], np.dtype[np.uint8]].
block_size (int) – The number of bytes returned per call.
vectorise (bool) – Whether the keystream function performs vectorised operations.
source_code (str) – The source code of the keystream function.
- Raises:
ValueError – If vectorise is True but numpy is not installed.
- class vernamveil.OTPFX(keystream, block_size, vectorise)
Bases:
FX
A callable class for one-time-pad (OTP) keystreams used in VernamVeil.
This class wraps a user-supplied keystream (as a list of byte blocks), providing a consistent interface for OTP encryption and decryption. The keystream must be at least as long as the message to be encrypted, and each keystream must be used only once for cryptographic security.
- keystream
The list of keystream blocks (each of length block_size).
- Type:
list[bytes]
- position
The current position in the keystream.
- Type:
int
- block_size
The number of bytes returned per call.
- Type:
int
- vectorise
Whether the keystream is used in vectorised mode.
- Type:
bool
- source_code
The source code to reconstruct this OTPFX instance.
- Type:
str
- Security Warning:
One-time-pad keystreams must never be reused for different messages. Reusing a keystream completely breaks the security of the encryption.
Example:
def get_true_random_bytes(n: int) -> bytes: # Replace with a function that returns n bytes from a true random source. # For real OTP, use a true random source (e.g., hardware RNG, quantum RNG, etc.) # Using `secrets` or `os.urandom` is not truly random and does not provide the same guarantees. raise NotImplementedError() # Generate a long enough keystream block_size = 64 keystream = [get_true_random_bytes(block_size) for _ in range(100)] # Create a cypher with the OTPFX instance fx = OTPFX(keystream, block_size=block_size, vectorise=False) cypher = VernamVeil(fx) # Encrypt a message initial_seed = VernamVeil.get_initial_seed() # remember to store this securely encrypted_message = cypher.encrypt(b"some message", initial_seed) # Optionally clip the keystream to the used portion fx.keystream = fx.keystream[:fx.position] # remember to store this securely # Reset the pointer for decryption fx.position = 0 # Decrypt the message decrypted_message = cypher.decrypt(encrypted_message, initial_seed)
Warning
Only reset fx.position to 0 for decryption of the same cyphertext. Never reuse the keystream for a new message.
Initialises the OTPFX instance.
- Parameters:
keystream (list[bytes]) – A list of bytes representing the keystream, split in equal block_size bytes.
block_size (int) – The block size for the keystream.
vectorise (bool) – Whether to use vectorised operations.
- Raises:
ValueError – If the keystream blocks are not of the same size.
- vernamveil.check_fx_sanity(fx, seed, num_samples=1000)
Perform basic sanity checks on a user-supplied fx function for use as a key stream generator.
- Return type:
bool
- Checks performed:
Type and output size check: All outputs should be bytes of length fx.block_size (scalar) or np.ndarray[tuple[int, int], np.dtype[np.uint8]] of shape (num_samples, fx.block_size) (vectorised).
Non-constant output: fx should return diverse values for varying i.
Seed sensitivity: fx output should change if the seed changes.
Basic uniformity: No single byte value should dominate.
Avalanche effect: Flipping a bit in the input should significantly change the output.
- Parameters:
fx (FX) – The function to test.
seed (bytes) – The seed to use for testing.
num_samples (int) – Number of samples to test.
- Returns:
True if all checks pass, False otherwise. Issues are reported as warnings.
- Return type:
bool
- vernamveil.generate_default_fx(*args, **kwargs)
Alias for
vernamveil.generate_keyed_hash_fx()
.
- vernamveil.generate_keyed_hash_fx(hash_name='blake2b', vectorise=False, block_size=None)
Generate a standard keyed hash-based pseudorandom function (PRF) using BLAKE2b, BLAKE3 or SHA256.
This is the recommended secure default fx for the VernamVeil cypher. :rtype:
FX
Note
For performance reasons, this function does not use an HMAC construction but instead concatenates the seed with the index. This is safe in this context because the inputs are tightly controlled by the cypher and always have fixed lengths.
- Parameters:
hash_name (Literal["blake2b", "blake3", "sha256"]) – Hash function to use (“blake2b”, “blake3” or “sha256”). The blake3 is only available if the C extension is installed. Defaults to “blake2b”.
vectorise (bool) – If True, uses numpy arrays as input for vectorised operations. Defaults to False.
block_size (int, optional) – Size of the hash output in bytes. Should be 64 for blake2b, larger than 0 for blake3 and 32 for sha256. If None, the default size for the selected hash algorithm is used. Defaults to None.
- Returns:
A callable that returns pseudo-random bytes from a keyed hash-based function.
- Return type:
- Raises:
ValueError – If hash_name is not “blake2b”, “blake3” or “sha256”.
ValueError – If hash_name is “blake3” but the C extension is not available.
ValueError – If the hash_size is not 64 for blake2b, larger than 0 for blake3 or 32 for sha256.
TypeError – If vectorise is not a boolean.
ValueError – If vectorise is True but numpy is not installed.
- vernamveil.generate_polynomial_fx(degree=10, max_weight=100000, vectorise=False)
Generate a random polynomial-based secret function to act as a deterministic key stream generator.
The transformed input index is passed to a cryptographic hash function.
- Return type:
- Parameters:
degree (int) – Degree of the polynomial. Defaults to 10.
max_weight (int) – Maximum value for polynomial coefficients. Defaults to 10 ** 5.
vectorise (bool) – If True, uses numpy arrays as input for vectorised operations. Defaults to False.
- Returns:
A callable that returns pseudo-random bytes from the polynomial-based function.
- Return type:
- Raises:
TypeError – If degree is not an integer.
ValueError – If degree is not positive.
TypeError – If max_weight is not an integer.
ValueError – If max_weight is not positive.
TypeError – If vectorise is not a boolean.
ValueError – If vectorise is True but numpy is not installed.
- vernamveil.load_fx_from_file(path)
Load the fx function from a Python file.
This uses importlib internally to import the fx. Never use this with files from untrusted sources, as it can run arbitrary code on your system.
- Return type:
- Parameters:
path (str or Path) – Path to the Python file containing fx.
- Returns:
The loaded fx function.
- Return type:
- Raises:
FileNotFoundError – If the file does not exist.
ImportError – If the module could not be loaded or no fx was found.
TypeError – If the loaded fx is not an instance of FX.