[{"data":1,"prerenderedAt":658},["ShallowReactive",2],{"navigation_docs":3,"-ciphers-xor":232,"-ciphers-xor-surround":655},[4,36],{"title":5,"path":6,"stem":7,"children":8,"icon":35},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19,23,27,31],{"title":10,"path":6,"stem":7},"Getting Started",{"title":12,"path":13,"stem":14},"Encode and decode","\u002Fguide\u002Ftransform","1.guide\u002F02.transform",{"title":16,"path":17,"stem":18},"Analysis","\u002Fguide\u002Fanalysis","1.guide\u002F03.analysis",{"title":20,"path":21,"stem":22},"CLI","\u002Fguide\u002Fcli","1.guide\u002F04.cli",{"title":24,"path":25,"stem":26},"Agents","\u002Fguide\u002Fagents","1.guide\u002F05.agents",{"title":28,"path":29,"stem":30},"Custom ciphers","\u002Fguide\u002Fcustom","1.guide\u002F06.custom",{"title":32,"path":33,"stem":34},"Playground","\u002Fguide\u002Fplayground","1.guide\u002F07.playground","i-lucide-book-open",{"title":37,"path":38,"stem":39,"children":40,"icon":231},"Ciphers","\u002Fciphers","2.ciphers\u002F00.index",[41,43,47,51,55,59,63,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227],{"title":42,"path":38,"stem":39},"Overview",{"title":44,"path":45,"stem":46},"Classical","\u002Fciphers\u002Fclassical","2.ciphers\u002F01.classical",{"title":48,"path":49,"stem":50},"Caesar","\u002Fciphers\u002Fcaesar","2.ciphers\u002F02.caesar",{"title":52,"path":53,"stem":54},"ROT-13","\u002Fciphers\u002Frot13","2.ciphers\u002F03.rot13",{"title":56,"path":57,"stem":58},"ROT-47","\u002Fciphers\u002Frot47","2.ciphers\u002F04.rot47",{"title":60,"path":61,"stem":62},"Atbash","\u002Fciphers\u002Fatbash","2.ciphers\u002F05.atbash",{"title":64,"path":65,"stem":66},"Affine","\u002Fciphers\u002Faffine","2.ciphers\u002F06.affine",{"title":68,"path":69,"stem":70},"Vigenère","\u002Fciphers\u002Fvigenere","2.ciphers\u002F07.vigenere",{"title":72,"path":73,"stem":74},"Beaufort","\u002Fciphers\u002Fbeaufort","2.ciphers\u002F08.beaufort",{"title":76,"path":77,"stem":78},"Autokey","\u002Fciphers\u002Fautokey","2.ciphers\u002F09.autokey",{"title":80,"path":81,"stem":82},"Trithemius","\u002Fciphers\u002Ftrithemius","2.ciphers\u002F10.trithemius",{"title":84,"path":85,"stem":86},"Alberti","\u002Fciphers\u002Falberti","2.ciphers\u002F11.alberti",{"title":88,"path":89,"stem":90},"Playfair","\u002Fciphers\u002Fplayfair","2.ciphers\u002F12.playfair",{"title":92,"path":93,"stem":94},"Polybius square","\u002Fciphers\u002Fpolybius","2.ciphers\u002F13.polybius",{"title":96,"path":97,"stem":98},"Morse code","\u002Fciphers\u002Fmorse","2.ciphers\u002F14.morse",{"title":100,"path":101,"stem":102},"Bacon's cipher","\u002Fciphers\u002Fbacon","2.ciphers\u002F15.bacon",{"title":104,"path":105,"stem":106},"Tap code","\u002Fciphers\u002Ftap-code","2.ciphers\u002F16.tap-code",{"title":108,"path":109,"stem":110},"ADFGVX","\u002Fciphers\u002Fadfgvx","2.ciphers\u002F17.adfgvx",{"title":112,"path":113,"stem":114},"Bifid","\u002Fciphers\u002Fbifid","2.ciphers\u002F18.bifid",{"title":116,"path":117,"stem":118},"Rail fence","\u002Fciphers\u002Frail-fence","2.ciphers\u002F19.rail-fence",{"title":120,"path":121,"stem":122},"Columnar transposition","\u002Fciphers\u002Fcolumnar","2.ciphers\u002F20.columnar",{"title":124,"path":125,"stem":126},"Enigma M3","\u002Fciphers\u002Fenigma","2.ciphers\u002F21.enigma",{"title":128,"path":129,"stem":130},"Block","\u002Fciphers\u002Fblock","2.ciphers\u002F22.block",{"title":132,"path":133,"stem":134},"AES (ECB)","\u002Fciphers\u002Faes","2.ciphers\u002F23.aes",{"title":136,"path":137,"stem":138},"AES (CBC)","\u002Fciphers\u002Faes-cbc","2.ciphers\u002F24.aes-cbc",{"title":140,"path":141,"stem":142},"AES (CFB)","\u002Fciphers\u002Faes-cfb","2.ciphers\u002F25.aes-cfb",{"title":144,"path":145,"stem":146},"AES (OFB)","\u002Fciphers\u002Faes-ofb","2.ciphers\u002F26.aes-ofb",{"title":148,"path":149,"stem":150},"AES (CTR)","\u002Fciphers\u002Faes-ctr","2.ciphers\u002F27.aes-ctr",{"title":152,"path":153,"stem":154},"AES (CCM)","\u002Fciphers\u002Faes-ccm","2.ciphers\u002F28.aes-ccm",{"title":156,"path":157,"stem":158},"AES (OCB)","\u002Fciphers\u002Faes-ocb","2.ciphers\u002F29.aes-ocb",{"title":160,"path":161,"stem":162},"AES (LRW)","\u002Fciphers\u002Faes-lrw","2.ciphers\u002F30.aes-lrw",{"title":164,"path":165,"stem":166},"AES (XTS)","\u002Fciphers\u002Faes-xts","2.ciphers\u002F31.aes-xts",{"title":168,"path":169,"stem":170},"AES (CBC-MAC)","\u002Fciphers\u002Faes-cbc-mac","2.ciphers\u002F32.aes-cbc-mac",{"title":172,"path":173,"stem":174},"AES (passphrase)","\u002Fciphers\u002Faes-passphrase","2.ciphers\u002F33.aes-passphrase",{"title":176,"path":177,"stem":178},"Rijndael (ECB)","\u002Fciphers\u002Frijndael","2.ciphers\u002F34.rijndael",{"title":180,"path":181,"stem":182},"DES (ECB)","\u002Fciphers\u002Fdes","2.ciphers\u002F35.des",{"title":184,"path":185,"stem":186},"DESX (ECB)","\u002Fciphers\u002Fdesx","2.ciphers\u002F36.desx",{"title":188,"path":189,"stem":190},"Triple DES (ECB)","\u002Fciphers\u002Ftriple-des","2.ciphers\u002F37.triple-des",{"title":192,"path":193,"stem":194},"Triple DES (CBC)","\u002Fciphers\u002Ftriple-des-cbc","2.ciphers\u002F38.triple-des-cbc",{"title":196,"path":197,"stem":198},"Blowfish (ECB)","\u002Fciphers\u002Fblowfish","2.ciphers\u002F39.blowfish",{"title":200,"path":201,"stem":202},"IDEA (ECB)","\u002Fciphers\u002Fidea","2.ciphers\u002F40.idea",{"title":204,"path":205,"stem":206},"Lucifer (ECB)","\u002Fciphers\u002Flucifer","2.ciphers\u002F41.lucifer",{"title":208,"path":209,"stem":210},"MARS (ECB)","\u002Fciphers\u002Fmars","2.ciphers\u002F42.mars",{"title":212,"path":213,"stem":214},"Serpent (ECB)","\u002Fciphers\u002Fserpent","2.ciphers\u002F43.serpent",{"title":216,"path":217,"stem":218},"Stream","\u002Fciphers\u002Fstream","2.ciphers\u002F44.stream",{"title":220,"path":221,"stem":222},"Rabbit","\u002Fciphers\u002Frabbit","2.ciphers\u002F45.rabbit",{"title":224,"path":225,"stem":226},"RC4","\u002Fciphers\u002Frc4","2.ciphers\u002F46.rc4",{"title":228,"path":229,"stem":230},"XOR","\u002Fciphers\u002Fxor","2.ciphers\u002F47.xor","i-lucide-library",{"id":233,"title":228,"body":234,"description":648,"extension":649,"links":650,"meta":651,"navigation":652,"path":229,"seo":653,"stem":230,"__hash__":654},"docs\u002F2.ciphers\u002F47.xor.md",{"type":235,"value":236,"toc":641},"minimark",[237,241,245,248,253,261,272,386,405,409,412,422,429,463,470,474,481,514,519,522,565,576,580,594,598,634,637],[238,239],"cipher-facts",{"name":240},"xor",[242,243,244],"p",{},"The smallest cipher in the package. Take the key bytes, repeat them under the text, XOR each pair. Done. Decrypting is the same XOR again, because XOR undoes itself.",[242,246,247],{},"It's older than computers, too. Gilbert Vernam built it into AT&T teleprinters in 1917 and patented it in 1919, US 1,310,719. The key sat on punched tape, and the machine XORed its pulses into the Baudot code of the message. Make that key random, as long as the message, and use it once? That's the one-time pad. Repeat a short key instead and you get this page.",[249,250,252],"h2",{"id":251},"vigenère-but-bytes","Vigenère, but bytes",[242,254,255,256,260],{},"Vigenère adds a repeating keyword to letters, mod 26. This adds a repeating key to bytes, mod 2 per bit. Same idea, same weakness. That's why its family here is ",[257,258,259],"code",{},"polyalphabetic",", next to Vigenère and Beaufort, even though it lives with the stream ciphers.",[242,262,263,264,267,268,271],{},"Cryptopals set 1, challenge 5, is the classic vector. Key ",[257,265,266],{},"ICE",", as hex ",[257,269,270],{},"494345",":",[273,274,279],"pre",{"className":275,"code":276,"language":277,"meta":278,"style":278},"language-ts shiki shiki-themes ciphers ciphers ciphers","const xor = create(\"xor\");\nconst key = \"494345\";\nconst text = \"Burning 'em, if you ain't quick and nimble\\nI go crazy when I hear a cymbal\";\nconst ciphertext = xor.encode(text, { key }).text; \u002F\u002F \"0b3637272a2b2e63622c2e69692a2369...\"\nxor.decode(ciphertext, { key }).text === text; \u002F\u002F true\n","ts","",[257,280,281,311,327,342,365],{"__ignoreMap":278},[282,283,286,290,294,297,301,304,308],"span",{"class":284,"line":285},"line",1,[282,287,289],{"class":288},"skH_V","const",[282,291,293],{"class":292},"s38Sx"," xor ",[282,295,296],{"class":288},"=",[282,298,300],{"class":299},"sK71F"," create",[282,302,303],{"class":292},"(",[282,305,307],{"class":306},"shU9J","\"xor\"",[282,309,310],{"class":292},");\n",[282,312,314,316,319,321,324],{"class":284,"line":313},2,[282,315,289],{"class":288},[282,317,318],{"class":292}," key ",[282,320,296],{"class":288},[282,322,323],{"class":306}," \"494345\"",[282,325,326],{"class":292},";\n",[282,328,330,332,335,337,340],{"class":284,"line":329},3,[282,331,289],{"class":288},[282,333,334],{"class":292}," text ",[282,336,296],{"class":288},[282,338,339],{"class":306}," \"Burning 'em, if you ain't quick and nimble\\nI go crazy when I hear a cymbal\"",[282,341,326],{"class":292},[282,343,345,347,350,352,355,358,361],{"class":284,"line":344},4,[282,346,289],{"class":288},[282,348,349],{"class":292}," ciphertext ",[282,351,296],{"class":288},[282,353,354],{"class":292}," xor.",[282,356,357],{"class":299},"encode",[282,359,360],{"class":292},"(text, { key }).text; ",[282,362,364],{"class":363},"scIB-","\u002F\u002F \"0b3637272a2b2e63622c2e69692a2369...\"\n",[282,366,368,371,374,377,380,383],{"class":284,"line":367},5,[282,369,370],{"class":292},"xor.",[282,372,373],{"class":299},"decode",[282,375,376],{"class":292},"(ciphertext, { key }).text ",[282,378,379],{"class":288},"===",[282,381,382],{"class":292}," text; ",[282,384,385],{"class":363},"\u002F\u002F true\n",[242,387,388,389,392,393,396,397,400,401,404],{},"A key of one byte is the single-byte XOR every CTF opens with. A key of ",[257,390,391],{},"20"," just flips the case of letters. ",[257,394,395],{},"hi"," comes out as ",[257,398,399],{},"4849",", which is ",[257,402,403],{},"HI"," in ASCII. Cute, not secret.",[249,406,408],{"id":407},"keys-and-bytes","Keys and bytes",[242,410,411],{},"The key is hex, any whole number of bytes, at least one. Case doesn't matter and spaces are ignored. There's no upper limit in the library. A key longer than the text just leaves its tail unused. The agent tools cap it at 1000 characters, like every other key.",[242,413,414,415,417,418,421],{},"By default text goes in as UTF-8 and ciphertext comes out as lowercase hex, same as RC4 and Rabbit. ",[257,416,373],{}," wants that hex back and fails with ",[257,419,420],{},"Decrypted bytes are not UTF-8 text; pass bytes: hex to get them as hex"," when the result isn't text.",[242,423,424,425,428],{},"And puzzles love results that aren't text. A layer of XOR over another cipher, a key hidden as raw bytes, a blob that's half binary. So ",[257,426,427],{},"bytes: \"hex\""," reads hex and writes hex, in both directions:",[273,430,432],{"className":275,"code":431,"language":277,"meta":278,"style":278},"xor.decode(\"00ff80\", { key: \"ff\", bytes: \"hex\" }).text; \u002F\u002F \"ff007f\"\n",[257,433,434],{"__ignoreMap":278},[282,435,436,438,440,442,445,448,451,454,457,460],{"class":284,"line":285},[282,437,370],{"class":292},[282,439,373],{"class":299},[282,441,303],{"class":292},[282,443,444],{"class":306},"\"00ff80\"",[282,446,447],{"class":292},", { key: ",[282,449,450],{"class":306},"\"ff\"",[282,452,453],{"class":292},", bytes: ",[282,455,456],{"class":306},"\"hex\"",[282,458,459],{"class":292}," }).text; ",[282,461,462],{"class":363},"\u002F\u002F \"ff007f\"\n",[242,464,465,466,469],{},"No UTF-8 check there. You get the bytes, and you decide what they are. On the CLI it's ",[257,467,468],{},"--bytes hex",".",[249,471,473],{"id":472},"known-text-gives-the-key","Known text gives the key",[242,475,476,477,480],{},"Here's the fun part. XOR the ciphertext with text you know, and the key falls out. Guess the Cryptopals message starts with ",[257,478,479],{},"Burning "," and use that as the key:",[273,482,484],{"className":275,"code":483,"language":277,"meta":278,"style":278},"xor.decode(\"0b3637272a2b2e63\", { key: \"4275726e696e6720\", bytes: \"hex\" }).text;\n\u002F\u002F \"4943454943454943\", which is \"ICEICEIC\"\n",[257,485,486,509],{"__ignoreMap":278},[282,487,488,490,492,494,497,499,502,504,506],{"class":284,"line":285},[282,489,370],{"class":292},[282,491,373],{"class":299},[282,493,303],{"class":292},[282,495,496],{"class":306},"\"0b3637272a2b2e63\"",[282,498,447],{"class":292},[282,500,501],{"class":306},"\"4275726e696e6720\"",[282,503,453],{"class":292},[282,505,456],{"class":306},[282,507,508],{"class":292}," }).text;\n",[282,510,511],{"class":284,"line":313},[282,512,513],{"class":363},"\u002F\u002F \"4943454943454943\", which is \"ICEICEIC\"\n",[242,515,516,518],{},[257,517,266],{},", over and over. That's the whole key, and its length too.",[242,520,521],{},"Same key twice is worse. XOR two ciphertexts and the key cancels out, no guessing needed:",[273,523,525],{"className":275,"code":524,"language":277,"meta":278,"style":278},"xor.encode(\"Attack at dawn\", { key }).text; \u002F\u002F \"08373128202e6922316927243e2d\"\nxor.encode(\"Attack at dusk\", { key }).text; \u002F\u002F \"08373128202e6922316927303a28\"\n\u002F\u002F XOR: \"0000000000000000000000140405\"\n",[257,526,527,544,560],{"__ignoreMap":278},[282,528,529,531,533,535,538,541],{"class":284,"line":285},[282,530,370],{"class":292},[282,532,357],{"class":299},[282,534,303],{"class":292},[282,536,537],{"class":306},"\"Attack at dawn\"",[282,539,540],{"class":292},", { key }).text; ",[282,542,543],{"class":363},"\u002F\u002F \"08373128202e6922316927243e2d\"\n",[282,545,546,548,550,552,555,557],{"class":284,"line":313},[282,547,370],{"class":292},[282,549,357],{"class":299},[282,551,303],{"class":292},[282,553,554],{"class":306},"\"Attack at dusk\"",[282,556,540],{"class":292},[282,558,559],{"class":363},"\u002F\u002F \"08373128202e6922316927303a28\"\n",[282,561,562],{"class":284,"line":329},[282,563,564],{"class":363},"\u002F\u002F XOR: \"0000000000000000000000140405\"\n",[242,566,567,568,571,572,575],{},"That's ",[257,569,570],{},"dawn"," XOR ",[257,573,574],{},"dusk",", the same bytes RC4 gave. Every stream cipher with a reused keystream ends here. This one just gets here on purpose.",[249,577,579],{"id":578},"checked-against","Checked against",[242,581,582,583,586,587,590,591,469],{},"The Cryptopals 1.5 vector, both ways and both byte forms. The rest is arithmetic you can check with a pencil, like ",[257,584,585],{},"00ff80"," under ",[257,588,589],{},"ff"," giving ",[257,592,593],{},"ff007f",[249,595,597],{"id":596},"errors","Errors",[242,599,600,601,604,605,608,609,612,613,616,617,620,621,623,624,626,627,630,631,469],{},"A key that isn't hex, or isn't whole bytes, is an ",[257,602,603],{},"InvalidOptionError",". A missing key is a ",[257,606,607],{},"MissingOptionError",", and so is an empty one. A ",[257,610,611],{},"bytes"," other than ",[257,614,615],{},"text"," or ",[257,618,619],{},"hex"," is an ",[257,622,603],{}," too. On ",[257,625,373],{},", an odd number of hex digits or a letter past ",[257,628,629],{},"f"," is a ",[257,632,633],{},"CipherError",[242,635,636],{},"No integrity check, no secrecy worth the name. A puzzle hands you hex and a short word? Try it here before anything fancier.",[638,639,640],"style",{},"html pre.shiki code .skH_V, html code.shiki .skH_V{--shiki-light:var(--shiki-token-keyword);--shiki-default:var(--shiki-token-keyword);--shiki-dark:var(--shiki-token-keyword)}html pre.shiki code .s38Sx, html code.shiki .s38Sx{--shiki-light:var(--ui-text-highlighted);--shiki-default:var(--ui-text-highlighted);--shiki-dark:var(--ui-text-highlighted)}html pre.shiki code .sK71F, html code.shiki .sK71F{--shiki-light:var(--shiki-token-function);--shiki-default:var(--shiki-token-function);--shiki-dark:var(--shiki-token-function)}html pre.shiki code .shU9J, html code.shiki .shU9J{--shiki-light:var(--shiki-token-string);--shiki-default:var(--shiki-token-string);--shiki-dark:var(--shiki-token-string)}html pre.shiki code .scIB-, html code.shiki .scIB-{--shiki-light:var(--shiki-token-comment);--shiki-default:var(--shiki-token-comment);--shiki-dark:var(--shiki-token-comment)}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":278,"searchDepth":313,"depth":313,"links":642},[643,644,645,646,647],{"id":251,"depth":313,"text":252},{"id":407,"depth":313,"text":408},{"id":472,"depth":313,"text":473},{"id":578,"depth":313,"text":579},{"id":596,"depth":313,"text":597},"Repeating-key XOR. Vigenère on bytes, with a hex key of any length. UTF-8 text in and hex out, or hex on both sides.","md",null,{},true,{"title":228,"description":648},"AalxvC1MJQWo6VCOV-xKJS-wT3lTwHUcc5_6xdbcz6Y",[656,650],{"title":224,"path":225,"stem":226,"description":657,"children":-1},"Rivest's stream cipher from 1987. A key of 1 to 256 bytes shuffles a table of 256 byte values into keystream. UTF-8 text in and hex out with no padding.",1790883387858]