Skip to content

Commit

Permalink
🗓 Apr 3, 2024 9:41:46 PM
Browse files Browse the repository at this point in the history
💚 build steps added/updated
🐙 add support for ecb/cbc/nopadding for aes and 3des
🐙 from_hex default joinby changed
🤖 types added/updated
  • Loading branch information
securisec committed Apr 4, 2024
1 parent f392d46 commit fc4f009
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@


test:
python -m pytest -v --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/
python -m pytest --noconftest -v --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/

test-all: test
python -m pytest -v --disable-pytest-warnings tests_plugins/
python -m pytest --noconftest -v --disable-pytest-warnings tests_plugins/

# git log --format=%B 4.0.0..5.0.0 | sed '/^\s*$/d' | sort | uniq
16 changes: 4 additions & 12 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ New ideas:
☐ ✨ amf encode/decode
☐ ✨ aes cmac
☐ ✨ whitespace encoding https://www.dcode.fr/whitespace-language
beaufort
beaufort
☐ register support in callstack
☐ 🔥 update python_requires in setup.py on python version change
☐ 🐙 update config to use envars also

Bug:

Expand Down Expand Up @@ -59,14 +60,5 @@ Misc:
☐ cyberchef recipe to chepy recipe converter

Archive:
✔ 🐙 diff show results only
✔ 🐙 update ascii in xor function to documentation
✔ 🐛 search with bytes is erroring
✔ ✨ base62
✔ ✨ callback function that can take a python function and run it over state. handle recipes for this
✔ ✨ automatic delimiter detect
✔ ✨ rabbit encryption
✔ ✨ cetacean encode/decode
✔ ✨ huffman encode/decode
✔ ✨ new plugin that can help detect encoding type trained on random data
✔ ✨ bifd
✔ ecb no padding in aes/des
✔ update ml model with different spacing for hex, binary etc
2 changes: 1 addition & 1 deletion chepy/chepy_plugins
2 changes: 1 addition & 1 deletion chepy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,5 @@ def load_plugins(self): # pragma: no cover
loaded = getattr(plugin, klass)
plugins.append(loaded)
except:
logging.warning("Error loading {}".format(plugin.__name__))
logging.warning(f"Error loading {plugin.__name__}")
return plugins
2 changes: 1 addition & 1 deletion chepy/modules/dataformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ def to_hex(self, delimiter: str = "") -> DataFormatT:
return self

@ChepyDecorators.call_stack
def from_hex(self, delimiter: str = None, join_by: str = " ") -> DataFormatT:
def from_hex(self, delimiter: str = None, join_by: str = "") -> DataFormatT:
"""Convert a non delimited hex string to string
Args:
Expand Down
2 changes: 1 addition & 1 deletion chepy/modules/dataformat.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DataFormat(ChepyCore):
def from_base64(self: DataFormatT, custom: str=..., url_safe: bool=...) -> DataFormatT: ...
def decode_bytes(self: DataFormatT, errors: Literal['ignore', 'backslashreplace', 'replace']=...) -> DataFormatT: ...
def to_hex(self: DataFormatT, delimiter: str=..., join_by: str=...) -> DataFormatT: ...
def from_hex(self: DataFormatT, delimiter: Union[str, None]=None) -> DataFormatT: ...
def from_hex(self: DataFormatT, delimiter: Union[str, None]=None, join_by: str='') -> DataFormatT: ...
def hex_to_int(self: DataFormatT) -> DataFormatT: ...
def hex_to_bytes(self: DataFormatT) -> DataFormatT: ...
def hex_to_str(self: DataFormatT, ignore: bool=...) -> DataFormatT: ...
Expand Down
29 changes: 23 additions & 6 deletions chepy/modules/encryptionencoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,18 +802,24 @@ def triple_des_decrypt(
b"some data"
"""

self.__check_mode(mode)

key, iv = self._convert_key(key, iv, key_format, iv_format)

if mode == "CBC":
cipher = DES3.new(key, mode=DES3.MODE_CBC, iv=iv)
self.state = Padding.unpad(cipher.decrypt(self._convert_to_bytes()), 8)
return self
elif mode == "CBC/NoPadding":
cipher = DES3.new(key, mode=DES3.MODE_CBC, iv=iv)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
elif mode == "ECB":
cipher = DES3.new(key, mode=DES3.MODE_ECB)
self.state = Padding.unpad(cipher.decrypt(self._convert_to_bytes()), 8)
return self
elif mode == "ECB/NoPadding":
cipher = DES3.new(key, mode=DES3.MODE_ECB)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
elif mode == "CTR":
cipher = DES3.new(key, mode=DES3.MODE_CTR, nonce=b"")
self.state = cipher.decrypt(self._convert_to_bytes())
Expand All @@ -822,6 +828,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')

@ChepyDecorators.call_stack
def aes_encrypt(
Expand Down Expand Up @@ -894,7 +902,7 @@ def aes_decrypt(
key_format: str = "hex",
iv_format: str = "hex",
) -> EncryptionEncodingT:
"""Decrypt raw state encrypted with DES.
"""Decrypt raw state encrypted with AES.
CFB mode reflects Cyberchef and not native python behaviour.
Args:
Expand All @@ -916,22 +924,28 @@ def aes_decrypt(
b"some data"
"""

assert mode in ["CBC", "CFB", "OFB", "CTR", "ECB", "GCM"], "Not a valid mode."

key, iv = self._convert_key(key, iv, key_format, iv_format)

if mode == "CBC":
cipher = AES.new(key, mode=AES.MODE_CBC, iv=iv)
self.state = Padding.unpad(cipher.decrypt(self._convert_to_bytes()), 16)
return self
if mode == "CFB":
elif mode == "CBC/NoPadding":
cipher = AES.new(key, mode=AES.MODE_CBC, iv=iv)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
elif mode == "CFB":
cipher = AES.new(key, mode=AES.MODE_CFB, iv=iv, segment_size=128)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
elif mode == "ECB":
cipher = AES.new(key, mode=AES.MODE_ECB)
self.state = Padding.unpad(cipher.decrypt(self._convert_to_bytes()), 16)
return self
elif mode == "ECB/NoPadding":
cipher = AES.new(key, mode=AES.MODE_ECB)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
elif mode == "CTR":
counter = Counter.new(128, initial_value=int.from_bytes(iv, "big"))
cipher = AES.new(key, mode=AES.MODE_CTR, counter=counter)
Expand All @@ -949,6 +963,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')

@ChepyDecorators.call_stack
def blowfish_encrypt(
Expand Down Expand Up @@ -1108,6 +1124,7 @@ def vigenere_decode(self, key: str) -> EncryptionEncodingT:
alphabet = "abcdefghijklmnopqrstuvwxyz"
output = ""
fail = 0
key = key.lower()

if not key:
raise ValueError("No key entered") # pragma: no cover
Expand Down
12 changes: 6 additions & 6 deletions chepy/modules/encryptionencoding.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ class EncryptionEncoding(ChepyCore):
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 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"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ...
def des_decrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]=..., key_format: FORMAT=..., iv_format: 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: ...
def des_decrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]="CBC", key_format: FORMAT="hex", iv_format: FORMAT="hex") -> EncryptionEncodingT: ...
def chacha_encrypt(self: EncryptionEncodingT, key: str, nonce: str=..., key_format: FORMAT=..., nonce_format: FORMAT=...) -> EncryptionEncodingT: ...
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"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ...
def triple_des_decrypt(self: EncryptionEncodingT, key: str, iv: str=..., mode: Literal["CBC", "OFB", "CTR", "ECB"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ...
def aes_encrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: str=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM"]=..., key_format: FORMAT=..., iv_format: FORMAT=...) -> EncryptionEncodingT: ...
def aes_decrypt(self: EncryptionEncodingT, key: Union[bytes, str], iv: str=..., mode: Literal["CBC", "CFB", "OFB", "CTR", "ECB", "GCM"]=..., key_format: FORMAT=..., iv_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 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: ...
Expand Down
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[metadata]
description-file = README.md

[tool:pytest]
testpaths = tests tests_plugins
2 changes: 1 addition & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def test_load_file_binary():

def test_show_recipe():
assert Chepy("4142").from_hex().recipe == [
{"function": "from_hex", "args": {"delimiter": None, "join_by": " "}}
{"function": "from_hex", "args": {"delimiter": None, "join_by": ""}}
]


Expand Down
20 changes: 19 additions & 1 deletion tests/test_encryptionencoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,22 @@ def test_aes_decrypt():
.o
== b"some data"
)
assert (
Chepy("6bcd22d5c24a59a818f39ba64b7f2d21")
.from_hex()
.aes_decrypt("b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", iv='404cce974703e46da08c3fb65c469109', mode='ECB/NoPadding')
.to_hex()
.o
== b"68656c6c6f0b0b0b0b0b0b0b0b0b0b0b"
)
assert (
Chepy("dda597db9a1b3627f64fb3397502c6f4")
.from_hex()
.aes_decrypt("b88e5c5597eb6e5e9d1ce47ab2eb57d0fcbd44a3c3a648116cbf6b09073f836b", iv='404cce974703e46da08c3fb65c469109', mode='CBC/NoPadding')
.to_hex()
.o
== b"68656c6c6f0b0b0b0b0b0b0b0b0b0b0b"
)


def test_des_decrypt():
Expand Down Expand Up @@ -540,6 +556,8 @@ 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'


def test_blowfish_encrypt():
Expand Down Expand Up @@ -622,7 +640,7 @@ def test_vigener_encode():

def test_vigenere_decode():
assert (
Chepy("npcdhzaon{a4Rmp!_K1N5q0p_4vQfKkT1uA3R}").vigenere_decode("victory").o
Chepy("npcdhzaon{a4Rmp!_K1N5q0p_4vQfKkT1uA3R}").vigenere_decode("vicTOry").o
== b"shaktictf{y4Yyy!_M1S5i0n_4cCoMpL1sH3D}"
)
assert Chepy("kieiim").vigenere_decode("secret").o == b"secret"
Expand Down

0 comments on commit fc4f009

Please sign in to comment.