[{"data":1,"prerenderedAt":498},["ShallowReactive",2],{"navigation_docs":3,"-ciphers-xsalsa20":276,"-ciphers-xsalsa20-surround":493},[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":275},"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,231,235,239,243,247,251,255,259,263,267,271],{"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},"A1Z26","\u002Fciphers\u002Fa1z26","2.ciphers\u002F17.a1z26",{"title":112,"path":113,"stem":114},"Book cipher","\u002Fciphers\u002Fbook","2.ciphers\u002F18.book",{"title":116,"path":117,"stem":118},"ADFGVX","\u002Fciphers\u002Fadfgvx","2.ciphers\u002F19.adfgvx",{"title":120,"path":121,"stem":122},"Bifid","\u002Fciphers\u002Fbifid","2.ciphers\u002F20.bifid",{"title":124,"path":125,"stem":126},"Straddling checkerboard","\u002Fciphers\u002Fstraddling-checkerboard","2.ciphers\u002F21.straddling-checkerboard",{"title":128,"path":129,"stem":130},"Rail fence","\u002Fciphers\u002Frail-fence","2.ciphers\u002F22.rail-fence",{"title":132,"path":133,"stem":134},"Columnar transposition","\u002Fciphers\u002Fcolumnar","2.ciphers\u002F23.columnar",{"title":136,"path":137,"stem":138},"Route transposition","\u002Fciphers\u002Froute","2.ciphers\u002F24.route",{"title":140,"path":141,"stem":142},"Enigma M3","\u002Fciphers\u002Fenigma","2.ciphers\u002F25.enigma",{"title":144,"path":145,"stem":146},"Block","\u002Fciphers\u002Fblock","2.ciphers\u002F26.block",{"title":148,"path":149,"stem":150},"AES (ECB)","\u002Fciphers\u002Faes","2.ciphers\u002F27.aes",{"title":152,"path":153,"stem":154},"AES (CBC)","\u002Fciphers\u002Faes-cbc","2.ciphers\u002F28.aes-cbc",{"title":156,"path":157,"stem":158},"AES (CFB)","\u002Fciphers\u002Faes-cfb","2.ciphers\u002F29.aes-cfb",{"title":160,"path":161,"stem":162},"AES (OFB)","\u002Fciphers\u002Faes-ofb","2.ciphers\u002F30.aes-ofb",{"title":164,"path":165,"stem":166},"AES (CTR)","\u002Fciphers\u002Faes-ctr","2.ciphers\u002F31.aes-ctr",{"title":168,"path":169,"stem":170},"AES (CCM)","\u002Fciphers\u002Faes-ccm","2.ciphers\u002F32.aes-ccm",{"title":172,"path":173,"stem":174},"AES (OCB)","\u002Fciphers\u002Faes-ocb","2.ciphers\u002F33.aes-ocb",{"title":176,"path":177,"stem":178},"AES (LRW)","\u002Fciphers\u002Faes-lrw","2.ciphers\u002F34.aes-lrw",{"title":180,"path":181,"stem":182},"AES (XTS)","\u002Fciphers\u002Faes-xts","2.ciphers\u002F35.aes-xts",{"title":184,"path":185,"stem":186},"AES (CBC-MAC)","\u002Fciphers\u002Faes-cbc-mac","2.ciphers\u002F36.aes-cbc-mac",{"title":188,"path":189,"stem":190},"AES (passphrase)","\u002Fciphers\u002Faes-passphrase","2.ciphers\u002F37.aes-passphrase",{"title":192,"path":193,"stem":194},"Rijndael (ECB)","\u002Fciphers\u002Frijndael","2.ciphers\u002F38.rijndael",{"title":196,"path":197,"stem":198},"DES (ECB)","\u002Fciphers\u002Fdes","2.ciphers\u002F39.des",{"title":200,"path":201,"stem":202},"DESX (ECB)","\u002Fciphers\u002Fdesx","2.ciphers\u002F40.desx",{"title":204,"path":205,"stem":206},"Triple DES (ECB)","\u002Fciphers\u002Ftriple-des","2.ciphers\u002F41.triple-des",{"title":208,"path":209,"stem":210},"Triple DES (CBC)","\u002Fciphers\u002Ftriple-des-cbc","2.ciphers\u002F42.triple-des-cbc",{"title":212,"path":213,"stem":214},"Blowfish (ECB)","\u002Fciphers\u002Fblowfish","2.ciphers\u002F43.blowfish",{"title":216,"path":217,"stem":218},"IDEA (ECB)","\u002Fciphers\u002Fidea","2.ciphers\u002F44.idea",{"title":220,"path":221,"stem":222},"Lucifer (ECB)","\u002Fciphers\u002Flucifer","2.ciphers\u002F45.lucifer",{"title":224,"path":225,"stem":226},"MARS (ECB)","\u002Fciphers\u002Fmars","2.ciphers\u002F46.mars",{"title":228,"path":229,"stem":230},"Serpent (ECB)","\u002Fciphers\u002Fserpent","2.ciphers\u002F47.serpent",{"title":232,"path":233,"stem":234},"CAST5 (ECB)","\u002Fciphers\u002Fcast5","2.ciphers\u002F48.cast5",{"title":236,"path":237,"stem":238},"OpenPGP (passphrase)","\u002Fciphers\u002Fopenpgp","2.ciphers\u002F49.openpgp",{"title":240,"path":241,"stem":242},"Stream","\u002Fciphers\u002Fstream","2.ciphers\u002F50.stream",{"title":244,"path":245,"stem":246},"Rabbit","\u002Fciphers\u002Frabbit","2.ciphers\u002F51.rabbit",{"title":248,"path":249,"stem":250},"RC4","\u002Fciphers\u002Frc4","2.ciphers\u002F52.rc4",{"title":252,"path":253,"stem":254},"XOR","\u002Fciphers\u002Fxor","2.ciphers\u002F53.xor",{"title":256,"path":257,"stem":258},"Salsa20","\u002Fciphers\u002Fsalsa20","2.ciphers\u002F54.salsa20",{"title":260,"path":261,"stem":262},"XSalsa20","\u002Fciphers\u002Fxsalsa20","2.ciphers\u002F55.xsalsa20",{"title":264,"path":265,"stem":266},"ChaCha20","\u002Fciphers\u002Fchacha20","2.ciphers\u002F56.chacha20",{"title":268,"path":269,"stem":270},"XChaCha20","\u002Fciphers\u002Fxchacha20","2.ciphers\u002F57.xchacha20",{"title":272,"path":273,"stem":274},"ChaCha20-Poly1305","\u002Fciphers\u002Fchacha20-poly1305","2.ciphers\u002F58.chacha20-poly1305","i-lucide-library",{"id":277,"title":260,"body":278,"description":486,"extension":487,"links":488,"meta":489,"navigation":490,"path":261,"seo":491,"stem":262,"__hash__":492},"docs\u002F2.ciphers\u002F55.xsalsa20.md",{"type":279,"value":280,"toc":481},"minimark",[281,285,294,299,302,309,312,316,327,436,443,457,461,464,474,477],[282,283],"cipher-facts",{"name":284},"xsalsa20",[286,287,288,289,293],"p",{},"Eight bytes of nonce is a problem. Pick them at random and two messages share one after about four billion messages. That's the birthday bound, and four billion isn't that many. Bernstein's fix, in \"Extending the Salsa20 nonce\" from 2008, was XSalsa20. NaCl and libsodium encrypt ",[290,291,292],"code",{},"crypto_secretbox"," with it.",[295,296,298],"h2",{"id":297},"how-it-runs","How it runs",[286,300,301],{},"The nonce is 24 bytes. The first 16 go through HSalsa20 with the key. That's the Salsa20 rounds on a state where nonce and counter would be, except nothing gets added back at the end. Eight of the output words become a new 256-bit key.",[286,303,304,305,308],{},"Then plain ",[306,307,256],"a",{"href":257}," runs under that subkey, with the last 8 nonce bytes as its nonce. One extra pass of the rounds per message, and that's the whole cost.",[286,310,311],{},"Why does it work? A different nonce gives a different subkey. Collisions now need 24 equal bytes, and that's far enough for random nonces.",[295,313,315],{"id":314},"keys-nonce-and-counter","Keys, nonce and counter",[286,317,318,319,322,323,326],{},"The key is 64 hex digits, 256 bits only. ",[290,320,321],{},"nonce"," is 48 hex digits and required. ",[290,324,325],{},"counter"," works as in Salsa20, default 0.",[328,329,334],"pre",{"className":330,"code":331,"language":332,"meta":333,"style":333},"language-ts shiki shiki-themes ciphers ciphers ciphers","const xsalsa = create(\"xsalsa20\");\nconst key = \"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\";\nconst nonce = \"000102030405060708090a0b0c0d0e0f1011121314151617\";\nxsalsa.encode(\"ATTACK AT DAWN\", { key, nonce }).text; \u002F\u002F \"3de234ee9ed5e607db77992c737d\"\nxsalsa.decode(\"3de234ee9ed5e607db77992c737d\", { key, nonce }).text; \u002F\u002F \"ATTACK AT DAWN\"\n","ts","",[290,335,336,366,382,397,418],{"__ignoreMap":333},[337,338,341,345,349,352,356,359,363],"span",{"class":339,"line":340},"line",1,[337,342,344],{"class":343},"skH_V","const",[337,346,348],{"class":347},"s38Sx"," xsalsa ",[337,350,351],{"class":343},"=",[337,353,355],{"class":354},"sK71F"," create",[337,357,358],{"class":347},"(",[337,360,362],{"class":361},"shU9J","\"xsalsa20\"",[337,364,365],{"class":347},");\n",[337,367,369,371,374,376,379],{"class":339,"line":368},2,[337,370,344],{"class":343},[337,372,373],{"class":347}," key ",[337,375,351],{"class":343},[337,377,378],{"class":361}," \"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\"",[337,380,381],{"class":347},";\n",[337,383,385,387,390,392,395],{"class":339,"line":384},3,[337,386,344],{"class":343},[337,388,389],{"class":347}," nonce ",[337,391,351],{"class":343},[337,393,394],{"class":361}," \"000102030405060708090a0b0c0d0e0f1011121314151617\"",[337,396,381],{"class":347},[337,398,400,403,406,408,411,414],{"class":339,"line":399},4,[337,401,402],{"class":347},"xsalsa.",[337,404,405],{"class":354},"encode",[337,407,358],{"class":347},[337,409,410],{"class":361},"\"ATTACK AT DAWN\"",[337,412,413],{"class":347},", { key, nonce }).text; ",[337,415,417],{"class":416},"scIB-","\u002F\u002F \"3de234ee9ed5e607db77992c737d\"\n",[337,419,421,423,426,428,431,433],{"class":339,"line":420},5,[337,422,402],{"class":347},[337,424,425],{"class":354},"decode",[337,427,358],{"class":347},[337,429,430],{"class":361},"\"3de234ee9ed5e607db77992c737d\"",[337,432,413],{"class":347},[337,434,435],{"class":416},"\u002F\u002F \"ATTACK AT DAWN\"\n",[286,437,438,439,442],{},"Got a NaCl secretbox? The first 32 bytes of its stream go to the Poly1305 key, and the message starts after them. So ",[290,440,441],{},"counter: 0"," gives you the MAC key, and the text sits at byte 32 of block 0. This package doesn't open secretboxes. It gives you the stream to do it by hand.",[286,444,445,448,449,452,453,456],{},[290,446,447],{},"xsalsa20(data, key, nonce, counter)"," from ",[290,450,451],{},"@agntn\u002Fciphers\u002Fsalsa"," runs the same thing on ",[290,454,455],{},"Uint8Array",".",[295,458,460],{"id":459},"checked-against","Checked against",[286,462,463],{},"Two of the XSalsa20 vectors in Crypto++, which Wei Dai made with naclcrypto-20090308. The 139-byte stream of the first by digest, the other one both ways.",[286,465,466,467,470,471,456],{},"A key that isn't 64 hex digits is an ",[290,468,469],{},"InvalidOptionError",", and so is a nonce that isn't 48 or a bad counter. A missing key or nonce is a ",[290,472,473],{},"MissingOptionError",[286,475,476],{},"Random nonces stop being scary here. A reused one is still as bad as in Salsa20, and there's still no tag. Puzzles and learning only.",[478,479,480],"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":333,"searchDepth":368,"depth":368,"links":482},[483,484,485],{"id":297,"depth":368,"text":298},{"id":314,"depth":368,"text":315},{"id":459,"depth":368,"text":460},"Salsa20 with a 24-byte nonce, the stream inside NaCl's secretbox. HSalsa20 turns the key and half the nonce into a subkey. UTF-8 in, hex out.","md",null,{},true,{"title":260,"description":486},"91piiqL33e8qfeC__v-q0VJ4RYlzoMU964e2FlG57ls",[494,496],{"title":256,"path":257,"stem":258,"description":495,"children":-1},"Bernstein's stream cipher from 2005. Twenty rounds of add, rotate and XOR turn key, nonce and counter into keystream. UTF-8 in, hex out, no padding.",{"title":264,"path":265,"stem":266,"description":497,"children":-1},"Salsa20 reshuffled, as RFC 8439 runs it in TLS and WireGuard. A 256-bit key, a 96-bit nonce and a 32-bit counter. UTF-8 in, hex out, no padding.",1791184045592]