Skip to content

Commit

Permalink
πŸ—“ Aug 28, 2023 9:40:38 PM
Browse files Browse the repository at this point in the history
✨ ls_47 encryption/decryption
πŸ™ rsa_enc/dec/sign/verify support for both PEM file and str
πŸ™ rsa_enc/dec/sign/verify support for PKCS and OEAP
  • Loading branch information
securisec committed Aug 29, 2023
1 parent 23c03e5 commit 028e035
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 37 deletions.
6 changes: 5 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ New ideas:
☐ ✨ rabbit encryption
☐ ✨ aes cmac
☐ ✨ cetacean encode/decode
☐ ✨ ls47 enc/dec
☐ ✨ Letter Number Code (A1Z26) A=1, B=2, C=3 encoder/decoder T4 l16 _36 510 _27 s26 _11 320 414 {6 }39 C2 T0 m28 317 y35 d31 F1 m22 g19 d38 z34 423 l15 329 c12 ;37 19 h13 _30 F5 t7 C3 325 z33 _21 h8 n18 132 k24 = TFCCTF{th15_ch4ll3ng3_m4k3s_m3_d1zzy_;d}
☐ ✨ whitespace encoding https://www.dcode.fr/whitespace-language
☐ ✨ huffman encode/decode
☐ ✨ bacon encode/decode
☐ ✨ new plugin that can help detect encoding type trained on random data

Bug:

Expand Down Expand Up @@ -62,6 +65,7 @@ Misc:
☐ cyberchef recipe to chepy recipe converter

Archive:
βœ” ✨ ls47 enc/dec
βœ” ✨ shuffle
βœ” πŸš€ add crib for xor bruteforce
βœ” ✨ twin hex encoder/decoder
Expand Down
148 changes: 116 additions & 32 deletions chepy/modules/encryptionencoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import string
import random
from typing import Literal, TypeVar, Dict, Any, Union
from .internal.ls47 import (
encrypt_pad as _ls47_enc,
decrypt_pad as _ls47_dec,
derive_key as _derive_key,
)

import lazy_import

Expand All @@ -24,6 +29,7 @@
Counter = lazy_import.lazy_module("Crypto.Util.Counter")
PKCS1_15 = lazy_import.lazy_module("Crypto.Signature.pkcs1_15")
PKCS1_OAEP = lazy_import.lazy_module("Crypto.Cipher.PKCS1_OAEP")
PKCS1_v1_5 = lazy_import.lazy_module("Crypto.Cipher.PKCS1_v1_5")
Blowfish = lazy_import.lazy_module("Crypto.Cipher.Blowfish")
Padding = lazy_import.lazy_module("Crypto.Util.Padding")
pycipher = lazy_import.lazy_module("pycipher")
Expand Down Expand Up @@ -80,6 +86,19 @@ def _convert_key(
iv = binascii.unhexlify(binascii.hexlify(iv))
return key, iv

def _rsa_process_key(self, key: str, is_file: bool, passphrase=None):
"""Returns an RSA instance for either keyfile or string key"""
if is_file:
with open(str(self._abs_path(key)), "r") as f:
return RSA.import_key(f.read(), passphrase)
return RSA.import_key(key, passphrase)

def _rsa_cipher(self, c_format: str, rsa):
"""Returns an RSA Cipher instnace based for cipher type"""
if c_format == "PKCS":
return PKCS1_v1_5.new(rsa)
return PKCS1_OAEP.new(rsa)

@ChepyDecorators.call_stack
def rotate(self, rotate_by: int) -> EncryptionEncodingT:
"""Rotate string by provided number
Expand Down Expand Up @@ -1239,75 +1258,105 @@ def from_morse_code(
return self

@ChepyDecorators.call_stack
def rsa_encrypt(self, pub_key_path: str) -> EncryptionEncodingT:
def rsa_encrypt(
self,
public_key: str,
is_file: bool = True,
passphrase: str = None,
cipher: Literal["OAEP", "PKCS"] = "OAEP",
) -> EncryptionEncodingT:
"""Encrypt data with RSA Public key in PEM format
Args:
pub_key_path (str): Path to Public key
public_key (str): Path to Public key
is_file (bool): If supplied argument is a PEM file path. Defaults to false
passphrase (str): passphrase. Defaults to None
cipher (str): Cipher type. Defaults to OAEP
Returns:
Chepy: The Chepy object
"""
with open(str(self._abs_path(pub_key_path)), "r") as f:
pub_key = f.read()
key = RSA.importKey(pub_key)
cipher = PKCS1_OAEP.new(key)
self.state = cipher.encrypt(self._convert_to_bytes())
return self
rsa = self._rsa_process_key(public_key, is_file, passphrase)
c = self._rsa_cipher(cipher, rsa)
self.state = c.encrypt(self._convert_to_bytes())
return self

@ChepyDecorators.call_stack
def rsa_decrypt(self, priv_key_path: str) -> EncryptionEncodingT:
def rsa_decrypt(
self,
private_key: str,
is_file: bool = True,
passphrase: str = None,
cipher: Literal["OAEP", "PKCS"] = "OAEP",
) -> EncryptionEncodingT:
"""Decrypt data with RSA Private key in PEM format
Args:
priv_key_path (str): Path to Private key
private_key (str): Path to Private key
is_file (bool): If supplied argument is a PEM file path. Defaults to false
passphrase (str): passphrase. Defaults to None
cipher (str): Cipher type. Defaults to OAEP
Returns:
Chepy: The Chepy object
"""
with open(str(self._abs_path(priv_key_path)), "r") as f:
priv_key = f.read()
key = RSA.importKey(priv_key)
cipher = PKCS1_OAEP.new(key)
self.state = cipher.decrypt(self._convert_to_bytes())
return self
rsa = self._rsa_process_key(private_key, is_file, passphrase)
c = self._rsa_cipher(cipher, rsa)
if cipher == "PKCS":
self.state = c.decrypt(self._convert_to_bytes(), None)
else:
self.state = c.decrypt(self._convert_to_bytes())
return self

@ChepyDecorators.call_stack
def rsa_sign(self, priv_key_path: str) -> EncryptionEncodingT:
def rsa_sign(
self,
private_key: str,
is_file: bool = True,
passphrase: str = None,
hash_format: Literal["SHA256", "SHA512", "SHA1", "MD5", "SHA384"] = "SHA256",
) -> EncryptionEncodingT:
"""Sign data in state with RSA Private key in PEM format
Args:
priv_key_path (str): Path to Private key
private_key (str): Private key
is_file (bool): If supplied argument is a PEM file path. Defaults to false
passphrase (str): passphrase. Defaults to None
hash_format (str): hash type. Defaults to SHA256
Returns:
Chepy: The Chepy object
"""
with open(str(self._abs_path(priv_key_path)), "r") as f:
priv_key = f.read()
key = RSA.importKey(priv_key)
h = Hash.SHA256.new(self._convert_to_bytes())
self.state = PKCS1_15.new(key).sign(h)
return self
rsa = self._rsa_process_key(private_key, is_file, passphrase)
h = getattr(Hash, hash_format).new(self._convert_to_bytes())
self.state = PKCS1_15.new(rsa).sign(h)
return self

@ChepyDecorators.call_stack
def rsa_verify(
self, signature: bytes, public_key_path: str
self,
signature: bytes,
public_key: str,
is_file: bool = True,
passphrase: str = None,
hash_format: Literal["SHA256", "SHA512", "SHA1", "MD5", "SHA384"] = "SHA256",
) -> EncryptionEncodingT: # pragma: no cover
"""Verify data in state with RSA Public key in PEM format
Args:
signature (bytes): The signature as bytes
public_key_path (str): Path to Private key
public_key (str): Path to Private key
is_file (bool): If supplied argument is a PEM file path. Defaults to false
passphrase (str): passphrase. Defaults to None
hash_format (str): Cipher type. Defaults to SHA256
Returns:
Chepy: The Chepy object
"""
with open(str(self._abs_path(public_key_path)), "r") as f:
pub_key = f.read()
key = RSA.importKey(pub_key)
h = Hash.SHA256.new(self._convert_to_bytes())
self.state = PKCS1_15.new(key).verify(h, signature)
return self
rsa = self._rsa_process_key(public_key, is_file, passphrase)
h = getattr(Hash, hash_format).new(self._convert_to_bytes())
self.state = PKCS1_15.new(rsa).verify(h, signature)
return self

@ChepyDecorators.call_stack
def rsa_private_pem_to_jwk(self) -> EncryptionEncodingT:
Expand Down Expand Up @@ -1469,3 +1518,38 @@ def from_letter_number_code(
continue
self.state = join_by.join(hold).encode()
return self

@ChepyDecorators.call_stack
def ls47_encrypt(
self, password: str, padding: int = 10, signature: str = ""
) -> EncryptionEncodingT:
"""LS47 encrypt
Args:
password (str): password
padding (int, optional): Padding. Defaults to 10.
signature (str, optional): Signature to prepend. Defaults to ''.
Returns:
Chepy: The Chepy object.
"""
key = _derive_key(password)
self.state = _ls47_enc(
key, self._convert_to_str(), padding_size=padding, signature=signature
)
return self

@ChepyDecorators.call_stack
def ls47_decrypt(self, password: str, padding: int = 10) -> EncryptionEncodingT:
"""LS47 decrypt
Args:
password (str): password
padding (int, optional): Padding. Defaults to 10.
Returns:
Chepy: The Chepy object.
"""
key = _derive_key(password)
self.state = _ls47_dec(key, padding, self._convert_to_str())
return self
10 changes: 6 additions & 4 deletions chepy/modules/encryptionencoding.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ class EncryptionEncoding(ChepyCore):
def atbash_decode(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def to_morse_code(self: EncryptionEncodingT, dot: str=..., dash: str=..., letter_delim: str=..., word_delim: str=...) -> EncryptionEncodingT: ...
def from_morse_code(self: EncryptionEncodingT, dot: str=..., dash: str=..., letter_delim: str=..., word_delim: str=...) -> EncryptionEncodingT: ...
def rsa_encrypt(self: EncryptionEncodingT, pub_key_path: str) -> EncryptionEncodingT: ...
def rsa_decrypt(self: EncryptionEncodingT, priv_key_path: str) -> EncryptionEncodingT: ...
def rsa_sign(self: EncryptionEncodingT, priv_key_path: str) -> EncryptionEncodingT: ...
def rsa_verify(self: EncryptionEncodingT, signature: bytes, public_key_path: str) -> EncryptionEncodingT: ...
def rsa_encrypt(self: EncryptionEncodingT, public_key: str, is_file: bool=False, passphrase: Union[str, None]=None, cipher:Literal['OAEP', 'PKCS']='OAEP') -> EncryptionEncodingT: ...
def rsa_decrypt(self: EncryptionEncodingT, private_key: str, is_file: bool=False, passphrase: Union[str, None]=None, cipher:Literal['OAEP', 'PKCS']='OAEP') -> EncryptionEncodingT: ...
def rsa_sign(self: EncryptionEncodingT, private_key: str, is_file: bool=False, passphrase: Union[str, None]=None, hash_format: Literal['SHA256', 'SHA512', 'SHA1', 'MD5', 'SHA384']='SHA256') -> EncryptionEncodingT: ...
def rsa_verify(self: EncryptionEncodingT, signature: bytes, public_key: str, is_file: bool=False, passphrase: Union[str, None]=None, hash_format: Literal['SHA256', 'SHA512', 'SHA1', 'MD5', 'SHA384']='SHA256') -> EncryptionEncodingT: ...
def rsa_private_pem_to_jwk(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def rsa_public_key_from_jwk(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def monoalphabetic_substitution(self: EncryptionEncodingT, mapping: Dict[str, str]=...): ...
def to_letter_number_code(self: EncryptionEncodingT, join_by: Union[str, bytes]=...) -> EncryptionEncodingT: ...
def from_letter_number_code(self: EncryptionEncodingT, delimiter: Union[str, bytes]=..., join_by: Union[str, bytes]=...) -> EncryptionEncodingT: ...
def ls47_encrypt(self: EncryptionEncodingT, password: str, padding: int=..., signature: str=...) -> EncryptionEncodingT: ...
def ls47_decrypt(self: EncryptionEncodingT, password: str, padding: int=...) -> EncryptionEncodingT: ...

0 comments on commit 028e035

Please sign in to comment.