From Newsgroup: sci.crypt
On 1/4/2026 9:23 PM, Chris M. Thomasson wrote:
For some reason, the AI wanted to rewrite my python code from:
http://funwithfractals.atspace.cc/ct_cipher
Here is what it dumped out:
[...]
It wrote a test that tries to alter a single bit of ciphertext:
import hashlib
import hmac
import os
# 1. Improved Hex Utility
# ____________________________________________________________
def ct_bytes_to_hex(data):
return '\n'.join(data[i:i+16].hex(' ') for i in range(0, len(data), 16)).upper()
# 2. Key Class (Handles Raw Bytes)
# ____________________________________________________________
class ct_secret_key:
def __init__(self, hmac_key, hash_algo, rand_n):
self.hmac_key = hmac_key if isinstance(hmac_key, bytes) else hmac_key.encode()
self.hash_algo = hash_algo
self.rand_n = rand_n
# 3. The Crypt Round Function (Raw Byte Logic)
# ____________________________________________________________
def ct_crypt_round(SK, data_in, decrypt_mode):
H = hmac.new(SK.hmac_key, None, SK.hash_algo)
H.update(SK.hmac_key[::-1])
output = bytearray()
p_idx = 0
p_len = len(data_in)
while p_idx < p_len:
D = H.digest()
d_idx = 0
d_len = len(D)
while p_idx < p_len and d_idx < d_len:
p_byte = data_in[p_idx]
c_byte = p_byte ^ D[d_idx]
output.append(c_byte)
if not decrypt_mode:
H.update(bytes([p_byte, c_byte]))
else:
H.update(bytes([c_byte, p_byte]))
p_idx += 1
d_idx += 1
return bytes(output)
# 4. The Main Crypt Wrapper
# ____________________________________________________________
def ct_crypt(SK, data_in, decrypt_mode):
processed_data = data_in
if not decrypt_mode:
prefix = os.urandom(SK.rand_n)
processed_data = prefix + processed_data
C = ct_crypt_round(SK, processed_data, decrypt_mode)
C_rev = C[::-1]
final = ct_crypt_round(SK, C_rev, decrypt_mode)
if decrypt_mode:
final = final[SK.rand_n:]
return final
# ____________________________________________________________
# BIT-FLIP AVALANCHE DEMO
# ____________________________________________________________
# Fixed key for reproducibility
key_material = b"K" * 64
SK = ct_secret_key(
key_material,
hashlib.sha512,
73
)
plaintext = b"ABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDE"
print("Original plaintext:")
print(plaintext)
# Encrypt
ciphertext = ct_crypt(SK, plaintext, False)
print("\nCiphertext (hex):")
print(ct_bytes_to_hex(ciphertext))
# Flip a single bit in the ciphertext
tampered = bytearray(ciphertext)
flip_index = len(tampered) // 2
tampered[flip_index] ^= 0x01
tampered = bytes(tampered)
print("\nTampered ciphertext (hex):")
print(ct_bytes_to_hex(tampered))
# Decrypt both
decrypted_ok = ct_crypt(SK, ciphertext, True)
decrypted_bad = ct_crypt(SK, tampered, True)
print("\nDecrypted (original ciphertext):")
print(decrypted_ok)
print("\nDecrypted (tampered ciphertext):")
print(decrypted_bad)
print("\nMatches original plaintext:", decrypted_ok == plaintext) print("Tampered equals original:", decrypted_bad == plaintext)
I got:
Original plaintext:
b'ABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDE'
Ciphertext (hex):
90 DD AA 68 72 29 4E 3E 69 EF 24 11 55 1E AD 5D
C2 AA 26 6B 7A 99 91 C1 0C F2 64 33 FA 70 BC 9E
C2 2E 2F F8 59 F7 C7 03 BD 80 09 DA 47 AB 91 A3
E8 8F 3A A3 BB B5 7F CB 2A CD 78 E4 8D E9 F0 1D
F2 74 01 B8 44 DA B0 06 0D AA 76 06 19 7E 54 68
66 10 92 D1 19 38 04 FF 68 BE 75 99 86 A5 20 40
A2 8B 79 77 B1 F0 D4 41 07 3A 5C 51 8E 36 EF A1
20 19 5B 4B 72 D5 69 13 85 D8 2C 0B 45 01 30 84
1D
Tampered ciphertext (hex):
90 DD AA 68 72 29 4E 3E 69 EF 24 11 55 1E AD 5D
C2 AA 26 6B 7A 99 91 C1 0C F2 64 33 FA 70 BC 9E
C2 2E 2F F8 59 F7 C7 03 BD 80 09 DA 47 AB 91 A3
E8 8F 3A A3 BB B5 7F CB 2A CD 78 E4 8D E9 F0 1D
F3 74 01 B8 44 DA B0 06 0D AA 76 06 19 7E 54 68
66 10 92 D1 19 38 04 FF 68 BE 75 99 86 A5 20 40
A2 8B 79 77 B1 F0 D4 41 07 3A 5C 51 8E 36 EF A1
20 19 5B 4B 72 D5 69 13 85 D8 2C 0B 45 01 30 84
1D
Decrypted (original ciphertext): b'ABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDE'
Decrypted (tampered ciphertext):
b'\xf0w\xa3:\x04|\x08lw\xfc\xed L\xb5\x0f\xd3\xdb\xe2\x95\xa3^\x89\x7f\xad.\xaf\xdc\xf9\xf0\x81&\xca\xb172v\xcb\xbc\xc1X\x99\x9b\xe3Y+\xfb3B/!\x97\xfd\xb6\xb3\x9bP'
Matches original plaintext: True
Tampered equals original: False
--- Synchronet 3.21a-Linux NewsLink 1.2