Skip to content

A project made to learn a bit more about cryptography and python

License

Notifications You must be signed in to change notification settings

RoyNisimov1/CHA

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

READ ME

This was made for fun and learning cryptography and python. Everything here is not for real use-cases. Keep in mind that the functions here are probably insecure. They went through 0 security checks, and were made without thinking of the security side of things.

Hashing use cases

  1. Detecting duplicated records.
  2. Locating points that are near each other.
  3. Verifying message integrity.
  4. Verifying passwords.

Installation

pip

pip install cha-hashing

how to use

import CHA *

from CHA import FeistelN
from CHA import CHAObject
from CHA import HashMaker
from CHA import Piranha
from CHA import PEMFile

or just

from CHA import *

How RA works

The shuffle algorithm

def shuffle(to_shuffle_list: list):
    to_shuffle_list = to_shuffle_list.copy()
    to_append_size = to_shuffle_list[0]
    a = []
    for i1 in range(to_append_size % len(to_shuffle_list)):
        a.append(to_shuffle_list.pop(0))
    to_shuffle_list.reverse()
    for i2 in a:
        to_shuffle_list.append(i2)
    e = []
    for i3, ch in enumerate(to_shuffle_list):
        if i3 % 2 == 0:
            e.append(to_shuffle_list.pop(i3))
    for i4 in e:
        to_shuffle_list.append(i4)
    return to_shuffle_list

Step One: Encipher

The function enciphers each letter with a letter in the shuffle list if it exists there, then shifts the letters in the shuffle list by the ord of c ** ord c each time.

for c in message:
    for i in range(0, pow(ord(c), ord(c), len(shuffle_list))):
        first = shuffle_list.pop(0)
        shuffle_list.append(first)
    ord_shuffle_list = [ord(c) for c in shuffle_list]
    shuffled = shuffle(ord_shuffle_list)
    shuffle_list = [chr(c) for c in shuffled]
    if c in characters and c in shuffle_list:
        index = characters.index(c)
        original_message.append(shuffle_list[index])
    else:
        original_message.append(c)

Step Two: Padding

binary_formatted_message = [format(ord(c), 'b') for c in original_message]

            amount_to_shift = len(padding_list) - len(binary_formatted_message)
            if amount_to_shift <= 0: amount_to_shift *= -1
            shift_must = ord(original_message[0]) if len(original_message) > 0 else shift_must_if_om0
            amount_to_shift += shift_must
            binary_formatted_message.extend(padding_list)

Step Three: Keying

key = binary_formatted_message.copy()
            for i in range(0, amount_to_shift):
                if times % rev_every == 0:
                    key.reverse()
                first = key.pop(0)
                key.append(first)
            if key == binary_formatted_message:
                first = key.pop(0)
                key.append(first)

Step Four: XORing

In this step we XOR the ciphertext with our key

binary_formatted_message = list(int(c, 2) for c in binary_formatted_message)
key = list(int(c, 2) for c in key)
xored = []
for i in range(len(binary_formatted_message)):
    xored.append(binary_formatted_message[i] ^ key[i])

Step Five: Repeat and shift padding

binary_formatted_message = list(int(c, 2) for c in binary_formatted_message)
key = list(int(c, 2) for c in key)
xored = []
for i in range(len(binary_formatted_message)):
    xored.append(binary_formatted_message[i] ^ key[i])

Step Six: Final

We join this large list, turn that into an int, and then we return a CHAObject object of it

s_xored = [str(n) for n in xored]
s = ''
for string in s_xored:
    s += string.strip("-")
s = s[0:size_limit_of_0]
for i in range(pow(amount_to_shift, amount_to_shift, len(padding_list))):
    intL = [int(c, 2) for c in padding_list]
    padding_list = shuffle(intL)
    padding_list = [format(c, 'b') for c in padding_list]
message = s

CHA - Customizable Hashing Algorithm

CHA works the same way as RA, but customizable. so I'll only talk about the customization.

message

The plaintext that enters the function.

padding

The padding as a byte string separated by a space, like : '01110011 00110011 11000110'. this will be appended to the message

shaffle_list

The letter shuffle list Check the encipher step in the RA

size_limit_of_0

how many 0 are allowed

rep

number of repetitions

char_set

Additional chars used in the shuffle_list

shift_must_if_om0

shift_must = ord(om[0]) if len(om) > 0 else shift_must_if_om0

rev_every

Will preform some additional tasks with every time % $rev_every == 0

CHAB

Like CHA but the message is in bytes

HMAC

Syntax for hmac:

from CHA import FeistelN
from CHA import CHAFHMAC
# our secret key:

secret = b'test'
# message
msg = b'secret msg'
# creating a hmac obj
hmac_obj = CHAFHMAC(secret, func=FeistelN.fRAB_with_nonce(secret))
hmac_obj.update(msg)
# getting a mac
mac = hmac_obj.hexdigest()
print(mac)
# verifying a mac
print(hmac_obj.verify(mac))

Creating your own algorithm using HashMaker

RandomShaffle

This function will help you make your own random shuffled charset (secrets.SystemRandom().shuffle(letters) but with built-in langs) returns a string

RandomBits

This function will help you make your own random bits. returns a string or a list

how_many:
how many groups of bits do you want.
group:
how many in one group, 8 for a byte
how_to_format:
Can be " " or "l". 
"l" for a list.
" " for a " ".join(bits)

get_CHA_args

This function will print the syntax needed. and return the padding, and shuffle key.

Note

There is a chance that some padding or shuffle_key have a backdoor in them (I don't know if there really is, but probably).

Encryption with CHA

CHA can be also used as an encryption function using the feistel cipher (see CHAF)

for example:

    def fCHA(b):
        padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()
        return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)
    s = input("Enter an input:\n").encode()
    e = FeistelN().DE(s,  8, fCHA)
    print(e)
    d = FeistelN().DE(e,  8,fCHA, 'd')
    print(d)

to make your own:

define a function

define a function using this template

    def fCHA(b):
        padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()
        return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)

the function needs to return bytes, here we're using CHAB with the RA args.

Call DE

then the Feistel function uses 64 bits everytime, I configed the DE function on the FeistelN class to do this automatically.

mode 'e'

this will return a list of hexes

mode 'd'

will return the string

Feistel Cipher - Computerphile

BlackFrog

This is an asymmetric encryption algorithm

Key generation:
—---------------------------------------------------------------

Let n = large prime number

Pick e such that gcd(e,n) == 1 and e < n and e is prime
d = e**-1 % n
N = n * e * random
E = e**d % N
D = d**d % n

Public key: {E,N}
Private key: {n,d,e,D}

Encryption:
—---------------------------------------------------------------

ciphertext = message*E % N

Decryption:
—---------------------------------------------------------------
message = ciphertext*D % n

Generate keys

returns two keys, one public, one private

Encrypt

Encrypts bytes with public key and returns cipher text as bytes

Decrypt

Decrypt bytes with private key and returns message text as bytes

Piranha

I made this cipher using the RAB-Feistel network.

I made this to learn about modes of operation.

Right now the available modes are:

  • ECB
  • CBC
  • CTR
  • EAA (My Encrypt and Authenticate, not EAX)
    key = b"super secret key"
    msg = b'Test message'
    # EBC
    cipher = Piranha(key, Piranha.EBC)
    c = cipher.encrypt(msg)
    print(c)
    cipher = Piranha(key, Piranha.EBC)
    m = cipher.decrypt(c)
    print(m)

    # CBC
    cipher = Piranha(key, Piranha.CBC)
    paddedMsg = Piranha.pad(msg, Piranha.BlockSize)
    c = cipher.encrypt(paddedMsg)
    print(c)
    cipher = Piranha(key, Piranha.CBC, iv=cipher.iv)
    m = Piranha.unpad(cipher.decrypt(c))
    print(m)

    # CTR
    cipher = Piranha(key, Piranha.CTR)
    paddedMsg = Piranha.pad(msg, Piranha.BlockSize)
    c = cipher.encrypt(paddedMsg)
    print(c)
    cipher = Piranha(key, Piranha.CTR, iv=cipher.iv)
    m = Piranha.unpad(cipher.decrypt(c))
    
    # EAA
    key = b"key"
    m = Piranha.pad(b'test')
    cipher = Piranha(key, Piranha.EAA, data=m)
    a = cipher.encrypt(m)
    print(a)
    cipher = Piranha(key, Piranha.EAA, iv=cipher.iv, data=a)
    print(Piranha.unpad(cipher.decrypt(a)))

KRY and KRHASH

I made this cipher using the KRHASH-Feistel network.

I made this to learn about modes of operation.

Right now the available modes are:

  • ECB
  • CBC
  • CTR
  • EAA (My Encrypt and Authenticate, not EAX)

Works similar to Piranha, just replace Piranha with KRY

CowCowModes

I made this cipher using the CowCow-sp network.

I made this to learn about modes of operation.

Right now the available modes are:

  • ECB
  • CTR
  • EAA (My Encrypt and Authenticate, not EAX)

Works similar to Piranha, just replace Piranha with CowCowModes

Modes (Build you own)

Right now the available modes are:

  • ECB
  • CBC
  • CTR
  • EAA (My Encrypt and Authenticate, not EAX)

Warning: do not init directly, use Modes.new()

Notes:

This is insecure! I made everything for fun and learning! Do not use in real usecases

PS: I know my code looks bad

About

A project made to learn a bit more about cryptography and python

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages