-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Major updates and security improvements.
- Loading branch information
Showing
15 changed files
with
269 additions
and
182 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,59 @@ | ||
from bitarray import bitarray | ||
from bitarray.util import int2ba | ||
from hashlib import sha256 | ||
from random import shuffle, seed | ||
|
||
|
||
def pad_bitarray_left(ba, size=4): | ||
# Calculate the number of bits to pad | ||
pad_size = size - len(ba) | ||
|
||
# Create a new bitarray for padding | ||
pad = bitarray(pad_size) | ||
pad.setall(0) | ||
|
||
# Prepend the padding to the original bitarray | ||
ba[:0] = pad | ||
return ba | ||
|
||
|
||
def merge_bitarrays(*bitarrays): | ||
merged_bitarray = bitarray() | ||
|
||
# Extend the result bitarray with each bitarray in the list | ||
for ba in bitarrays: | ||
merged_bitarray.extend(ba) | ||
return merged_bitarray | ||
|
||
|
||
def split_bitarray(ba, block_size=4): | ||
return [ | ||
pad_bitarray_left(ba[i:i + block_size], block_size) | ||
for i in range(0, len(ba), block_size) | ||
] | ||
|
||
|
||
def hash(data: str, length: int = 256, block_size: int = 4) -> str: | ||
from random import shuffle, seed, randint | ||
import base64 | ||
from typing import Union | ||
from .util import to_bitarray, merge_bitarrays, pad_bitarray_left, split_bitarray | ||
import math | ||
|
||
|
||
def hash(data: Union[str, int, bitarray, bytes], | ||
length: int = 256, | ||
block_size: int = 2, | ||
affected_area: int = 0.5, | ||
output: str = "hex") -> Union[bitarray, str, int, bytes]: | ||
""" | ||
Hashes data using the hashing PCSS algorithm. | ||
The length of the hash is supplied as the length arguemnt and it must be divisible by the block size (which defaults to 4). | ||
An increased block size results in increased randomness. | ||
The length of the hash is supplied as the length arguemnt and it must be divisible by the block size (which defaults to 4). | ||
An increased block size results in increased randomness. | ||
`affected_area` is the number of input blocks used in the output block calculation. If it is an integer, it represents a concrete value, and if it is between 0 and 1 it is proportional to the number of blocks. This value is very particular, be careful! | ||
Output can be "hex", "bitarray", "bytes", "base64", "base64-bytes", or "int". | ||
""" | ||
if length % block_size != 0: | ||
raise ValueError("Length must be a multiple of block_size") | ||
encoded = bitarray() | ||
encoded.frombytes(data.encode('utf-8')) | ||
hash_data = [ | ||
encoded, | ||
int2ba(len(data)), | ||
int2ba(length), | ||
int2ba(encoded.count(1)) | ||
] | ||
encoded = to_bitarray(data) | ||
hash_data = [encoded, int2ba(length), int2ba(encoded.count(1))] | ||
blocks = [] | ||
for x in hash_data: | ||
blocks = blocks + split_bitarray(x, block_size) | ||
emptyblocks = [bitarray(block_size) for _ in range(length)] | ||
seed((length + block_size + len(data)) * int(blocks[0].to01(), 2)) | ||
emptyblocks = [bitarray(block_size) for _ in range(int(length / block_size))] | ||
seed((affected_area + (length + block_size) * int(blocks[0].to01(), 2)) * | ||
int(blocks[-1].to01(), 2) + int(encoded.to01(), 2)) | ||
if affected_area > 0 and affected_area < 1: | ||
affected_area = math.floor(affected_area * len(blocks)) | ||
for index, i in enumerate(emptyblocks): | ||
i.setall(0) | ||
shuffle(blocks) | ||
for block in blocks: | ||
x = randint(0, len(blocks) - affected_area - 1) | ||
for block in blocks[x:x + affected_area]: | ||
i ^= block | ||
x = bitarray(blocks[min(index, len(blocks) - 1)]) | ||
x.reverse() | ||
i ^= ~x | ||
emptyblocks[index] = ~i | ||
return ''.join('{:x}'.format(int(i.to01(), 2)) | ||
for i in split_bitarray(merge_bitarrays(*emptyblocks), 4)) | ||
merged = merge_bitarrays(*emptyblocks) | ||
if output == "hex": | ||
return ''.join('{:x}'.format(int(i.to01(), 2)) | ||
for i in split_bitarray(merged, 4)) | ||
elif output == 'bitarray': | ||
return merged | ||
elif output == 'bytes': | ||
return merged.tobytes() | ||
elif output == 'base64': | ||
return base64.b64encode(merged.tobytes()).decode('utf-8') | ||
elif output == 'base64-bytes': | ||
return base64.b64encode(merged.tobytes()) | ||
elif output == 'int': | ||
return int(merged.to01(), 2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from bitarray import bitarray | ||
from typing import Union | ||
from bitarray.util import int2ba | ||
|
||
|
||
def to_bitarray(data: Union[str, bytes, bitarray, int]) -> bitarray: | ||
""" | ||
Converts a string, bytes-like object, int, or bitarray to a bitarray. | ||
""" | ||
if type(data) == bytes: | ||
x = bitarray() | ||
x.frombytes(data) | ||
return x | ||
elif type(data) == str: | ||
x = bitarray() | ||
x.frombytes(data.encode()) | ||
return x | ||
elif type(data) == int: | ||
return int2ba(data) | ||
elif type(data) == bitarray: | ||
return data | ||
elif type(data) != bitarray: | ||
raise TypeError("`data` must be a bitarray or bytes-like object.") | ||
|
||
|
||
def pad_bitarray_left(ba, size=4): | ||
# Calculate the number of bits to pad | ||
pad_size = size - len(ba) | ||
|
||
# Create a new bitarray for padding | ||
pad = bitarray(pad_size) | ||
pad.setall(0) | ||
|
||
# Prepend the padding to the original bitarray | ||
ba[:0] = pad | ||
return ba | ||
|
||
|
||
def merge_bitarrays(*bitarrays): | ||
merged_bitarray = bitarray() | ||
|
||
# Extend the result bitarray with each bitarray in the list | ||
for ba in bitarrays: | ||
merged_bitarray.extend(ba) | ||
return merged_bitarray | ||
|
||
|
||
def split_bitarray(ba, block_size=4): | ||
return [ | ||
pad_bitarray_left(ba[i:i + block_size], block_size) | ||
for i in range(0, len(ba), block_size) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.