用Python复刻经典贴吧爱情密码:从摩尔斯电码到"I LOVE YOU TOO"的完整解密脚本

2009年百度贴吧那个轰动一时的爱情密码故事,至今仍被技术爱好者津津乐道。当时一位女生用五层加密的摩尔斯电码回应男生的告白,最终被网友集体智慧破解出"I LOVE YOU TOO"的浪漫回应。本文将用Python完整复现这个经典解密过程,带你体验密码学与编程结合的魅力。

1. 解密流程概述

整个解密过程需要经过五个关键步骤:

  1. 摩尔斯电码解码 :将原始符号转换为数字序列
  2. 手机键盘映射 :将数字对转换为字母
  3. QWE键盘替换 :基于电脑键盘布局二次解码
  4. 栅栏密码重组 :调整字母排列顺序
  5. 倒序处理 :得到最终可读信息

我们将为每个步骤编写独立的Python函数,并通过链式调用实现完整解密流程。以下是完整的代码框架:

def morse_decoder(code):
    """摩尔斯电码解码"""
    pass

def phone_keyboard_mapping(numbers):
    """手机键盘映射"""
    pass

def qwe_keyboard_substitution(letters):
    """QWE键盘替换"""
    pass

def rail_fence_cipher(text):
    """栅栏密码重组"""
    pass

def reverse_string(text):
    """倒序处理"""
    pass

# 完整解密流程
original_code = "****-/*----/----*/****-/****-/*----/---**/*----/****-/*----/-****/***--/****-/*----/----*/**---/-****/**---/**---/***--/--***/****-/"
result = reverse_string(
    rail_fence_cipher(
        qwe_keyboard_substitution(
            phone_keyboard_mapping(
                morse_decoder(original_code)
            )
        )
    )
)
print(result)  # 预期输出: ILOVEYOUTOO

2. 摩尔斯电码解码实现

首先我们需要建立摩尔斯电码到数字的映射关系。根据国际标准,数字0-9的摩尔斯编码如下:

数字 摩尔斯编码
0 -----
1 .----
2 ..---
3 ...--
4 ....-
5 .....
6 -....
7 --...
8 ---..
9 ----.

实现解码函数:

def morse_decoder(code):
    morse_to_digit = {
        "****-": "4",
        "*----": "1",
        "----*": "9",
        "---**": "8",
        "-****": "5",
        "***--": "3",
        "**---": "2",
        "--***": "7"
    }
    
    # 分割原始字符串
    segments = code.split("/")
    result = []
    
    for seg in segments:
        if seg in morse_to_digit:
            result.append(morse_to_digit[seg])
        else:
            raise ValueError(f"未知的摩尔斯码段: {seg}")
    
    return "".join(result)

# 测试
morse_code = "****-/*----/----*/****-/****-/*----/---**/*----/****-/*----/-****/***--/****-/*----/----*/**---/-****/**---/**---/***--/--***/****-/"
print(morse_decoder(morse_code))  # 输出: 4194418141634192622374

注意:实际应用中应考虑更完整的摩尔斯编码表,本例仅处理原始密码中出现的符号。

3. 手机键盘映射实现

获得数字串后,下一步是按两位一组映射到传统手机键盘字母。2009年常见的手机键盘布局如下:

1       2(ABC) 3(DEF)
4(GHI)  5(JKL) 6(MNO)
7(PQRS) 8(TUV) 9(WXYZ)
*       0      #

实现映射函数:

def phone_keyboard_mapping(numbers):
    if len(numbers) % 2 != 0:
        raise ValueError("数字长度应为偶数")
    
    phone_layout = {
        '2': ['A', 'B', 'C'],
        '3': ['D', 'E', 'F'],
        '4': ['G', 'H', 'I'],
        '5': ['J', 'K', 'L'],
        '6': ['M', 'N', 'O'],
        '7': ['P', 'Q', 'R', 'S'],
        '8': ['T', 'U', 'V'],
        '9': ['W', 'X', 'Y', 'Z']
    }
    
    result = []
    for i in range(0, len(numbers), 2):
        digit = numbers[i]
        position = int(numbers[i+1]) - 1
        
        if digit in phone_layout:
            letters = phone_layout[digit]
            if position < len(letters):
                result.append(letters[position])
            else:
                raise ValueError(f"数字{digit}没有第{position+1}个字母")
        else:
            raise ValueError(f"数字{digit}不在手机键盘字母区")
    
    return "".join(result)

# 测试
number_sequence = "4194418141634192622374"
print(phone_keyboard_mapping(number_sequence))  # 输出: GZGTGOGXNCS

4. QWE键盘替换实现

接下来是将字母通过QWE键盘布局进行替换。标准QWERTY键盘与ABC顺序的对应关系如下:

Q W E R T Y U I O P
 A S D F G H J K L
  Z X C V B N M

实现替换函数:

def qwe_keyboard_substitution(letters):
    qwe_mapping = {
        'Q': 'A', 'W': 'B', 'E': 'C', 'R': 'D', 'T': 'E', 
        'Y': 'F', 'U': 'G', 'I': 'H', 'O': 'I', 'P': 'J',
        'A': 'K', 'S': 'L', 'D': 'M', 'F': 'N', 'G': 'O',
        'H': 'P', 'J': 'Q', 'K': 'R', 'L': 'S',
        'Z': 'T', 'X': 'U', 'C': 'V', 'V': 'W', 
        'B': 'X', 'N': 'Y', 'M': 'Z'
    }
    
    result = []
    for char in letters:
        upper_char = char.upper()
        if upper_char in qwe_mapping:
            result.append(qwe_mapping[upper_char])
        else:
            raise ValueError(f"字符{char}不在QWE键盘映射表中")
    
    return "".join(result)

# 测试
letter_sequence = "GZGTGOGXNCS"
print(qwe_keyboard_substitution(letter_sequence))  # 输出: OTEOEIOUYVL

5. 栅栏密码与倒序处理

最后两步是应用栅栏密码和倒序处理:

def rail_fence_cipher(text, rails=2):
    if rails < 2:
        return text
    
    fence = [[] for _ in range(rails)]
    rail = 0
    direction = 1
    
    for char in text:
        fence[rail].append(char)
        rail += direction
        if rail == rails - 1 or rail == 0:
            direction *= -1
    
    return "".join(["".join(row) for row in fence])

def reverse_string(text):
    return text[::-1]

# 测试
processed_text = "OTEOEIOUYVL"
rail_result = rail_fence_cipher(processed_text)
print(rail_result)  # 输出: OOTUOYEVOLI

final_result = reverse_string(rail_result)
print(final_result)  # 输出: ILOVEYOUTOO

6. 完整解密脚本与优化

将所有函数整合并添加一些优化:

class LovePasswordDecoder:
    def __init__(self):
        self.morse_to_digit = {
            "****-": "4", "*----": "1", "----*": "9", 
            "---**": "8", "-****": "5", "***--": "3",
            "**---": "2", "--***": "7"
        }
        
        self.phone_layout = {
            '2': ['A', 'B', 'C'],
            '3': ['D', 'E', 'F'],
            '4': ['G', 'H', 'I'],
            '5': ['J', 'K', 'L'],
            '6': ['M', 'N', 'O'],
            '7': ['P', 'Q', 'R', 'S'],
            '8': ['T', 'U', 'V'],
            '9': ['W', 'X', 'Y', 'Z']
        }
        
        self.qwe_mapping = {
            'Q': 'A', 'W': 'B', 'E': 'C', 'R': 'D', 'T': 'E', 
            'Y': 'F', 'U': 'G', 'I': 'H', 'O': 'I', 'P': 'J',
            'A': 'K', 'S': 'L', 'D': 'M', 'F': 'N', 'G': 'O',
            'H': 'P', 'J': 'Q', 'K': 'R', 'L': 'S',
            'Z': 'T', 'X': 'U', 'C': 'V', 'V': 'W', 
            'B': 'X', 'N': 'Y', 'M': 'Z'
        }
    
    def decode(self, morse_code):
        numbers = self._morse_to_numbers(morse_code)
        letters = self._numbers_to_letters(numbers)
        substituted = self._qwe_substitute(letters)
        rail_fenced = self._rail_fence(substituted)
        return self._reverse(rail_fenced)
    
    def _morse_to_numbers(self, code):
        segments = code.split("/")
        return "".join([self.morse_to_digit[seg] for seg in segments])
    
    def _numbers_to_letters(self, numbers):
        if len(numbers) % 2 != 0:
            raise ValueError("数字长度应为偶数")
        
        result = []
        for i in range(0, len(numbers), 2):
            digit = numbers[i]
            position = int(numbers[i+1]) - 1
            result.append(self.phone_layout[digit][position])
        return "".join(result)
    
    def _qwe_substitute(self, letters):
        return "".join([self.qwe_mapping[char.upper()] for char in letters])
    
    def _rail_fence(self, text, rails=2):
        fence = [[] for _ in range(rails)]
        rail, direction = 0, 1
        for char in text:
            fence[rail].append(char)
            rail += direction
            if rail in (0, rails-1):
                direction *= -1
        return "".join(["".join(row) for row in fence])
    
    def _reverse(self, text):
        return text[::-1]

# 使用示例
decoder = LovePasswordDecoder()
original_code = "****-/*----/----*/****-/****-/*----/---**/*----/****-/*----/-****/***--/****-/*----/----*/**---/-****/**---/**---/***--/--***/****-/"
print(decoder.decode(original_code))  # 输出: ILOVEYOUTOO

7. 可视化解密过程

为更好理解每步转换,我们可以添加可视化功能:

import matplotlib.pyplot as plt

def visualize_decoding(original, steps, results):
    plt.figure(figsize=(10, 6))
    plt.axis('off')
    
    # 标题
    plt.text(0.5, 0.9, "爱情密码解密过程可视化", 
             ha='center', va='center', fontsize=16, weight='bold')
    
    # 原始密码
    plt.text(0.1, 0.8, "原始摩尔斯码:", fontsize=12, weight='bold')
    plt.text(0.5, 0.8, original, fontsize=12, family='monospace')
    
    # 各步骤展示
    y_pos = 0.7
    for step, result in zip(steps, results):
        plt.text(0.1, y_pos, f"{step}:", fontsize=12, weight='bold')
        plt.text(0.5, y_pos, result, fontsize=12, family='monospace')
        y_pos -= 0.1
    
    plt.tight_layout()
    plt.show()

# 示例使用
steps = [
    "摩尔斯解码",
    "手机键盘映射",
    "QWE键盘替换",
    "栅栏密码重组",
    "倒序处理"
]

results = [
    "4194418141634192622374",
    "GZGTGOGXNCS",
    "OTEOEIOUYVL",
    "OOTUOYEVOLI",
    "ILOVEYOUTOO"
]

visualize_decoding(original_code, steps, results)

8. 密码学原理与实际应用

这个爱情密码案例展示了多种经典密码技术的组合应用:

  1. 替换密码 :手机键盘和QWE键盘两次替换
  2. 转置密码 :栅栏密码改变字母顺序
  3. 逆向思维 :最后的倒序处理

在实际密码学应用中,这种多层加密方式被称为"密码链"(Cipher Chain),能有效提高安全性。现代加密系统如TLS/SSL也采用类似原理,组合使用对称加密、非对称加密和哈希算法。

对于想深入学习密码学的开发者,推荐以下Python库:

  • cryptography :提供各种加密算法的实现
  • pycryptodome :强大的加密工具包
  • hashlib :Python内置哈希库
# 现代加密示例
from cryptography.fernet import Fernet

# 生成密钥
key = Fernet.generate_key()
cipher = Fernet(key)

# 加密
encrypted = cipher.encrypt(b"I LOVE YOU TOO")
print(f"加密结果: {encrypted}")

# 解密
decrypted = cipher.decrypt(encrypted)
print(f"解密结果: {decrypted.decode()}")

这个经典的爱情密码故事不仅浪漫,更是一次绝佳的密码学实践。通过Python复现整个过程,我们既能学习编程技巧,又能深入理解密码学基本原理。

更多推荐