class obsidianpermutation:
    def __init__(self, block_size=32):
        self._block_size = block_size
        self._perm_table = list(range(block_size * 8))
        self._inv_perm_table = list(range(block_size * 8))
    
    def generate_permutation(self, seed):
        state = seed
        total_bits = self._block_size * 8
        perm = list(range(total_bits))
        
        for i in range(total_bits - 1, 0, -1):
            state = self._prng_step(state)
            j = state % (i + 1)
            perm[i], perm[j] = perm[j], perm[i]
        
        self._perm_table = perm
        self._inv_perm_table = [0] * total_bits
        for i, p in enumerate(perm):
            self._inv_perm_table[p] = i
    
    def _prng_step(self, state):
        state ^= (state << 21) & 0xffffffffffffffff
        state ^= (state >> 35) & 0xffffffffffffffff
        state ^= (state << 4) & 0xffffffffffffffff
        return (state * 0x2545f4914f6cdd1d) & 0xffffffffffffffff
    
    def permute(self, data):
        if len(data) != self._block_size:
            raise ValueError(f"data must be {self._block_size} bytes")
        
        bits = []
        for byte in data:
            for i in range(7, -1, -1):
                bits.append((byte >> i) & 1)
        
        permuted_bits = [bits[self._perm_table[i]] for i in range(len(bits))]
        
        result = bytearray(self._block_size)
        for i in range(self._block_size):
            byte = 0
            for j in range(8):
                byte = (byte << 1) | permuted_bits[i * 8 + j]
            result[i] = byte
        
        return bytes(result)
    
    def inverse_permute(self, data):
        if len(data) != self._block_size:
            raise ValueError(f"data must be {self._block_size} bytes")
        
        bits = []
        for byte in data:
            for i in range(7, -1, -1):
                bits.append((byte >> i) & 1)
        
        permuted_bits = [bits[self._inv_perm_table[i]] for i in range(len(bits))]
        
        result = bytearray(self._block_size)
        for i in range(self._block_size):
            byte = 0
            for j in range(8):
                byte = (byte << 1) | permuted_bits[i * 8 + j]
            result[i] = byte
        
        return bytes(result)
