[Python] I have created an original crytographic hash function is python, and would want...

Discussão em 'Python' iniciado por Stack, Maio 10, 2025.

  1. Stack

    Stack Membro Participativo

    I’ve created a new cryptographic hash function and would like your help in thoroughly testing its security and reliability. Please begin by verifying its determinism—ensure that the same input consistently produces the same output. Next, test for pre-image resistance by attempting to reverse a given hash to its original input. Try evaluating its second pre-image resistance as well: given one input and its hash, it should be computationally infeasible to find a different input with the same hash.

    Also, please test the function’s collision resistance by trying to find two different inputs that generate the same hash. I’d like to confirm that it demonstrates a strong avalanche effect—a single-bit change in the input should cause a drastic change in the output. Run a uniformity test by hashing a large set of diverse inputs and analyzing whether the output bits are evenly distributed, indicating randomness and lack of bias.

    Check the efficiency of the function—measure its performance on inputs of various sizes to ensure it's fast enough for practical use. Regardless of input length, the function should produce outputs of a fixed length, so please confirm that too. I’d also appreciate it if you could assess its resistance to known attacks, such as length extension and differential cryptanalysis. Lastly, examine the function for any signs of backdoors or hidden vulnerabilities.

    Your feedback on these points will be invaluable in determining whether this hash function meets modern cryptographic standards. Made in python, the hash function is as follows:

    import hashlib
    import os
    import struct
    import time
    from typing import Union, Tuple, List
    import secrets
    import threading
    from concurrent.futures import ThreadPoolExecutor
    import numpy as np

    class CustomHash:
    """
    An advanced custom cryptographic hash function implementation.
    WARNING: This is for educational purposes only. Use established hash functions in production.
    """

    def __init__(self,
    salt_length: int = 64, # Increased salt length
    rounds: int = 20000, # Increased rounds
    memory_cost: int = 2048, # Increased memory cost
    parallel_chains: int = 4): # Number of parallel hash chains
    """
    Initialize the hash function with enhanced security parameters.

    Args:
    salt_length: Length of the salt in bytes (default: 64)
    rounds: Number of hashing rounds (default: 20000)
    memory_cost: Memory cost in KB for memory-hard operations (default: 2048)
    parallel_chains: Number of parallel hash chains (default: 4)
    """
    self.salt_length = salt_length
    self.rounds = rounds
    self.memory_cost = memory_cost
    self.parallel_chains = parallel_chains
    self.block_size = 128 # Increased block size to 1024 bits
    self.output_size = 64 # Increased output size to 512 bits

    # Initialize multiple S-boxes for enhanced substitution
    self._init_sboxes()

    # Initialize mixing matrices
    self._init_mixing_matrices()

    def _init_sboxes(self):
    """Initialize multiple substitution boxes for enhanced mixing."""
    # Generate multiple S-boxes using different methods
    self.sboxes = []

    # S-box 1: Random permutation
    sbox1 = list(range(256))
    secrets.SystemRandom().shuffle(sbox1)
    self.sboxes.append(sbox1)

    # S-box 2: Multiplicative inverse in GF(2^8)
    sbox2 = [self._multiplicative_inverse(i) for i in range(256)]
    self.sboxes.append(sbox2)

    # S-box 3: Affine transformation
    sbox3 = [self._affine_transform(i) for i in range(256)]
    self.sboxes.append(sbox3)

    # S-box 4: Non-linear transformation
    sbox4 = [self._nonlinear_transform(i) for i in range(256)]
    self.sboxes.append(sbox4)

    def _init_mixing_matrices(self):
    """Initialize mixing matrices for advanced state mixing."""
    # Create multiple mixing matrices
    self.mixing_matrices = []

    # Matrix 1: Random orthogonal matrix
    matrix1 = np.random.randn(8, 8)
    Q, R = np.linalg.qr(matrix1)
    self.mixing_matrices.append(Q)

    # Matrix 2: Hadamard matrix
    matrix2 = np.array([[1, 1], [1, -1]])
    for _ in range(2):
    matrix2 = np.kron(matrix2, np.array([[1, 1], [1, -1]]))
    self.mixing_matrices.append(matrix2)

    # Matrix 3: Circulant matrix
    matrix3 = np.zeros((8, 8))
    for i in range(8):
    matrix3 = np.roll([1, 2, 3, 4, 5, 6, 7, 8], i)
    self.mixing_matrices.append(matrix3)

    def _multiplicative_inverse(self, x: int) -> int:
    """Calculate multiplicative inverse in GF(2^8)."""
    if x == 0:
    return 0
    for i in range(256):
    if (x * i) % 256 == 1:
    return i
    return 0

    def _affine_transform(self, x: int) -> int:
    """Apply affine transformation to byte."""
    # Affine transformation: y = Ax + b
    A = 0x1F
    b = 0x63
    return (x * A + b) % 256

    def _nonlinear_transform(self, x: int) -> int:
    """Apply non-linear transformation to byte."""
    # Complex non-linear transformation
    x = ((x << 1) | (x >> 7)) & 0xFF # Rotate left
    x = (x * 0x1B) % 256 # Multiply by irreducible polynomial
    x = x ^ ((x >> 4) & 0x0F) # Non-linear mixing
    return x

    def _pad_message(self, message: bytes) -> bytes:
    """
    Enhanced padding with multiple security measures.

    Args:
    message: Input message to pad

    Returns:
    Padded message
    """
    message_length = len(message)
    padding_length = (self.block_size - (message_length + 17) % self.block_size) % self.block_size

    # Add padding with multiple random bytes
    padding = b'\x80' + os.urandom(padding_length)

    # Add message length, nonce, and additional entropy
    length_bytes = struct.pack('>Q', message_length * 8)
    nonce = os.urandom(8)
    entropy = struct.pack('>Q', int(time.time() * 1000000))

    return message + padding + length_bytes + nonce + entropy

    def _mix_block(self, block: bytes, state: bytes, round_num: int) -> bytes:
    """
    Enhanced block mixing with multiple operations and advanced mixing.

    Args:
    block: Block of data
    state: Current state
    round_num: Current round number

    Returns:
    New state
    """
    # Convert to numpy arrays for matrix operations, making them writable
    state_array = np.frombuffer(state, dtype=np.uint8).reshape(-1, 8).copy()
    block_array = np.frombuffer(block, dtype=np.uint8).reshape(-1, 8).copy()

    # Apply multiple mixing operations
    for i in range(len(state_array)):
    # Matrix mixing
    for matrix in self.mixing_matrices:
    state_array = np.mod(np.dot(state_array, matrix), 256).astype(np.uint8)

    # S-box substitution
    for j in range(8):
    for sbox in self.sboxes:
    state_array[j] = sbox[state_array[j]]

    # Block mixing
    state_array = np.mod(state_array.astype(np.uint16) + block_array[i % len(block_array)].astype(np.uint16), 256).astype(np.uint8)

    # Round-dependent mixing
    round_key = (round_num * 0x1F + i) & 0xFF
    state_array = state_array ^ round_key

    return state_array.tobytes()

    def _memory_hard_operation(self, state: bytes) -> bytes:
    """
    Enhanced memory-hard operations with multiple mixing passes.

    Args:
    state: Current state

    Returns:
    Modified state
    """
    # Create multiple memory buffers
    memory_buffers = [bytearray(self.memory_cost * 1024) for _ in range(self.parallel_chains)]

    # Fill memory buffers with state-dependent values
    for i in range(0, len(memory_buffers[0]), self.output_size):
    for j in range(self.parallel_chains):
    memory_buffers[j][i:i + self.output_size] = state

    # Perform parallel memory-hard mixing
    def mix_buffer(buffer_index):
    buffer = memory_buffers[buffer_index]
    for i in range(0, len(buffer) - self.output_size, self.output_size):
    block = buffer[i:i + self.output_size]
    next_block = buffer[i + self.output_size:i + 2 * self.output_size]

    # Complex mixing operations
    for j in range(self.output_size):
    buffer[i + j] = (block[j] + next_block[j]) % 256
    buffer[i + j] = self.sboxes[buffer_index % len(self.sboxes)][buffer[i + j]]

    # Execute mixing in parallel
    with ThreadPoolExecutor(max_workers=self.parallel_chains) as executor:
    executor.map(mix_buffer, range(self.parallel_chains))

    # Final mixing of all buffers
    result = bytearray(state)
    for buffer in memory_buffers:
    for i in range(0, len(buffer), self.output_size):
    block = buffer[i:i + self.output_size]
    for j in range(self.output_size):
    result[j] ^= block[j]

    return bytes(result)

    def _generate_salt(self) -> bytes:
    """
    Generate enhanced cryptographically secure random salt.

    Returns:
    Random salt bytes
    """
    # Combine multiple sources of entropy
    salt = os.urandom(self.salt_length)
    time_entropy = struct.pack('>Q', int(time.time() * 1000000))
    process_entropy = struct.pack('>Q', os.getpid())
    thread_entropy = struct.pack('>Q', threading.get_ident())

    # Mix entropy sources
    mixed_entropy = hashlib.sha512(salt + time_entropy + process_entropy + thread_entropy).digest()
    return mixed_entropy[:self.salt_length]

    def hash(self, message: Union[str, bytes], salt: bytes = None) -> Tuple[bytes, bytes]:
    """
    Enhanced hashing with multiple rounds, parallel chains, and advanced mixing.

    Args:
    message: Input message (string or bytes)
    salt: Optional salt (if None, a new salt will be generated)

    Returns:
    Tuple of (hash, salt)
    """
    if isinstance(message, str):
    message = message.encode('utf-8')

    if salt is None:
    salt = self._generate_salt()

    # Initialize multiple hash chains
    states = [hashlib.sha512(salt + struct.pack('>I', i)).digest()
    for i in range(self.parallel_chains)]

    # Add pepper
    pepper = os.urandom(32)
    salted_message = salt + message + pepper

    # Pad the message
    padded_message = self._pad_message(salted_message)

    # Multiple rounds of processing
    for round_num in range(self.rounds):
    # Process message in blocks for each chain
    for i in range(0, len(padded_message), self.block_size):
    block = padded_message[i:i + self.block_size]
    for chain in range(self.parallel_chains):
    states[chain] = self._mix_block(block, states[chain], round_num)

    # Perform memory-hard operation every 1000 rounds
    if round_num % 1000 == 0:
    for chain in range(self.parallel_chains):
    states[chain] = self._memory_hard_operation(states[chain])

    # Mix chains together
    if round_num % 100 == 0:
    mixed_state = bytearray(self.output_size)
    for chain in range(self.parallel_chains):
    for j in range(self.output_size):
    mixed_state[j] ^= states[chain][j]
    mixed_state = bytes(mixed_state)
    for chain in range(self.parallel_chains):
    states[chain] = hashlib.sha512(mixed_state + struct.pack('>I', chain)).digest()

    # Final mixing of all chains
    final_state = bytearray(self.output_size)
    for chain in range(self.parallel_chains):
    for j in range(self.output_size):
    final_state[j] ^= states[chain][j]

    return bytes(final_state), salt

    def verify(self, message: Union[str, bytes], stored_hash: bytes, salt: bytes) -> bool:
    """
    Verify if a message matches a stored hash.

    Args:
    message: Input message to verify
    stored_hash: Previously stored hash
    salt: Salt used in the stored hash

    Returns:
    True if the message matches the stored hash, False otherwise
    """
    computed_hash, _ = self.hash(message, salt)
    return secrets.compare_digest(computed_hash, stored_hash)

    def main():
    """Example usage of the enhanced hash function."""
    # Create hash function with increased security parameters
    hasher = CustomHash(
    salt_length=64,
    rounds=20000,
    memory_cost=2048,
    parallel_chains=4
    )

    # Example password
    password = "MySecretPassword123!"

    # Hash the password
    start_time = time.time()
    hash_value, salt = hasher.hash(password)
    end_time = time.time()

    print(f"Password: {password}")
    print(f"Salt: {salt.hex()}")
    print(f"Hash: {hash_value.hex()}")
    print(f"Hashing time: {end_time - start_time:.2f} seconds")

    # Verify the password
    is_valid = hasher.verify(password, hash_value, salt)
    print(f"Password verification: {'Valid' if is_valid else 'Invalid'}")

    # Try with wrong password
    wrong_password = "WrongPassword"
    is_valid = hasher.verify(wrong_password, hash_value, salt)
    print(f"Wrong password verification: {'Valid' if is_valid else 'Invalid'}")

    if __name__ == "__main__":
    main()

    Continue reading...

Compartilhe esta Página