So I've been working on a simple little hashing algorithm for Python that I like to call PRBHA-10 for short, or Pseudo-Random-Based Hash Algorithm. This is a hash algorithm in Python that is meant to be simplistic and secure. As you could see from the title, the algorithm implements a system with seeding the pseudo-random number generator to be able to produce the correct integer values when provided the correct password, therefore enabling the decryption of an encrypted byte sequence or string.
Here's the advantages of my method:
The functions are tiny and simple, unlike some hashing methods out there.
Despite the simplicity of the algorithm, it is secure due to the generation of large random numbers that scale with the password size.
There is no chance of revealing even part of the encrypted string without the full password due to the huge numbers created by the seeded PRNG and multiplication that completely messes up the string if the wrong password is entered.
It is fast. I have not done
timeit
s yet, but the functions run in a trivial amount of time to generate their results.
The disadvantages:
A somewhat large password is required to ensure security - usually anything over seven characters is completely cryptographically secure.
It is vulnerable to the same brute-force attacks that any cryptographic encryption method is vulnerable to.
With larger passwords comes greater security, but also a larger hash. The hash size slightly increases with each character added onto the password.
Here's the whole module program, prhba.py
:
"""Pseudo-Random Based Hash Algorithm (PRHBA-10) is a simple
Python cipher that uses the integer representation of a
string, along with taking advantage of the built-in
pseudo-random number generator to be able to securely encrypt
strings and bytearrays.
The algorithm uses the integer representation of byte sequences,
seeding the random number generator using the password to
create a predictable random number for later use, and a special
encoded form to turn any byte sequence into an ASCII string
using only the letters 'aceilnorst'. This is secure due to the
extremely large random number generated ensuring the security
of the result.
The result can be later decrypted using a special algorithm to
decipher the text into a large integer number. Then, the
password is used as a seed to once again get the random number
used earlier in the process. That integer is used to modify
the large integer to be able to get the integer form of the
original string, which can then be converted to a string.
This cipher currently only works in Python due to the specific
random number generation implementation in the `random` module.
"""
import math
import random
__all__ = ["encrypt", "decrypt"]
LETTERS = "aceilnorst"
def to_num(s):
return int.from_bytes(s.encode(), 'little')
def from_num(n):
return n.to_bytes(math.ceil(n.bit_length() / 8), 'little')
def encrypt(data, password):
assert len(password) > 1, "Password length cannot be less than two"
random.seed(to_num(password))
unique_id = to_num(data) * random.getrandbits(len(password))
chunk = []
for digit in str(unique_id):
chunk.append(LETTERS[int(digit)])
return "".join(chunk)
def decrypt(encrypted_data, password):
random.seed(to_num(password))
partnum_digits = []
for char in encrypted_data:
partnum_digits.append(str(LETTERS.index(char)))
partnum = int("".join(partnum_digits))
return from_num(partnum // random.getrandbits(len(password)))
Here's the questions I have:
Is it PEP-8 compliant?
Are the variable names confusing?
Is there any parts that could be improved or further reduced?
Do you have any other suggestions?
Thanks in advance!