diff --git a/README.md b/README.md index e208594..a52a8b0 100644 --- a/README.md +++ b/README.md @@ -258,7 +258,8 @@ o - [X] `atbash`: aka Atbash Cipher - [X] `bacon`: aka Baconian Cipher - [X] `barbie-N`: aka Barbie Typewriter (*N* belongs to [1, 4]) -- [X] `citrix`: aka Citrix CTX1 passord encoding +- [X] `citrix`: aka Citrix CTX1 password encoding +- [X] `rail`: aka Rail Fence Cipher - [X] `rotN`: aka Caesar cipher (*N* belongs to [1,25]) - [X] `scytaleN`: encrypts using the number of letters on the rod (*N* belongs to [1,[) - [X] `shiftN`: shift ordinals (*N* belongs to [1,255]) diff --git a/codext/crypto/__init__.py b/codext/crypto/__init__.py index 29673c3..6928637 100755 --- a/codext/crypto/__init__.py +++ b/codext/crypto/__init__.py @@ -4,6 +4,7 @@ from .bacon import * from .barbie import * from .citrix import * +from .railfence import * from .rot import * from .scytale import * from .shift import * diff --git a/codext/crypto/railfence.py b/codext/crypto/railfence.py new file mode 100644 index 0000000..3c231a1 --- /dev/null +++ b/codext/crypto/railfence.py @@ -0,0 +1,76 @@ +# -*- coding: UTF-8 -*- +"""Rail Fence Cipher Codec - rail fence encoding. + +This codec: +- en/decodes strings from str to str +- en/decodes strings from bytes to bytes +- decodes file content to str (read) +- encodes file content from str to bytes (write) +""" + + + +from ..__common__ import * + + +__examples__ = { + 'enc(rail-5-3|rail_5_3)': {'this is a test' : 'it sss etiath '}, + 'enc(rail-5-3-up|rail_5_3-up)' :{'this is a test': 'h tiats e ssit'}, + 'dec(rail-7-4|rail_7_4)': {'a stiet shsti': 'this is a test'} +} + + + +def __buildf(text, rails, offset = 0, up = 0) : + l, rail = len(text), offset + if up != '' : + dr = -1 + rail = rails - offset - 1 + else : + dr = 1 + + f = [["#"] * l for i in range(rails)] + + for x in range(l) : + f[rail][x] = text[x] + if rail >= rails - 1: + dr = -1 + elif rail <= 0: + dr = 1 + rail += dr + return f + +def railfence_encode(rails = 3, offset = 0, up = 0) : + def encode(text, errors="strict") : + c,l = '', len(text) + f = __buildf(text, rails, offset, up) + for r in range(rails) : + for x in range(l) : + if f[r][x] != '#' : + c += f[r][x] + return c, l + return encode + +def railfence_decode(rails = 3, offset = 0, up = 0) : + def decode(text, errors = 'strict') : + f = __buildf("x" * len(text), rails, offset, up) + plain, i = '', 0 + ra, l = range(rails), range(len(text)) + + #Put the characters in the right place + for r in ra: + for x in l : + if f[r][x] == "x" : + f[r][x] = text[i] + i += 1 + #Read the characters in the right order + for x in l : + for r in ra: + if f[r][x] != '#' : + plain += f[r][x] + + return plain, len(plain) + + return decode + +add("rail", railfence_encode, railfence_decode, r"rail[-_](\d+)[-_](\d+)[-_]?(up)?$") diff --git a/docs/enc/crypto.md b/docs/enc/crypto.md index 00b4f51..a9c13f7 100644 --- a/docs/enc/crypto.md +++ b/docs/enc/crypto.md @@ -128,6 +128,21 @@ This implements the Citrix CTX1 password encoding algorithm. ----- +### Rail Fence Cipher + +This implements the Rail Fence encoding algorithm. + +**Codec** | **Conversions** | **Aliases** | **Comment** +:---: | :---: | --- | --- +`rail` | text <-> rail fence ciphertext, X rails and Y offset | `rail-X-Y`, `rail_X_Y`, `rail-X-Y-up`| The encoding fence is built from the top. Careful to trailing whitespaces. The `up` flag is used to build the fence from the bottom to the top. +```python +>>> codext.encode("this is a test", "rail-5-3") +'it sss etiath ' +>>> codext.decode("it sss etiath ", "rail-5-3") +'this is a test' +``` + +----- ### ROT N This is a dynamic encoding, that is, it can be called with an integer to define the ROT offset. Encoding will apply a positive offset, decoding will apply a negative one.