培根密码
培根密码(Baconian Cipher)是由弗朗西斯·培根(Francis Bacon)在1605年发明的一种隐写术加密方法。它将每个字母用5位二进制编码表示,然后通过两种不同的字体、大小写或其他二元区分方式来隐藏信息。
核心特点: - 基于二进制编码思想(A/B 或 0/1) - 每个字母固定使用5位编码 - 属于隐写术范畴,可以隐藏在正常文本中 - CTF中常见的古典密码类型
历史背景¶
发明者¶
- 弗朗西斯·培根(Francis Bacon, 1561-1626)
- 英国哲学家、政治家、科学家
- 现代科学方法的奠基人之一
发明时间¶
- 1605年,首次出现在培根的著作《De Augmentis Scientiarum》中
历史意义¶
- 是最早的二进制编码系统之一
- 为现代计算机二进制编码奠定了理论基础
- 在密码学史上具有重要地位
加密原理¶
培根密码的核心思想是将26个英文字母映射到5位二进制编码,每一位可以用两种状态表示:
二元对立的表示方式¶
- A/B 编码:用字母 A 和 B 表示
- 0/1 编码:用数字 0 和 1 表示
- 大小写:用大写和小写字母区分
- 字体样式:用粗体/正常体、斜体/正常体等区分
- 其他方式:颜色、字号、符号等
编码位数¶
- 固定使用 5位二进制 编码
- 2^5 = 32,足够表示26个字母
编码表¶
标准培根密码编码表(24字母版本)¶
在原始培根密码中,I和J共用一个编码,U和V共用一个编码:
| 字母 | 编码 | 字母 | 编码 | 字母 | 编码 |
|---|---|---|---|---|---|
| A | AAAAA | J/I | ABAAA | S | BAAAB |
| B | AAAAB | K | ABAAB | T | BAABA |
| C | AAABA | L | ABABA | U/V | BAABB |
| D | AAABB | M | ABBAA | W | BABAA |
| E | AABAA | N | ABBAB | X | BABAB |
| F | AABAB | O | ABBBA | Y | BABBA |
| G | AABBA | P | ABBBB | Z | BABBB |
| H | AABBB | Q | BAAAA | ||
| I/J | ABAAA | R | BAAAB |
现代培根密码编码表(26字母完整版本)¶
现代版本为每个字母分配独立编码:
| 字母 | 编码 | 字母 | 编码 | 字母 | 编码 |
|---|---|---|---|---|---|
| A | AAAAA | J | ABAAA | S | BAABA |
| B | AAAAB | K | ABAAB | T | BAABB |
| C | AAABA | L | ABABA | U | BABAA |
| D | AAABB | M | ABBAA | V | BABAB |
| E | AABAA | N | ABBAB | W | BABBA |
| F | AABAB | O | ABBBA | X | BABBB |
| G | AABBA | P | ABBBB | Y | BBAAA |
| H | AABBB | Q | BAAAA | Z | BBAAB |
| I | ABAAA | R | BAAAB |
使用0/1表示的编码表¶
| 字母 | 编码 | 字母 | 编码 | 字母 | 编码 |
|---|---|---|---|---|---|
| A | 00000 | J | 01000 | S | 10010 |
| B | 00001 | K | 01001 | T | 10011 |
| C | 00010 | L | 01010 | U | 10100 |
| D | 00011 | M | 01100 | V | 10101 |
| E | 00100 | N | 01101 | W | 10110 |
| F | 00101 | O | 01110 | X | 10111 |
| G | 00110 | P | 01111 | Y | 11000 |
| H | 00111 | Q | 10000 | Z | 11001 |
| I | 01000 | R | 10001 |
加密过程¶
步骤1:明文转换为培根编码¶
将明文中的每个字母转换为对应的5位培根编码。
示例: 明文 "HELLO"
完整编码:AABBB AABAA ABABA ABABA ABBBA(25位)
步骤2:选择载体文本¶
选择一段至少有25个字母的载体文本(carrier text)。
示例载体: "Bring me the golden apple from the tree"
步骤3:应用二元区分¶
根据培根编码,将载体文本的字母进行区分标记: - A → 小写字母 - B → 大写字母
密文编码:A A B B B A A B A A A B A B A A B A B A A B B B A
载体文本:B r i n g m e t h e g o l d e n a p p l e f r o m
处理结果:b r I N G m e T H e g O l D e n A p P l e F R O m
最终密文¶
或者不分组:brING meTHe gOlDe nApPl eFROm the tree
解密过程¶
步骤1:提取二元信息¶
从密文中提取大小写模式: - 小写字母 → A(或0) - 大写字母 → B(或1)
示例: brING meTHe gOlDe nApPl eFROm
步骤2:分组为5位¶
将提取的二进制序列按5位一组分割:
步骤3:查表解码¶
根据培根编码表将每组转换为对应字母:
最终明文¶
CTF中的常见形式¶
1. 大小写混合文本¶
特征: 看似正常的英文文本,但大小写混乱
示例:
2. 粗体/斜体混合¶
特征: 正常字体和粗体(或斜体)混合
示例:
3. 字体颜色区分¶
特征: 两种不同颜色的字母
示例:
4. 0/1或A/B序列¶
特征: 直接给出二进制序列
示例:
5. 图片隐写¶
特征: 文字以图片形式给出,通过颜色、字体等区分
6. 其他二元对立形式¶
- 全角/半角字符
- 不同符号(如●/○,★/☆)
- 空格的有无
- 特殊Unicode字符
识别特征¶
如何判断是培根密码?¶
1. 文本特征¶
- 大小写混乱但有规律
- 文本长度是5的倍数(或接近)
- 只有26个字母,无其他字符
- 存在明显的二元对立特征
2. 编码特征¶
- 只包含两种元素(如A/B、0/1)
- 总长度能被5整除
- 每5位一组可能对应有意义的字母
3. 题目提示¶
- 题目名称包含"bacon"、"培根"
- 题目描述提到"大小写"、"字体"
- 题目文件为图片,文字有明显样式差异
常见混淆¶
与摩斯电码的区别: - 摩斯:每个字母长度不固定(1-4个符号) - 培根:每个字母固定5位
与二进制编码的区别: - 二进制:通常每字符8位(ASCII) - 培根:每字符固定5位
解密工具与方法¶
在线工具¶
- CyberChef
- URL: https://gchq.github.io/CyberChef/
- 操作:选择 "Bacon Cipher Decode"
-
支持自定义A/B字符
-
dCode
- URL: https://www.dcode.fr/bacon-cipher
- 支持多种变体
-
可自动识别编码方式
-
Rumkin Cipher Tools
- URL: http://rumkin.com/tools/cipher/baconian.php
- 简单易用
Python脚本解密¶
# 标准培根密码编码表(26字母版本)
bacon_dict = {
'AAAAA': 'A', 'AAAAB': 'B', 'AAABA': 'C', 'AAABB': 'D', 'AABAA': 'E',
'AABAB': 'F', 'AABBA': 'G', 'AABBB': 'H', 'ABAAA': 'I', 'ABAAB': 'J',
'ABABA': 'K', 'ABABB': 'L', 'ABBAA': 'M', 'ABBAB': 'N', 'ABBBA': 'O',
'ABBBB': 'P', 'BAAAA': 'Q', 'BAAAB': 'R', 'BAABA': 'S', 'BAABB': 'T',
'BABAA': 'U', 'BABAB': 'V', 'BABBA': 'W', 'BABBB': 'X', 'BBAAA': 'Y',
'BBAAB': 'Z'
}
def bacon_decode(ciphertext, char_a='a', char_b='A'):
"""
解密培根密码
:param ciphertext: 密文
:param char_a: 代表A的字符类型(默认小写)
:param char_b: 代表B的字符类型(默认大写)
:return: 明文
"""
# 提取二进制序列
binary = ''
for char in ciphertext:
if char.isalpha():
if char.islower():
binary += 'A'
else:
binary += 'B'
# 分组解码
plaintext = ''
for i in range(0, len(binary), 5):
group = binary[i:i+5]
if len(group) == 5:
plaintext += bacon_dict.get(group, '?')
return plaintext
# 使用示例
cipher = "brING meTHe gOlDe nApPl eFROm"
plain = bacon_decode(cipher)
print(f"明文: {plain}") # 输出: HELLO
更通用的Python解密脚本¶
def bacon_decode_advanced(text, reverse=False):
"""
高级培根密码解密,支持多种模式
:param text: 输入文本
:param reverse: 是否反转A/B映射
:return: 可能的明文列表
"""
# 标准编码表
bacon_standard = {
'AAAAA': 'A', 'AAAAB': 'B', 'AAABA': 'C', 'AAABB': 'D', 'AABAA': 'E',
'AABAB': 'F', 'AABBA': 'G', 'AABBB': 'H', 'ABAAA': 'I', 'ABAAB': 'J',
'ABABA': 'K', 'ABABB': 'L', 'ABBAA': 'M', 'ABBAB': 'N', 'ABBBA': 'O',
'ABBBB': 'P', 'BAAAA': 'Q', 'BAAAB': 'R', 'BAABA': 'S', 'BAABB': 'T',
'BABAA': 'U', 'BABAB': 'V', 'BABBA': 'W', 'BABBB': 'X', 'BBAAA': 'Y',
'BBAAB': 'Z'
}
# 24字母版本(I/J共用,U/V共用)
bacon_24 = {
'AAAAA': 'A', 'AAAAB': 'B', 'AAABA': 'C', 'AAABB': 'D', 'AABAA': 'E',
'AABAB': 'F', 'AABBA': 'G', 'AABBB': 'H', 'ABAAA': 'I/J', 'ABAAB': 'K',
'ABABA': 'L', 'ABABB': 'M', 'ABBAA': 'N', 'ABBAB': 'O', 'ABBBA': 'P',
'ABBBB': 'Q', 'BAAAA': 'R', 'BAAAB': 'S', 'BAABA': 'T', 'BAABB': 'U/V',
'BABAA': 'W', 'BABAB': 'X', 'BABBA': 'Y', 'BABBB': 'Z'
}
results = []
# 尝试不同的A/B映射方式
mappings = [
('lower', 'upper'), # 小写→A, 大写→B
('upper', 'lower'), # 大写→A, 小写→B
]
for a_type, b_type in mappings:
binary = ''
for char in text:
if char.isalpha():
if (a_type == 'lower' and char.islower()) or \
(a_type == 'upper' and char.isupper()):
binary += 'A'
else:
binary += 'B'
# 使用26字母表解码
plaintext = ''
for i in range(0, len(binary), 5):
group = binary[i:i+5]
if len(group) == 5:
plaintext += bacon_standard.get(group, '?')
if '?' not in plaintext:
results.append(f"映射{a_type}→A: {plaintext}")
return results
# 使用示例
cipher = "brING meTHe gOlDe nApPl eFROm"
results = bacon_decode_advanced(cipher)
for result in results:
print(result)
命令行工具¶
# 使用 Python 单行命令
echo "brING meTHe gOlDe nApPl eFROm" | python3 -c "
import sys
d={'AAAAA':'A','AAAAB':'B','AAABA':'C','AAABB':'D','AABAA':'E','AABAB':'F','AABBA':'G','AABBB':'H','ABAAA':'I','ABAAB':'J','ABABA':'K','ABABB':'L','ABBAA':'M','ABBAB':'N','ABBBA':'O','ABBBB':'P','BAAAA':'Q','BAAAB':'R','BAABA':'S','BAABB':'T','BABAA':'U','BABAB':'V','BABBA':'W','BABBB':'X','BBAAA':'Y','BBAAB':'Z'}
s=''.join('A' if c.islower() else 'B' for c in sys.stdin.read() if c.isalpha())
print(''.join(d.get(s[i:i+5],'?') for i in range(0,len(s),5)))
"
实战例题¶
例题1:基础大小写混合¶
题目:
解题步骤:
- 识别密码类型:大小写混乱 → 培根密码
- 提取大小写模式:
- 分组(5位): 注意:最后一组不足5位,舍去
- 查表解码:
- 得到明文:
LGOSUS(可能需要调整或提示有误)
实际情况: 需要尝试反向映射(大写→A,小写→B)
例题2:0/1序列¶
题目:
解题步骤:
- 识别:长度符合,每组5位 → 培根密码
- 将0→A,1→B转换:
例题3:真实CTF题目示例¶
题目名称: "Bacon's Secret"
题目文件: message.txt
解题过程:
text = "THE qUIck BRowN fox JUMPs OVER the LAZy DOG. THis SENTence CONtains A SEcret MESSage."
# 提取大小写(只保留字母)
binary = ''.join('B' if c.isupper() else 'A' for c in text if c.isalpha())
print(f"二进制序列: {binary}")
# 输出: BBBAABAABBAAABABABAABBBAAABAAAAAABBBAABAABBBBBB...
# 分组
groups = [binary[i:i+5] for i in range(0, len(binary), 5)]
print(f"分组: {groups}")
# 解码
bacon_dict = {...} # 完整编码表
plaintext = ''.join(bacon_dict.get(g, '?') for g in groups)
print(f"明文: {plaintext}")
变种与扩展¶
1. 反向培根密码¶
- 大写字母 → A
- 小写字母 → B
解密时需要注意尝试两种映射方式
2. 多层加密¶
培根密码 + Base64 + ROT13等组合
示例:
3. 自定义编码表¶
某些CTF题目会修改标准编码表,需要根据题目提示或尝试破解。
4. 使用特殊字符¶
- 用●/○代替A/B
- 用不同表情符号
- 用全角/半角字符
示例:
5. 培根栅栏密码组合¶
先培根加密,再栅栏密码加密,增加破解难度。
6. 培根隐写¶
将培根密码隐藏在图片的LSB(最低有效位)中。
Python完整工具脚本¶
#!/usr/bin/env python3
"""
培根密码完整工具集
支持加密、解密、多种变体
"""
class BaconCipher:
# 26字母完整编码表
BACON_26 = {
'A': 'AAAAA', 'B': 'AAAAB', 'C': 'AAABA', 'D': 'AAABB', 'E': 'AABAA',
'F': 'AABAB', 'G': 'AABBA', 'H': 'AABBB', 'I': 'ABAAA', 'J': 'ABAAB',
'K': 'ABABA', 'L': 'ABABB', 'M': 'ABBAA', 'N': 'ABBAB', 'O': 'ABBBA',
'P': 'ABBBB', 'Q': 'BAAAA', 'R': 'BAAAB', 'S': 'BAABA', 'T': 'BAABB',
'U': 'BABAA', 'V': 'BABAB', 'W': 'BABBA', 'X': 'BABBB', 'Y': 'BBAAA',
'Z': 'BBAAB'
}
# 反向字典(解密用)
BACON_26_REV = {v: k for k, v in BACON_26.items()}
@staticmethod
def encode(plaintext, carrier="", use_case=True):
"""
加密
:param plaintext: 明文
:param carrier: 载体文本(可选)
:param use_case: 是否使用大小写区分(True=大小写,False=A/B)
:return: 密文
"""
plaintext = plaintext.upper().replace(' ', '')
bacon_code = ''.join(BaconCipher.BACON_26.get(c, '') for c in plaintext)
if not use_case:
return bacon_code
if not carrier:
# 生成随机载体
import random
import string
carrier = ''.join(random.choice(string.ascii_lowercase)
for _ in range(len(bacon_code)))
# 应用大小写
result = []
carrier_alpha = [c for c in carrier if c.isalpha()]
for i, bit in enumerate(bacon_code):
if i < len(carrier_alpha):
char = carrier_alpha[i]
result.append(char.upper() if bit == 'B' else char.lower())
return ''.join(result)
@staticmethod
def decode(ciphertext, reverse=False):
"""
解密
:param ciphertext: 密文
:param reverse: 是否反向映射(大写→A)
:return: 明文
"""
# 提取二进制
binary = ''
for char in ciphertext:
if char.isalpha():
if reverse:
binary += 'A' if char.isupper() else 'B'
else:
binary += 'A' if char.islower() else 'B'
elif char in 'AB':
binary += char
elif char in '01':
binary += 'A' if char == '0' else 'B'
# 解码
plaintext = ''
for i in range(0, len(binary), 5):
group = binary[i:i+5]
if len(group) == 5:
plaintext += BaconCipher.BACON_26_REV.get(group, '?')
return plaintext
@staticmethod
def auto_decode(ciphertext):
"""
自动尝试多种解密方式
:param ciphertext: 密文
:return: 可能的明文列表
"""
results = []
# 尝试正向和反向
for reverse in [False, True]:
plaintext = BaconCipher.decode(ciphertext, reverse)
if '?' not in plaintext:
mode = "大写→B" if not reverse else "大写→A"
results.append((mode, plaintext))
return results
# 使用示例
if __name__ == "__main__":
# 测试加密
plain = "HELLO"
cipher = BaconCipher.encode(plain, carrier="the quick brown fox jumps")
print(f"明文: {plain}")
print(f"密文: {cipher}")
# 测试解密
decoded = BaconCipher.decode(cipher)
print(f"解密: {decoded}")
# 自动解密
test_cipher = "brING meTHe gOlDe nApPl eFROm"
results = BaconCipher.auto_decode(test_cipher)
print(f"\n自动解密结果:")
for mode, text in results:
print(f" {mode}: {text}")