Crib Drag攻击开发中十六进制转ASCII的Python实现问题求助
Crib拖拽攻击开发中的问题与修复方案
遇到的问题
- 十六进制转ASCII功能执行报错
- 无法正常获取用户输入并执行攻击逻辑
- 不清楚如何实现十六进制密文解密为ASCII的代码
原代码
def crib_drag_attack(guess, cp1, cp2): xor_ciphers = "" for idx in range(len(cp1)): ic1 = ord(cp1[idx]) ic2 = ord(cp2[idx]) ic_xor = ic1 ^ ic2 xor_ciphers += chr(ic_xor) for idx in range(len(xor_ciphers) - len(guess)+1): slide = xor_ciphers[idx: idx + len(guess)] results = "" for i in range(len(guess)): ig = ord(guess[i]) id = ord(slide[i]) ir = ig ^ id results += chr(ir) print(results) def encrypt(key, plaintext): idx = 0 # Declare index (idx) variable ciphertext = "" # Declare ciphertext variable for p in plaintext: # Take one character at a time in message ip = ord(p) # Convert to Decimal value code k = key[idx] # Take byte value of the key at idx ik = ord(k) # Convert to Decimal value code inew = ip ^ ik # XOR bit-by-bit ciphertext += chr(inew) # Convert to character code and Update ciphertext print(p, hex(ip), k, hex(ik), hex(inew)) # print every result idx += 1 # Increment idx by 1 hexstring = ciphertext.encode("ascii").hex() print("\n{} --> {}\n".format(ciphertext, hexstring)) trial = bytes.fromhex(hexstring).decode("ascii") print("Trial: {}".format(trial)) return ciphertext def decrypt(key, ciphertext): idx = 0 # Declare index (idx) variable plaintext = "" # Declare plaintext variable for c in ciphertext: # Take one character at a time in message ic = ord(c) # Convert to Decimal value code k = key[idx] # Take byte value of the key at idx ik = ord(k) # Convert to Decimal value code inew = ic ^ ik # XOR bit-by-bit plaintext += chr(inew) # Convert to character code and Update ciphertext print(c, hex(ic), k, hex(ik), hex(inew)) # print every result idx += 1 # Increment idx by 1 print("\n{} --> {}\n".format(plaintext, plaintext.encode("ascii").hex())) return plaintext if __name__ == '__main__': # ciphertext1 = encrypt(key, message1) # plaintext1 = decrypt(key, ciphertext1) # # # ciphertext2 = encrypt(key, message2) # plaintext1 = decrypt(key, ciphertext2) # place the given ciphertext 1 and 2 below # # Insert the hex string below ciphertextHex1 = "" ciphertextHex2 = "" # Convert the hex string to ascii string quote_h = "300d04014" quote = binascii.a2b_hex("%s" % (quote_h.strip())).decode("ASCII").replace(';', '\n- ') print(quote) guess = input("Guess a word: ") crib_drag_attack(guess, ciphertext1, ciphertext2)
问题修复与代码优化
1. 十六进制转ASCII错误修复
- 十六进制字符串必须是偶数长度,原代码中
quote_h = "300d04014"长度为9(奇数),会触发binascii.Error,需调整为偶数位的合法十六进制字符串。 - 必须导入
binascii模块,否则无法使用a2b_hex方法。 - 加密后的密文可能包含非ASCII控制字符,直接用
ascii编码会丢失数据,应改用字节对象处理密文,避免编码错误。
2. 用户输入与攻击逻辑修复
- 原代码中
ciphertext1和ciphertext2未赋值,直接调用crib_drag_attack会报错,需先将十六进制密文转换为字节串。 - 调整
crib_drag_attack函数,支持字节输入而非字符串,避免ord()处理非ASCII字符的异常。
3. 十六进制解密为ASCII的实现
- 先将十六进制字符串转换为字节串,再传入
decrypt函数解密,最后将解密后的字节串转换为ASCII(可过滤不可打印字符)。
修复后的完整代码
import binascii def crib_drag_attack(guess, cp1, cp2): # 处理字节形式的密文 xor_ciphers = bytearray() for b1, b2 in zip(cp1, cp2): xor_ciphers.append(b1 ^ b2) guess_bytes = guess.encode('ascii') for idx in range(len(xor_ciphers) - len(guess_bytes) + 1): slide = xor_ciphers[idx: idx + len(guess_bytes)] results = bytearray() for g, s in zip(guess_bytes, slide): results.append(g ^ s) # 转换为ASCII,替换不可打印字符为. print(results.decode('ascii', errors='replace')) def encrypt(key, plaintext): key_bytes = key.encode('ascii') plaintext_bytes = plaintext.encode('ascii') ciphertext = bytearray() idx = 0 for p in plaintext_bytes: k = key_bytes[idx % len(key_bytes)] # 支持密钥循环复用 ciphertext.append(p ^ k) print(f"{chr(p)} {hex(p)} {chr(k)} {hex(k)} {hex(p^k)}") idx += 1 hexstring = ciphertext.hex() print(f"\n{ciphertext.decode('ascii', errors='replace')} --> {hexstring}\n") # 验证十六进制转换 trial = bytes.fromhex(hexstring) print(f"Trial: {trial.decode('ascii', errors='replace')}") return ciphertext def decrypt(key, ciphertext): key_bytes = key.encode('ascii') plaintext = bytearray() idx = 0 for c in ciphertext: k = key_bytes[idx % len(key_bytes)] plaintext.append(c ^ k) print(f"{chr(c) if c >= 32 else '.'} {hex(c)} {chr(k)} {hex(k)} {hex(c^k)}") idx += 1 plaintext_str = plaintext.decode('ascii', errors='replace') print(f"\n{plaintext_str} --> {plaintext.hex()}\n") return plaintext_str if __name__ == '__main__': # 示例密钥与明文(可替换为实际数据) key = "secretkey" message1 = "Hello, this is message one!" message2 = "Hi there, this is message two!" # 生成密文(实际使用时可直接填入十六进制密文) ciphertext1 = encrypt(key, message1) ciphertext2 = encrypt(key, message2) # 从十六进制密文初始化(如果已有十六进制密文) # ciphertextHex1 = "your_hex_ciphertext_1" # ciphertextHex2 = "your_hex_ciphertext_2" # ciphertext1 = bytes.fromhex(ciphertextHex1) # ciphertext2 = bytes.fromhex(ciphertextHex2) # 测试十六进制转ASCII quote_h = "300d040104" # 修正为偶数长度的十六进制字符串 quote_bytes = binascii.a2b_hex(quote_h.strip()) quote = quote_bytes.decode('ascii', errors='replace').replace(';', '\n- ') print(f"Hex to ASCII test: {quote}") guess = input("Guess a word: ").strip() if guess: crib_drag_attack(guess, ciphertext1, ciphertext2)
关键修改说明
- 改用字节数组
bytearray处理密文,避免字符串编码带来的异常。 - 加密/解密函数支持密钥循环复用(
idx % len(key_bytes)),符合流密码的常见使用场景。 - 处理不可打印字符时用
.替换,提升可读性。 - 新增十六进制密文直接初始化的注释示例,方便实际使用。
内容的提问来源于stack exchange,提问作者Claudio Esteban
相关产品推荐
相关产品推荐

