Lorenz
Category: Bletchley
Status: Registered and callable in the CyberChef 11.3.0 compatibility inventory.
Input / output: string → string
Background: https://wikipedia.org/wiki/Lorenz_cipher
What it does
The Lorenz SZ40/42 cipher attachment was a WW2 German rotor cipher machine with twelve rotors which attached in-line between remote teleprinters. It used the Vernam cipher with two groups of five rotors (named the psi(ψ) wheels and chi(χ) wheels at Bletchley Park) to create two pseudorandom streams of five bits, encoded in ITA2, which were XOR added to the plaintext. Two other rotors, dubbed the mu(μ) or motor wheels, could hold up the stepping of the psi wheels meaning they stepped intermittently. Each rotor has a different number of cams/lugs around their circumference which could be set active or inactive changing the key stream. Three models of the Lorenz are emulated, SZ40, SZ42a and SZ42b and three example wheel patterns (the lug settings) are included (KH, ZMUG & BREAM) with the option to set a custom set using the letter ‘x’ for active or ‘.’ for an inactive lug. The input can either be plaintext or ITA2 when sending and ITA2 when receiving. To learn more, Virtual Lorenz, an online, browser based simulation of the Lorenz SZ40/42 is available at lorenz.virtualcolossus.co.uk. A more detailed description of this operation can be found here.
Note
Status here means the operation name is implemented and callable. It does not by itself promise byte-for-byte parity for every upstream option. See Compatibility and current status for the verified scope and known boundaries.
Warning
Historical machine presets currently cover a documented compatibility subset.
Arguments and options
Arguments are positional. Keep their order when using bake() or
Pipeline.then().
Index |
Name |
UI type |
PyChef default |
Accepted values / format |
|---|---|---|---|---|
|
Model |
|
|
|
|
Wheel Pattern |
|
|
|
|
KT-Schalter |
|
|
|
|
Mode |
|
|
|
|
Input Type |
|
|
|
|
Output Type |
|
|
|
|
ITA2 Format |
|
|
|
|
Ψ1 start (1-43) |
|
|
A Python integer or floating-point value |
|
Ψ2 start (1-47) |
|
|
A Python integer or floating-point value |
|
Ψ3 start (1-51) |
|
|
A Python integer or floating-point value |
|
Ψ4 start (1-53) |
|
|
A Python integer or floating-point value |
|
Ψ5 start (1-59) |
|
|
A Python integer or floating-point value |
|
Μ37 start (1-37) |
|
|
A Python integer or floating-point value |
|
Μ61 start (1-61) |
|
|
A Python integer or floating-point value |
|
Χ1 start (1-41) |
|
|
A Python integer or floating-point value |
|
Χ2 start (1-31) |
|
|
A Python integer or floating-point value |
|
Χ3 start (1-29) |
|
|
A Python integer or floating-point value |
|
Χ4 start (1-26) |
|
|
A Python integer or floating-point value |
|
Χ5 start (1-23) |
|
|
A Python integer or floating-point value |
|
Ψ1 lugs (43) |
|
|
|
|
Ψ2 lugs (47) |
|
|
|
|
Ψ3 lugs (51) |
|
|
|
|
Ψ4 lugs (53) |
|
|
|
|
Ψ5 lugs (59) |
|
|
|
|
Μ37 lugs (37) |
|
|
|
|
Μ61 lugs (61) |
|
|
|
|
Χ1 lugs (41) |
|
|
|
|
Χ2 lugs (31) |
|
|
|
|
Χ3 lugs (29) |
|
|
|
|
Χ4 lugs (26) |
|
|
|
|
Χ5 lugs (23) |
|
|
|
Recipe template
Important
This is a call template built from the documented defaults. Replace placeholder values such as empty keys, paths, patterns, or lookup data before running it.
from pychef import bake
input_value = "example"
args = ['SZ40', 'KH Pattern', False, 'Send', 'Plaintext', 'Plaintext', '5/8/9', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, '.x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x', '.xx.x.xxx..x.x.x..x.xx.x.xxx.x....x.xx.x.x.x..x', '.x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x', '.xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x.', 'xx...xx.x..x.xx.x...x.x.x.x.x.x.x.x.xx..xxxx.x.x...xx.x..x.', 'x.x.x.x.x.x...x.x.x...x.x.x...x.x....', '.xxxx.xxxx.xxx.xxxx.xx....xxx.xxxx.xxxx.xxxx.xxxx.xxx.xxxx...', '.x...xxx.x.xxxx.x...x.x..xxx....xx.xxxx..', 'x..xxx...x.xxxx..xx..x..xx.xx..', '..xx..x.xxx...xx...xx..xx.xx.', 'xx..x..xxxx..xx.xxx....x..', 'xx..xx....xxxx.x..x.x..']
result = bake(input_value, [{"op": 'Lorenz', "args": args}])
print(result)
Pipeline example
from pychef import Pipeline
args = ['SZ40', 'KH Pattern', False, 'Send', 'Plaintext', 'Plaintext', '5/8/9', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, '.x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x', '.xx.x.xxx..x.x.x..x.xx.x.xxx.x....x.xx.x.x.x..x', '.x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x', '.xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x.', 'xx...xx.x..x.xx.x...x.x.x.x.x.x.x.x.xx..xxxx.x.x...xx.x..x.', 'x.x.x.x.x.x...x.x.x...x.x.x...x.x....', '.xxxx.xxxx.xxx.xxxx.xx....xxx.xxxx.xxxx.xxxx.xxxx.xxx.xxxx...', '.x...xxx.x.xxxx.x...x.x..xxx....xx.xxxx..', 'x..xxx...x.xxxx..xx..x..xx.xx..', '..xx..x.xxx...xx...xx..xx.xx.', 'xx..x..xxxx..xx.xxx....x..', 'xx..xx....xxxx.x..x.x..']
transform = Pipeline().then('Lorenz', *args)
result = transform("example")
Dedicated operation module
The registered entry point lives in
pychef.operations.by_operation.lorenz. Direct calls
receive the input value and a positional argument tuple:
from pychef.operations.by_operation.lorenz import run
result = run("example", tuple(['SZ40', 'KH Pattern', False, 'Send', 'Plaintext', 'Plaintext', '5/8/9', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, '.x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x', '.xx.x.xxx..x.x.x..x.xx.x.xxx.x....x.xx.x.x.x..x', '.x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x', '.xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x.', 'xx...xx.x..x.xx.x...x.x.x.x.x.x.x.x.xx..xxxx.x.x...xx.x..x.', 'x.x.x.x.x.x...x.x.x...x.x.x...x.x....', '.xxxx.xxxx.xxx.xxxx.xx....xxx.xxxx.xxxx.xxxx.xxxx.xxx.xxxx...', '.x...xxx.x.xxxx.x...x.x..xxx....xx.xxxx..', 'x..xxx...x.xxxx..xx..x..xx.xx..', '..xx..x.xxx...xx...xx..xx.xx.', 'xx..x..xxxx..xx.xxx....x..', 'xx..xx....xxxx.x..x.x..']))
- pychef.operations.by_operation.lorenz.run(value, args)
Run this operation using its shared internal implementation.
- Parameters:
value (str | bytes)
args (Sequence[Any])
- Return type:
str | bytes