fictive.feistel package

Module contents

generic implementation of a Feistel cipher

class fictive.feistel.Feistel(*, round_func: Union[collections.abc.Iterator[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Iterable[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Callable[Data, Key, Optional[int], Data]], key: Union[collections.abc.Iterator[Key], collections.abc.Iterable[Key], Key], num_rounds: int, chirality: fictive.feistel.ChiralityType = <ChiralityType.SOURCE_TARGET: 1>, xor_operation: Optional[collections.abc.Callable[Data, Data, Data]] = None)[source]

Bases: Generic[fictive.feistel.Data, fictive.feistel.Key]

Didactic implementation of a generalized Feistel Cipher

see https://www.schneier.com/wp-content/uploads/2016/02/paper-unbalanced-feistel.pdf

This class implements a simple Feistel cipher using an arbitrary round function and number of rounds. THIS IMPLEMENTATION IS INEFFICIENT AND INSECURE. It can be used for simple experimentation and obfuscation, but MUST NOT be used for any application requiring (or even expecting) actual security.

import hashlib
import hmac

from fictive.feistel import Feistel

def func(source, key, target_length):
    return hmac.new(key, source, hashlib.sha1).digest()[:target_length]

key = [b'secrets', b'protect', b'my data']
>>> cipher = Feistel(round_func=func, key=key, num_rounds=3)
>>> cipher.encrypt(b'My data is secret')
b"2X\x9a\x9d\x13\x0e\xf0pW\x8c\xa9\x9a'\xd8\x08\xe2\x90"
>>> cipher.decrypt(b"2X\x9a\x9d\x13\x0e\xf0pW\x8c\xa9\x9a'\xd8\x08\xe2\x90")
b'My data is secret'
class ChiralityType(value)

Bases: enum.Enum

indicates which “half” of the input is the “source” and which is the “target” (the source is passed through the round function and mixed with the target)

SOURCE_TARGET = 1
TARGET_SOURCE = 2
__init__(*, round_func: Union[collections.abc.Iterator[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Iterable[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Callable[Data, Key, Optional[int], Data]], key: Union[collections.abc.Iterator[Key], collections.abc.Iterable[Key], Key], num_rounds: int, chirality: fictive.feistel.ChiralityType = <ChiralityType.SOURCE_TARGET: 1>, xor_operation: Optional[collections.abc.Callable[Data, Data, Data]] = None)[source]

Initialize a re-usable Feistel network

Parameters
  • round_func – the round function (or functions) that will accept a source Data sequence, a Key key, and a target length as inputs, and returns a Data sequence of the target length. This can be a single callable, or an iterable sequence of callables that will be used sequentially as each round of the Feistel network is calculated

  • key – A ‘Key’ object (or objects) that will be used as input to the round function(s). It can be a single value, or an iterable sequence of values

  • num_rounds – the number of Feistel network rounds to use when generating the enciphered output

  • chirality – determines which portion of the data is the “source” and which is the “target”

  • xor_operation

    the operation that will be used to combine (a) the output of the round function and (b) the target data. If none is provided, the default is to map operator.xor to each element of the values, and create a new Data instance from that map object. I.e.:

    combined = type(data)(map(operator.xor, output, target))
    

    This will likely be suitable for most sequence types

Returns

the enciphered data

decrypt(data: Data, source_length: Optional[int] = None, target_length: Optional[int] = None)Data[source]

decipher data using the Feistel network in the “reverse” direction

Parameters
  • data – the data to be encrypted

  • source_length – explicitly specify the length of the data that should be considered the “source” in each round of the Feistel network (the source is used as input to the round function)

  • target_length – explicitly specify the length of the data that should be considered the “target” in each round of the Feistel network (the target is mixed with the output of the round function)

classmethod encipher(*, round_func: Union[collections.abc.Iterator[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Iterable[collections.abc.Callable[Data, Key, Optional[int], Data]], collections.abc.Callable[Data, Key, Optional[int], Data]], key: Union[collections.abc.Iterator[Key], collections.abc.Iterable[Key], Key], num_rounds: int, data: Data, source_length: Optional[int] = None, target_length: Optional[int] = None, chirality: fictive.feistel.ChiralityType = <ChiralityType.SOURCE_TARGET: 1>, xor_operation: Optional[collections.abc.Callable[Data, Data, Data]] = None)Data[source]

apply a generalized Feistel cipher to data

Parameters
  • round_func – the round function (or functions) that will accept a source Data sequence, a Key key, and a target length as inputs, and returns a Data sequence of the target length. This can be a single callable, or an iterable sequence of callables that will be used sequentially as each round of the Feistel network is calculated

  • key – A ‘Key’ object (or objects) that will be used as input to the round function(s). It can be a single value, or an iterable sequence of values

  • num_rounds – the number of Feistel network rounds to use when generating the enciphered output

  • data – a Data sequence to be enciphered (i.e., the “plaintext”)

  • source_length – the length of the data that should be considered the “source” in each round of the Feistel network (the source is used as input to the round function)

  • target_length – the length of the data that should be considered the “target” in each round of the Feistel network (the target is mixed with the output of the round function)

  • chirality – determines which portion of the data is the “source” and which is the “target”

  • xor_operation

    the operation that will be used to combine (a) the output of the round function and (b) the target data. If none is provided, the default is to map operator.xor to each element of the values, and create a new Data instance from that map object. I.e.:

    combined = type(data)(map(operator.xor, output, target))
    

    This will likely be suitable for most sequence types

Returns

the enciphered data

encrypt(data: Data, source_length: Optional[int] = None, target_length: Optional[int] = None)Data[source]

encipher data using the Feistel network in the “forward” direction

Parameters
  • data – the data to be encrypted

  • source_length – explicitly specify the length of the data that should be considered the “source” in each round of the Feistel network (the source is used as input to the round function)

  • target_length – explicitly specify the length of the data that should be considered the “target” in each round of the Feistel network (the target is mixed with the output of the round function)