diff --git a/chepy/modules/encryptionencoding.py b/chepy/modules/encryptionencoding.py index 6ed823f..f809465 100644 --- a/chepy/modules/encryptionencoding.py +++ b/chepy/modules/encryptionencoding.py @@ -321,7 +321,6 @@ def xor( x.append(char ^ key_val) else: - if key_type == "utf": key = str(key) key = binascii.hexlify(key.encode()) @@ -828,8 +827,8 @@ def triple_des_decrypt( cipher = DES3.new(key, mode=DES3.MODE_OFB, iv=iv) self.state = cipher.decrypt(self._convert_to_bytes()) return self - else: # pragma: no cover - raise ValueError('Invalid mode') + else: # pragma: no cover + raise ValueError("Invalid mode") @ChepyDecorators.call_stack def aes_encrypt( @@ -963,8 +962,8 @@ def aes_decrypt( cipher = AES.new(key, mode=AES.MODE_OFB, iv=iv) self.state = cipher.decrypt(self._convert_to_bytes()) return self - else: # pragma: no cover - raise ValueError('Invalid AES mode') + else: # pragma: no cover + raise ValueError("Invalid AES mode") @ChepyDecorators.call_stack def blowfish_encrypt( @@ -1522,7 +1521,7 @@ def to_letter_number_code( @ChepyDecorators.call_stack def from_letter_number_code( - self, delimiter: Union[str, bytes] = ' ', join_by: Union[str, bytes] = "" + self, delimiter: Union[str, bytes] = " ", join_by: Union[str, bytes] = "" ) -> EncryptionEncodingT: """Decode A1Z26 @@ -1593,8 +1592,8 @@ def bifid_encode(self, key: Union[bytes, str] = "") -> EncryptionEncodingT: key = self._bytes_to_str(key) key = "".join(re.findall(r"[A-Z]+", key)) keyword_str = key.upper().replace("J", "I") - keyword_set = set(keyword_str) - keyword_list = [] + # keyword_set = set(keyword_str) + # keyword_list = [] alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ" x_co = [] y_co = [] @@ -1655,7 +1654,7 @@ def bifid_decode(self, key: Union[str, bytes] = ""): key = self._bytes_to_str(key) key = "".join(re.findall(r"[A-Z]+", key)) keyword_str = key.upper().replace("J", "I") - keyword_set = set(keyword_str) + # keyword_set = set(keyword_str) alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ" structure = [] @@ -1836,3 +1835,73 @@ def fernet_decrypt( out = Fernet(key).decrypt(self._convert_to_bytes()) self.state = out return self + + @ChepyDecorators.call_stack + def railfence_encode(self, key=2, offset=0) -> EncryptionEncodingT: + """Encode to railfence + + Args: + key (int, optional): Key. Should be equal or larger than data. Defaults to 2. + offset (int, optional): Offset. Defaults to 0. + + Returns: + Chepy: The Chepy object. + """ + key, offset = int(key), int(offset) + data = self._convert_to_str() + if key < 2: + raise ValueError("Key has to be bigger than 2") # pragma: no cover + elif key > len(data): + raise ValueError( + "Key should be smaller than the plain text's length" + ) # pragma: no cover + + if offset < 0: + raise ValueError("Offset has to be a positive integer") # pragma: no cover + + cycle = (key - 1) * 2 + rows = [""] * key + + for pos in range(len(data)): + row_idx = key - 1 - abs(cycle // 2 - (pos + offset) % cycle) + rows[row_idx] += data[pos] + + self.state = "".join(rows).strip() + return self + + @ChepyDecorators.call_stack + def railfence_decode(self, key=2, offset=0) -> EncryptionEncodingT: + """Decode railfence + + Args: + key (int, optional): Key. Should be equal or larger than data. Defaults to 2. + offset (int, optional): Offset. Defaults to 0. + + Returns: + Chepy: The Chepy object. + """ + key, offset = int(key), int(offset) + cipher = self._convert_to_str() + + if key < 2: + raise ValueError("Key has to be bigger than 2") # pragma: no cover + elif key > len(cipher): + raise ValueError( + "Key should be smaller than the cipher's length" + ) # pragma: no cover + + if offset < 0: + raise ValueError("Offset has to be a positive integer") # pragma: no cover + + cycle = (key - 1) * 2 + plaintext = [""] * len(cipher) + + j = 0 + for y in range(key): + for x in range(len(cipher)): + if (y + x + offset) % cycle == 0 or (y - x - offset) % cycle == 0: + plaintext[x] = cipher[j] + j += 1 + + self.state = "".join(plaintext).strip() + return self diff --git a/chepy/modules/encryptionencoding.pyi b/chepy/modules/encryptionencoding.pyi index 4600d5d..367ccfe 100644 --- a/chepy/modules/encryptionencoding.pyi +++ b/chepy/modules/encryptionencoding.pyi @@ -26,7 +26,7 @@ class EncryptionEncoding(ChepyCore): def jwt_verify(self: EncryptionEncodingT, secret: str, algorithm: list=...) -> EncryptionEncodingT: ... def jwt_sign(self: EncryptionEncodingT, secret: str, algorithms: str=...) -> EncryptionEncodingT: ... def jwt_token_generate_none_alg(self: EncryptionEncodingT, headers: Dict[str, Any]=...) -> EncryptionEncodingT: ... - def jwt_token_generate_embedded_jwk(self: EncryptionEncodingT, private_key_pem: str, private_key_passphrase: str = ..., headers: dict = ..., alg: str = Union["RS256", "RS512"]) -> EncryptionEncodingT: ... + def jwt_token_generate_embedded_jwk(self: EncryptionEncodingT, private_key_pem: str, private_key_passphrase: str = ..., headers: dict = ..., alg: str = Literal["RS256", "RS512"]) -> EncryptionEncodingT: ... def rc4_encrypt(self: EncryptionEncodingT, key: str, key_format: RC4_FORMAT=...) -> EncryptionEncodingT: ... def rc4_decrypt(self: EncryptionEncodingT, key: str, key_format: RC4_FORMAT=...) -> EncryptionEncodingT: ... def des_encrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... @@ -35,8 +35,8 @@ class EncryptionEncoding(ChepyCore): def chacha_decrypt(self: EncryptionEncodingT, key: str, nonce: str=..., key_format: FORMAT=..., nonce_format: FORMAT=...) -> EncryptionEncodingT: ... def triple_des_encrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... def triple_des_decrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB", "ECB/NoPadding", "CBC/NoPadding"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... - def aes_encrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: str=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... - def aes_decrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: str=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM", "ECB/NoPadding", "CBC/NoPadding"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... + def aes_encrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: Union[bytes, str]=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... + def aes_decrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: Union[bytes, str]=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM", "ECB/NoPadding", "CBC/NoPadding"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ... def blowfish_encrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ... def blowfish_decrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ... def vigenere_encode(self: EncryptionEncodingT, key: str) -> EncryptionEncodingT: ... @@ -67,3 +67,5 @@ class EncryptionEncoding(ChepyCore): def rabbit(self: EncryptionEncodingT, key: str, iv: Union[None, str]=...) -> EncryptionEncodingT: ... def fernet_encrypt(self: EncryptionEncodingT, key:Union[bytes, str], encode_key: bool=False) -> EncryptionEncodingT: ... def fernet_decrypt(self: EncryptionEncodingT, key:Union[bytes, str], encode_key: bool=False) -> EncryptionEncodingT: ... + def railfence_encode(self: EncryptionEncodingT, key: Union[int, str]=2, offset: Union[int, str]=0) -> EncryptionEncodingT: ... + def railfence_decode(self: EncryptionEncodingT, key: Union[int, str]=2, offset: Union[int, str]=0) -> EncryptionEncodingT: ... diff --git a/tests/test_encryptionencoding.py b/tests/test_encryptionencoding.py index b595a92..b839eee 100644 --- a/tests/test_encryptionencoding.py +++ b/tests/test_encryptionencoding.py @@ -43,7 +43,10 @@ def test_rot_47_bruteforce(): def test_rot_8000(): - assert Chepy("籯籵籪籰粄类簹籽籽簼籷籽簹籽籱簼籬簹类簼粆").rot_8000().o == b"flag{r0tt3nt0th3c0r3}" + assert ( + Chepy("籯籵籪籰粄类簹籽籽簼籷籽簹籽籱簼籬簹类簼粆").rot_8000().o + == b"flag{r0tt3nt0th3c0r3}" + ) def test_rotate(): @@ -155,24 +158,19 @@ def test_xor_bruteforce(): def test_jwt_decode(): - assert ( - Chepy( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmF\ + assert Chepy( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmF\ tZSI6IkFtYXppbmcgSGF4eDByIiwiZXhwIjoiMTQ2NjI3MDcyMiIsImFkbWluIjp0\ cnVlfQ.UL9Pz5HbaMdZCV9cS9OcpccjrlkcmLovL2A2aiKiAOY" - ) - .jwt_decode() - .o - == { - "payload": { - "sub": "1234567890", - "name": "Amazing Haxx0r", - "exp": "1466270722", - "admin": True, - }, - "header": {"alg": "HS256", "typ": "JWT"}, - } - ) + ).jwt_decode().o == { + "payload": { + "sub": "1234567890", + "name": "Amazing Haxx0r", + "exp": "1466270722", + "admin": True, + }, + "header": {"alg": "HS256", "typ": "JWT"}, + } def test_jwt_sign(): @@ -187,15 +185,10 @@ def test_jwt_sign(): def test_jwt_verify(): - assert ( - Chepy( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5N\ + assert Chepy( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5N\ iznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg" - ) - .jwt_verify("secret") - .o - == {"some": "payload"} - ) + ).jwt_verify("secret").o == {"some": "payload"} def test_jwt_non_alg(): @@ -402,9 +395,9 @@ def test_aes_encrypt(): .o == b"4ab2b4f72e9d92960b" ) - raw_key = ( - raw_iv - ) = b'\xe1p\x07\x01R\xee\xde)\xa0gx\xb6\xc2\xcb\x18\x9e\x80\xe5\x9eu\xf2"0PVvE\xdb\x08\x93\xa0\x93' + raw_key = raw_iv = ( + b'\xe1p\x07\x01R\xee\xde)\xa0gx\xb6\xc2\xcb\x18\x9e\x80\xe5\x9eu\xf2"0PVvE\xdb\x08\x93\xa0\x93' + ) assert ( Chepy("hello") .aes_encrypt(key=raw_key, iv=raw_iv[:16], key_format="raw", iv_format="raw") @@ -413,9 +406,17 @@ def test_aes_encrypt(): == b"hello" ) assert ( - Chepy('hello') - .aes_encrypt(key='supersecret!!!!!', key_format='utf8', iv='abcdefghijklmnop', iv_format='utf-8') - .to_hex().o == b'd18c2cba21d2eef40c9ed4771a9b320e') + Chepy("hello") + .aes_encrypt( + key="supersecret!!!!!", + key_format="utf8", + iv="abcdefghijklmnop", + iv_format="utf-8", + ) + .to_hex() + .o + == b"d18c2cba21d2eef40c9ed4771a9b320e" + ) def test_aes_decrypt(): @@ -471,7 +472,11 @@ def test_aes_decrypt(): assert ( Chepy("6bcd22d5c24a59a818f39ba64b7f2d21") .from_hex() - .aes_decrypt("b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", iv='404cce974703e46da08c3fb65c469109', mode='ECB/NoPadding') + .aes_decrypt( + "b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", + iv="404cce974703e46da08c3fb65c469109", + mode="ECB/NoPadding", + ) .to_hex() .o == b"68656c6c6f0b0b0b0b0b0b0b0b0b0b0b" @@ -479,7 +484,11 @@ def test_aes_decrypt(): assert ( Chepy("dda597db9a1b3627f64fb3397502c6f4") .from_hex() - .aes_decrypt("b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", iv='404cce974703e46da08c3fb65c469109', mode='CBC/NoPadding') + .aes_decrypt( + "b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", + iv="404cce974703e46da08c3fb65c469109", + mode="CBC/NoPadding", + ) .to_hex() .o == b"68656c6c6f0b0b0b0b0b0b0b0b0b0b0b" @@ -560,8 +569,30 @@ def test_triple_des_decrypt(): .o == b"some data" ) - assert Chepy('23bba626dce4683a').from_hex().triple_des_decrypt('df5770dec9f7d1843d72f195656b374c894b435da94a830d', '8219e29f40416b93', mode='ECB/NoPadding').to_hex().o == b'68656c6c6f030303' - assert Chepy('804b7fd84fa2d823').from_hex().triple_des_decrypt('df5770dec9f7d1843d72f195656b374c894b435da94a830d', '8219e29f40416b93', mode='CBC/NoPadding').to_hex().o == b'68656c6c6f030303' + assert ( + Chepy("23bba626dce4683a") + .from_hex() + .triple_des_decrypt( + "df5770dec9f7d1843d72f195656b374c894b435da94a830d", + "8219e29f40416b93", + mode="ECB/NoPadding", + ) + .to_hex() + .o + == b"68656c6c6f030303" + ) + assert ( + Chepy("804b7fd84fa2d823") + .from_hex() + .triple_des_decrypt( + "df5770dec9f7d1843d72f195656b374c894b435da94a830d", + "8219e29f40416b93", + mode="CBC/NoPadding", + ) + .to_hex() + .o + == b"68656c6c6f030303" + ) def test_blowfish_encrypt(): @@ -868,3 +899,10 @@ def test_fernet(): c = Chepy(flag).fernet_encrypt(key, True) assert c.o.startswith(b"gAAA") assert c.fernet_decrypt(key, True).o == flag.encode() + + +def test_railfence(): + assert Chepy("hello").railfence_encode().o == b"hloel" + assert Chepy("hello world").railfence_encode(key=4, offset=4).o == b"lrelolhowd" + assert Chepy("hloel").railfence_decode().o == b"hello" + assert Chepy(b"lelho").railfence_decode(key=4, offset="4").o == b"hello"