ROT13/ROT47
经典字母移位
字母对照表(ROT13)
密文:n o p q r s t u v w x y z | a b c d e f g h i j k l m
说明
· ROT13:Usenet / 邮件列表传统隐藏剧透;自反 → 加密 = 解密
· ROT47:在 ROT13 基础上覆盖标点 / 数字 / 大小写,所有可打印 ASCII 都被替换
· 非加密用途:仅作"轻度混淆"(信息隐藏 / 防误读);任何密码学场景必须用 AES/ChaCha20
· 攻击难度:肉眼可破,仅 26 种偏移(凯撒密码) · 词频分析或 brute force 1 秒解出
关于本工具
了解工具定位 · 使用场景 · 对比优势
使用场景
论坛帖子加密
在公开论坛发布含剧透、敏感词或未公开信息的帖子时,发帖人先用本工具将正文转为 ROT13 密文,并提示读者“手动解码”。读者复制密文到工具中一键还原,无需注册或下载软件。既避免被搜索引擎直接索引敏感内容,又保留了社区自解码的传统玩法。
代码片段混淆
开发者在技术问答社区(如 Stack Overflow)贴出包含 API 密钥、内部路径或待修复漏洞的代码片段时,用 ROT13 对敏感字符串进行快速混淆。读者复制后即时解码,而爬虫或自动扫描工具无法直接提取明文。工具纯前端运行,代码不会上传服务器,适合对隐私敏感的发布场景。
谜题线索隐藏
密室逃脱设计师或 ARG 游戏策划在谜题卡、线索纸条上书写 ROT13 密文,玩家拿到后使用本工具逐段解码,逐步拼出完整提示。ROT47 还可用于加密含数字、符号的坐标或密码,适合需要多层解密链的线下谜题设计。
文本防误删标记
运维人员在服务器配置文件或日志注释中写入 ROT13 编码的“删除前请确认”提示,防止他人误删关键行。解码后看到的警告文本与普通注释区分开,降低被忽略的概率。工具离线可用,适合没有图形界面的纯命令行环境快速验证。
邮件签名彩蛋
技术博主或极客在邮件签名末尾附上一段 ROT13 编码的短句,收件人如果好奇,复制到本工具解码后会发现一句隐藏的格言或彩蛋。这种方式不增加邮件正文长度,只对主动探索者开放,适合体现个人风格又不干扰正常沟通的场景。
对比矩阵本工具 vs 竞品 vs 传统方法
| 维度 | 本工具 (rot.tl654.com) | 竞品 A (ROT13.com) | 传统方法 (手动替换) |
|---|---|---|---|
| 数据隐私 | 纯浏览器处理,文本不上传服务器 | 部分同类工具上传到服务器处理 | 完全本地,但需人工操作 |
| 处理速度 | 即时(毫秒级) | 取决于网络延迟(秒级) | 取决于文本长度(分钟级) |
| 离线可用 | 完全离线(纯前端实现) | 需要网络连接 | 完全离线 |
| 字符集支持 | ROT13(仅字母)+ ROT47(可打印 ASCII) | 通常仅支持 ROT13 | 取决于操作者知识 |
| 批量处理 | 支持任意长度文本 | 通常有长度限制 | 无限制但效率低 |
| 使用门槛 | 零门槛,打开即用 | 需要打开网页 | 需要理解移位规则并手动计算 |
使用指南
上手步骤 · 输入输出 · 避坑提示
输入输出示例6 个典型场景,覆盖常规、边界与易错
| 输入 | 输出 | 说明 |
|---|---|---|
| Hello, World! | Uryyb, Jbeyq! | 典型场景:英文短语 ROT13 加密 |
| Uryyb, Jbeyq! | Hello, World! | 典型场景:ROT13 可逆,再次加密即解密 |
| abc123xyz | nop123klm | 边界 case:数字保持原样,仅字母移位 |
| Hello, 世界! | Uryyb, 世界! | 边界 case:非英文字符(中文)不受影响 |
| a | n | 边界 case:单字符输入,验证移位正确性 |
| Hello, World! | w½==@\E@C=5 | 易错 case:ROT47 对同一输入输出不同,避免混淆 |
常见错误对照7 个常踩的坑 · 错误 → 修复
1. 混淆 ROT13 与 ROT47 的字符范围
对中文或特殊符号(如 `@`、`#`)使用 ROT13 加密后得到原样输出ROT13 只处理 A-Za-z 共 52 个字母;ROT47 处理 ASCII 33-126 共 94 个可打印字符。需要加密标点/数字时使用 ROT47ROT13 是 ROT5 和 ROT13 的复合,仅作用于字母;ROT47 是完整的 94 字符循环移位,覆盖数字和符号。选错模式会导致部分字符不变,破坏密文一致性
2. 误以为 ROT13 是安全的加密算法
用 ROT13 加密密码或敏感信息后存储到数据库ROT13 仅用于文本混淆(如隐藏剧透、绕过简单过滤),不应替代 AES / bcrypt 等密码学算法ROT13 是凯撒密码的变体(偏移 13),密钥空间仅 1,可被暴力破解或频率分析秒破。任何需要保密的数据都不应使用
3. 对非 ASCII 文本使用 ROT47 后得到乱码
输入中文「你好」→ ROT47 输出「?O?」或空白ROT47 只处理 ASCII 33-126 范围内的字符,中文/日文/Emoji 等 Unicode 字符会原样保留或显示为不可读符号ROT47 的移位算法基于 ASCII 码表,Unicode 码点超出范围时不会参与循环。如需处理多语言文本,应先转换为纯 ASCII 表示(如 URL 编码)
4. 混淆 ROT13 与 ROT5 或 ROT18
对数字「123」使用 ROT13 得到「123」(不变),期望得到「678」数字专用移位应使用 ROT5(0-9 循环移位 5);字母+数字组合使用 ROT18(ROT13 + ROT5)ROT13 不处理数字,ROT5 只处理数字,ROT18 同时处理字母和数字。本工具仅提供 ROT13 和 ROT47,不包含 ROT5/ROT18,需要数字移位请选择 ROT47
5. 连续加密两次后认为结果错误
输入「HELLO」→ ROT13 →「URYYB」→ 再次 ROT13 →「HELLO」,认为第二次结果应该是「URYYB」ROT13 在 26 个字母上偏移 13,两次应用等于偏移 26 即还原。这是 ROT13 的对称特性,不是 bug因为 13+13=26,正好是一轮字母表长度。ROT47 同理,47+47=94,两次加密也还原。这种自逆特性常用于简单混淆
6. 把 ROT47 结果直接用于 URL 参数
ROT47 加密后得到包含 `?`、`&`、`=` 的字符串,直接拼入 URL query string对 ROT47 输出做 URL 编码(encodeURIComponent),或使用 Base64 代替 ROT47 作为 URL 安全编码ROT47 输出包含大量 URL 保留字符(? & = # %),直接拼接会破坏 URL 结构,导致参数解析错误或路径截断
7. 误以为 ROT13 和 ROT47 能处理换行符
输入多行文本(含 `\n`),ROT13 输出中换行符被删除或变成空格换行符(ASCII 10)不在 ROT13 或 ROT47 的处理范围内,会原样保留。如果发现换行丢失,检查输入是否被前端 trim() 或后端过滤ROT13 和 ROT47 只修改指定范围内的字符,控制字符(如 \n、\r、\t)保持不变。换行丢失通常是输入处理环节的问题,不是算法本身
工作原理
公式推导 · 流程图解 · 依据出处
核心公式
c = (p + k) mod n
变量说明
c— 移位后的字符编码值p— 原始字符的 ASCII 编码值k— 移位量(ROT13=13,ROT47=47)n— 字符集大小(ROT13=26,ROT47=94)
示例
将字母 'A'(ASCII 65)进行 ROT13 移位:p=65,k=13,n=26。c = (65 - 65 + 13) mod 26 + 65 = 13 + 65 = 78,对应 'N'。原 'A' 变为 'N'。
适用范围
仅适用于 ASCII 可打印字符(32-126)。ROT13 只处理 A-Z/a-z,ROT47 处理全部 94 个可打印字符。非 ASCII 字符(如中文、表情符号)不参与移位,保持原样。
原理图
开发者集成
3 种主流语言 · 复制即用
import string
def rot13(text: str) -> str:
"""ROT13:仅移位 A-Z a-z,其他字符不变"""
trans = str.maketrans(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
)
return text.translate(trans)
def rot47(text: str) -> str:
"""ROT47:移位 ASCII 33-126,其他字符不变"""
result = []
for ch in text:
code = ord(ch)
if 33 <= code <= 126:
result.append(chr(33 + (code - 33 + 47) % 94))
else:
result.append(ch)
return "".join(result)
# 示例
print(rot13("Hello, World!")) # Uryyb, Jbeyq!
print(rot47("Hello, World!")) # w6==@[ (@C=5Ppackage main
import (
"fmt"
"strings"
"unicode"
)
func rot13(s string) string {
return strings.Map(func(r rune) rune {
switch {
case 'a' <= r && r <= 'z':
return 'a' + (r-'a'+13)%26
case 'A' <= r && r <= 'Z':
return 'A' + (r-'A'+13)%26
default:
return r
}
}, s)
}
func rot47(s string) string {
return strings.Map(func(r rune) rune {
if r >= 33 && r <= 126 {
return 33 + (r-33+47)%94
}
return r
}, s)
}
func main() {
fmt.Println(rot13("Hello, World!")) // Uryyb, Jbeyq!
fmt.Println(rot47("Hello, World!")) // w6==@[ (@C=5P
}function rot13(text) {
return text.replace(/[a-zA-Z]/g, (ch) => {
const base = ch <= 'Z' ? 65 : 97;
return String.fromCharCode(base + ((ch.charCodeAt(0) - base + 13) % 26));
});
}
function rot47(text) {
return text.replace(/[!-~]/g, (ch) => {
const code = ch.charCodeAt(0);
return String.fromCharCode(33 + ((code - 33 + 47) % 94));
});
}
// 示例
console.log(rot13('Hello, World!')); // Uryyb, Jbeyq!
console.log(rot47('Hello, World!')); // w6==@[ (@C=5P常见问题
8 个高频疑问