Danger

Nothing here should be used for any security purposes.

  • If you need cryptographic tools in a Python environment use pyca.

  • If you need efficient and reliable abstract math utilities in a Python-like environment consider using SageMath.

Utility functions

This module is imported with:

import toy_crypto.utils

toy_crypto.utils.digit_count(n: int, base: int = 10) int

returns the number of digits (base b) of integer n.

Raises:
Parameters:
Return type:

int

Coding this is a math problem, not a string representation problem. Idetally the solution would be to use

\[d = \lfloor\log_b \| x \| + 1\rfloor\]

but that leads to erroneous results due to the precision limitations of math.log().

>>> from toy_crypto.utils import digit_count
>>> digit_count(999)
3
>>> digit_count(1000)
4
>>> digit_count(1001)
4
>>> digit_count(9999999999999998779999999999999999999999999999999999999999999)
61
>>> digit_count(9999999999999999999999999999999999999999999999999999999999999)
61
>>> digit_count(10000000000000000000000000000000000000000000000000000000000000)
62
>>> digit_count(0)
1
>>> digit_count(-10_000)
5
toy_crypto.utils.lsb_to_msb(n: int) Iterator[int]

0s and 1s representing bits of n, starting with the least significant bit.

Raises:
Parameters:

n (int)

Return type:

Iterator[int]

lsb_to_msb() is used by scaler_multiply() and would be used by modular exponentiation for implementations of those that leak the bits of the scalar (or exponent) through side channels.

>>> from toy_crypto.utils import lsb_to_msb
>>> list(lsb_to_msb(13))
[1, 0, 1, 1]
toy_crypto.utils.hamming_distance(a: bytes, b: bytes) int

Hamming distance between byte sequences of equal length.

Raises:

ValueError – if len(a) != len(b).

Parameters:
Return type:

int

Let’s illustrate with an example from Cryptopals.

>>> from toy_crypto.utils import hamming_distance
>>> s1 = b"this is a test"
>>> s2 = b"wokka wokka!!!"
>>> hamming_distance(s1, s2)
37

xor

The utils.xor() and the class utils.Xor provide utilities for xoring strings of bytes together. There is some assymetry between the two arguments. The message can be an collections.abc.Iterator as well as bytes. The pad arguement on the other hand, is expected to be bytes only (in this version.) The pad argument is will be repeated if it is shorter than the message.

Warning

The Byte type is just a type alias for int. There is no run time nor type checking mechanism that prevents you from passing an Iterator[Byte] message that contains integers outside of the range that would be expected for a byte. If you do so, bad things will happen. If you are lucky some exception from the bowels of Python will be raised in a way that will help you identify the error. If you are unlucky, you will silently get garbage results.

class toy_crypto.utils.Xor(message: Iterator[int] | bytes, pad: bytes)

Iterator that spits out xor of message with (repeated) pad.

The iterator will run through successful bytes of message xor-ing those with successive bytes of pad, repeating pad if pad is shorter than message.

Each iteration returns a non-negative int less than 256.

Parameters:
toy_crypto.utils.xor(message: bytes | Iterator[int], pad: bytes) bytes

Returns the xor of message with a (repeated) pad.

The pad is repeated if it is shorter than m. This can be thought of as bytewise Vigenère.

Parameters:
Return type:

bytes

>>> from toy_crypto.utils import xor
>>> message = b"Attack at dawn!"
>>> pad = bytes(10) + bytes.fromhex("00 14 04 05 00")
>>> modified_message = xor(message, pad)
>>> modified_message
b'Attack at dusk!'

Encodings for the RSA 129 challenge

When the RSA 129 challenge was first published in Scientific American in 1979 it used its own encoding scheme between text and integers. This class provides an encoder and decoder for that scheme.

class toy_crypto.utils.Rsa129

Text encoder/decoder used in RSA-129 challenge.

Encoding scheme from Martin Gardner’s 1977 article.

classmethod decode(number: int) str

Decode text.

Parameters:

number (int)

Return type:

str

classmethod encode(text: str) int

Encode text

Parameters:

text (str)

Return type:

int