ROT13 是一種凱薩密碼,對 26 個字母的拉丁字母套用固定的 13 位偏移,而且它是一種本身就是自身反函式的凱薩位移——對任何文字套用 ROT13 兩次,可以逐字還原原始內容。這個轉換會將每個 ASCII 大寫字母 A–Z 剛好旋轉 13 格,因此 A 變成 N,B 變成 O,M 變成 Z,而 N 則循環回 A;小寫 a–z 則獨立遵循相同的模式,並保留小寫形式。由於 26 ÷ 2 = 13,字母表的兩半會完美對調,這正是為什麼同一個單一操作既可以加密也可以解密。此轉換刻意範圍很窄:只會動到 ASCII 的 A 到 Z 以及 a 到 z。數字、標點、空格、換行、附加變音符號的拉丁字母(例如 é)、希臘文、西里爾文、阿拉伯文、CJK 漢字,以及表情符號的代理對,都會逐個程式碼單元原封不動地保留。一個在瀏覽器中運作的 ROT13 編碼解碼器 會在當前的分頁內就地套用此替換,報告它更改了多少個 ASCII 字母,並且永遠不會把輸入上傳到遠端伺服器。
這篇以淺白英語進行的逐步說明,會拆解字母數學、保留規則、自身反函式特性,以及在你把 ROT13 視為比休閒混淆手段更嚴肅的工具之前應該知道的所有限制。

ROT13 替換是如何機械化運作的
經典的 ROT13 字母對應表定義了 26 個固定的交換。Python 標準函式庫在其 rot_13 編解碼器中直接公布了這個表格,而瀏覽器式的 ROT13 解碼器則對每個 ASCII 字母套用完全相同的規則,同時保留每個字元的大小寫。在機制上,每個大寫字母會將其編碼減去 65,加上 13 後取模 26,然後再加回 65;小寫字母則改用基底 97 而非 65。這整個替換就只有這一道運算。
舉例來說,"HELLO" 會旋轉成 "URYYB"。H 是第 8 個大寫字母(從 0 開始索引為 7),加上 13 之後是 20,也就是 U。E 加上 13 是 R。兩個 L 都會變成 Y,而 O 則變成 B。字串中其他任何東西——引號、空格或任何其他字元——都不會被修改,因為 ROT13 只作用於 ASCII 的 A–Z 與 a–z。
官方的 Python codecs documentation 確認了這種嚴格的行為,而 CPython rot_13 source 則提供了任何正確實作都會用來交叉比對的直接字母對應表。
哪些會改變,哪些維持不變
ROT13 只旋轉 ASCII 字母,並保留其他所有程式碼單元,這代表這個轉換可以安全地套用在混合文字上而不會破壞結構。0 到 9 的數字會原封不動地保留。空格、Tab、換行、NUL、標點和符號都會原樣返回。帶附加變音符號的拉丁字母(例如 é、ñ 或 ü)也會被保留,因為它們落在 A–Z 與 a–z 範圍之外——例如,"café" 會變成 "pnsé",因為只有 c、a 和 f 被移位,而 é 則原封不動地通過。
非拉丁文字的處理方式也相同。希臘文、西里爾文、阿拉伯文、希伯來文、天城文以及 CJK 漢字,都會以 UTF-16 程式碼單元的形式保留。表情符號則以其代理對的形式保留。像字母 e 後面接著 U+0301(組合銳音符號)這種組合序列,只會改變其中的 ASCII e,而將組合記號留在原位,產生視覺上看起來像預先組成的正確輸出。
這種嚴格的保留規則與 Python 的 rot_13 編解碼器一致,也避免了假裝 ROT13 為所有書寫系統定義了旋轉。任何聲稱可以「旋轉帶附加音符的 é」或「移位表情符號」的工具,根據定義都已經超出 ROT13 的範疇。
三個步驟套用與還原 ROT13
在瀏覽器式的 ROT13 解碼器上,整個工作流程只需要三個動作:貼上、套用,然後複製或還原。
- 把包含任意 ASCII 字母與其他字元組合的文字貼到輸入欄位。這個工具接受最長 1,000,000 個 UTF-16 程式碼單元的字串,並會在轉換前拒絕空白的輸入。
- 選擇套用 ROT13,並檢視轉換後的輸出以及被更改的 ASCII 字母數量。這個數量也就是值有變動的程式碼單元位置數,因為每個符合條件的 ASCII 字母必定會對應到另一個不同的 ASCII 字母。
- 如果你需要混淆過的文字,就複製結果,或者對該結果再套用一次 ROT13 來還原出完全相同的原始字串。重新執行會在發布新輸出之前,先清除任何先前的結果、驗證錯誤、統計資訊、複製狀態與確認計時器。
為什麼 ROT13 是自身的反函式
自身反函式這個特性是字母表長度直接造成的結果,而不是巧合。每個 ASCII 字母在其大小寫類別中會有一個介於 0 到 25 之間的索引。ROT13 會計算 (index + 13) mod 26。第二次套用同一個轉換時,則會計算 ((index + 13) mod 26 + 13) mod 26,化簡後為 (index + 26) mod 26,等於 index。這個字母會回到它的起始位置,而保留大小寫的實作也保證了大小寫一致。
由於每個被轉換的 ASCII 程式碼單元恰好被另一個 ASCII 程式碼單元取代,並且其他每個程式碼單元都會被保留,因此以 UTF-16 程式碼單元計算時,輸出長度永遠等於輸入長度。這個 1:1 的長度規則,正是「套用兩次就能還原」能對任意混合文字(即使是完全不包含 ASCII 字母的輸入)奏效的原因。
舉例來說,輸入 "ABC123" 會產生 "NOP123"。對 "NOP123" 再套用一次 ROT13,會再次產生 "ABC123"。數字從未移動,而每個字母都透過同一個單一操作完成了來回轉換。
ROT13 與凱薩、ROT47、ROT18 的比較
ROT13 屬於一系列簡單旋轉的家族,而且它是最受限的一員。下表比較了最常見的四種變體,讓你能為自己的文字挑選合適的工具。
| 轉換方式 | 涵蓋的字母範圍 | 偏移量 | 自身反函式? | 典型使用情境 |
|---|---|---|---|---|
| ROT13 | 僅 ASCII A–Z 與 a–z | 固定 13 | 是 | 英文文字與劇透的休閒式混淆 |
| 凱薩(任意) | ASCII A–Z 與 a–z | 可設定 1–25 | 否 | 謎題與可設定的位移 |
| ROT47 | 可列印 ASCII 33–126 | 固定 47 | 是 | 含有符號的網址與程式碼片段 |
| ROT18 | 對字母套用 ROT13,加上對數字套用 ROT5 | 13 + 5 | 是 | 與文字混合的訂單編號、序號與日期 |
如果你需要可設定的 ASCII 位移而非固定的 13,請改用專門的 凱薩密碼解碼器。ROT13 並未實作任意的凱薩位移、ROT5、ROT47 或 Unicode 轉寫;如果硬把它用於這些用途,會默默地保留住那些本來會被更廣泛的轉換所改變的符號。
安全現實:ROT13 做得到與做不到的事
ROT13 是混淆,不是加密。它沒有金鑰,替換表是公開的,任何識得這個旋轉的人只要再套用一次 ROT13 就能立刻還原。它不提供機密性、不提供身分驗證、不提供完整性保護、不提供雜湊,也不提供存取控管。請將任何「以 ROT13 加密的密碼」或「以 ROT13 保護的訊息」之類的說法,視為即將發生的安全失效。
歷史上,ROT13 在早期的 Usenet 上扮演著一個狹隘的社交角色:把劇透、笑點、謎底或粗俗語言遮起來,以免休閒讀者不小心看到。RFC 1855 記錄了這種用法的歷史背景。這種轉換在混合散文中隱藏劇透時確實很方便,因為每個字母看起來仍然像個字母,但它永遠無法保護任何真正需要保密的東西。
若要保護真正的機密,請使用經過稽核的成熟密碼學系統,例如 AES-GCM、RSA-OAEP 或 HMAC,並搭配攻擊者無法取得的金鑰。ROT13 在這個流程中沒有任何角色。對這個工具最誠實的描述就是最安全的說法:可還原、自身反函式、公開,且不構成安全界線。
延伸閱讀:透過 ROT47 編碼解碼器重複產生相同的結果。
延伸閱讀:維吉尼亞密碼解碼器範例:完整逐步解析。