[{"data":1,"prerenderedAt":835},["ShallowReactive",2],{"navigation_docs":3,"-guide-extend":244,"-guide-extend-surround":830},[4,52],{"title":5,"path":6,"stem":7,"children":8,"icon":51},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19,23,27,31,35,39,43,47],{"title":10,"path":6,"stem":7},"Getting Started",{"title":12,"path":13,"stem":14},"Hashing","\u002Fguide\u002Fhashing","1.guide\u002F02.hashing",{"title":16,"path":17,"stem":18},"HMAC and verify","\u002Fguide\u002Fverify","1.guide\u002F03.verify",{"title":20,"path":21,"stem":22},"Salted KDFs","\u002Fguide\u002Fkdf","1.guide\u002F04.kdf",{"title":24,"path":25,"stem":26},"Length extension","\u002Fguide\u002Fextend","1.guide\u002F05.extend",{"title":28,"path":29,"stem":30},"Identify a hash","\u002Fguide\u002Fidentify","1.guide\u002F06.identify",{"title":32,"path":33,"stem":34},"Search for a transform","\u002Fguide\u002Fsearch","1.guide\u002F07.search",{"title":36,"path":37,"stem":38},"CLI","\u002Fguide\u002Fcli","1.guide\u002F08.cli",{"title":40,"path":41,"stem":42},"Agents","\u002Fguide\u002Fagents","1.guide\u002F09.agents",{"title":44,"path":45,"stem":46},"Custom algorithms","\u002Fguide\u002Fcustom","1.guide\u002F10.custom",{"title":48,"path":49,"stem":50},"Playground","\u002Fguide\u002Fplayground","1.guide\u002F11.playground","i-lucide-book-open",{"title":53,"path":54,"stem":55,"children":56,"icon":243},"Algorithms","\u002Falgorithms","2.algorithms\u002F00.index",[57,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],{"title":58,"path":54,"stem":55},"Every algorithm",{"title":60,"path":61,"stem":62},"SHA-256","\u002Falgorithms\u002Fsha256","2.algorithms\u002F01.sha256",{"title":64,"path":65,"stem":66},"SHA-384","\u002Falgorithms\u002Fsha384","2.algorithms\u002F02.sha384",{"title":68,"path":69,"stem":70},"SHA-512","\u002Falgorithms\u002Fsha512","2.algorithms\u002F03.sha512",{"title":72,"path":73,"stem":74},"SHA-224","\u002Falgorithms\u002Fsha224","2.algorithms\u002F04.sha224",{"title":76,"path":77,"stem":78},"SHA-512\u002F224","\u002Falgorithms\u002Fsha512-224","2.algorithms\u002F05.sha512-224",{"title":80,"path":81,"stem":82},"SHA-512\u002F256","\u002Falgorithms\u002Fsha512-256","2.algorithms\u002F06.sha512-256",{"title":84,"path":85,"stem":86},"SHA-512Half","\u002Falgorithms\u002Fsha512-half","2.algorithms\u002F07.sha512-half",{"title":88,"path":89,"stem":90},"SHA3-256","\u002Falgorithms\u002Fsha3-256","2.algorithms\u002F08.sha3-256",{"title":92,"path":93,"stem":94},"SHA3-512","\u002Falgorithms\u002Fsha3-512","2.algorithms\u002F09.sha3-512",{"title":96,"path":97,"stem":98},"Keccak-256","\u002Falgorithms\u002Fkeccak256","2.algorithms\u002F10.keccak256",{"title":100,"path":101,"stem":102},"BLAKE2b","\u002Falgorithms\u002Fblake2b","2.algorithms\u002F11.blake2b",{"title":104,"path":105,"stem":106},"BLAKE2b-256","\u002Falgorithms\u002Fblake2b-256","2.algorithms\u002F12.blake2b-256",{"title":108,"path":109,"stem":110},"BLAKE2b-224","\u002Falgorithms\u002Fblake2b-224","2.algorithms\u002F13.blake2b-224",{"title":112,"path":113,"stem":114},"BLAKE2s","\u002Falgorithms\u002Fblake2s","2.algorithms\u002F14.blake2s",{"title":116,"path":117,"stem":118},"BLAKE3","\u002Falgorithms\u002Fblake3","2.algorithms\u002F15.blake3",{"title":120,"path":121,"stem":122},"BLAKE-256","\u002Falgorithms\u002Fblake256","2.algorithms\u002F16.blake256",{"title":124,"path":125,"stem":126},"RIPEMD-160","\u002Falgorithms\u002Fripemd160","2.algorithms\u002F17.ripemd160",{"title":128,"path":129,"stem":130},"RIPEMD-320","\u002Falgorithms\u002Fripemd320","2.algorithms\u002F18.ripemd320",{"title":132,"path":133,"stem":134},"HASH160","\u002Falgorithms\u002Fhash160","2.algorithms\u002F19.hash160",{"title":136,"path":137,"stem":138},"HASH256","\u002Falgorithms\u002Fhash256","2.algorithms\u002F20.hash256",{"title":140,"path":141,"stem":142},"Whirlpool","\u002Falgorithms\u002Fwhirlpool","2.algorithms\u002F21.whirlpool",{"title":144,"path":145,"stem":146},"MD5","\u002Falgorithms\u002Fmd5","2.algorithms\u002F22.md5",{"title":148,"path":149,"stem":150},"MD4","\u002Falgorithms\u002Fmd4","2.algorithms\u002F23.md4",{"title":152,"path":153,"stem":154},"MD2","\u002Falgorithms\u002Fmd2","2.algorithms\u002F24.md2",{"title":156,"path":157,"stem":158},"NTLM","\u002Falgorithms\u002Fntlm","2.algorithms\u002F25.ntlm",{"title":160,"path":161,"stem":162},"SHA-1","\u002Falgorithms\u002Fsha1","2.algorithms\u002F26.sha1",{"title":164,"path":165,"stem":166},"SHA-0","\u002Falgorithms\u002Fsha0","2.algorithms\u002F27.sha0",{"title":168,"path":169,"stem":170},"RIPEMD-128","\u002Falgorithms\u002Fripemd128","2.algorithms\u002F28.ripemd128",{"title":172,"path":173,"stem":174},"RIPEMD-256","\u002Falgorithms\u002Fripemd256","2.algorithms\u002F29.ripemd256",{"title":176,"path":177,"stem":178},"HAVAL","\u002Falgorithms\u002Fhaval","2.algorithms\u002F30.haval",{"title":180,"path":181,"stem":182},"Tiger","\u002Falgorithms\u002Ftiger","2.algorithms\u002F31.tiger",{"title":184,"path":185,"stem":186},"CRC-32","\u002Falgorithms\u002Fcrc32","2.algorithms\u002F32.crc32",{"title":188,"path":189,"stem":190},"CRC-64","\u002Falgorithms\u002Fcrc64","2.algorithms\u002F33.crc64",{"title":192,"path":193,"stem":194},"CRC-24","\u002Falgorithms\u002Fcrc24","2.algorithms\u002F34.crc24",{"title":196,"path":197,"stem":198},"CRC-16\u002FXMODEM","\u002Falgorithms\u002Fcrc16-xmodem","2.algorithms\u002F35.crc16-xmodem",{"title":200,"path":201,"stem":202},"Adler-32","\u002Falgorithms\u002Fadler32","2.algorithms\u002F36.adler32",{"title":204,"path":205,"stem":206},"xxHash","\u002Falgorithms\u002Fxxhash","2.algorithms\u002F37.xxhash",{"title":208,"path":209,"stem":210},"FNV-1a (64-bit)","\u002Falgorithms\u002Ffnv1a","2.algorithms\u002F38.fnv1a",{"title":212,"path":213,"stem":214},"scrypt","\u002Falgorithms\u002Fscrypt","2.algorithms\u002F39.scrypt",{"title":216,"path":217,"stem":218},"PBKDF2","\u002Falgorithms\u002Fpbkdf2","2.algorithms\u002F40.pbkdf2",{"title":220,"path":221,"stem":222},"HKDF","\u002Falgorithms\u002Fhkdf","2.algorithms\u002F41.hkdf",{"title":224,"path":225,"stem":226},"EVP_BytesToKey","\u002Falgorithms\u002Fevp-bytestokey","2.algorithms\u002F42.evp-bytestokey",{"title":228,"path":229,"stem":230},"Argon2id","\u002Falgorithms\u002Fargon2id","2.algorithms\u002F43.argon2id",{"title":232,"path":233,"stem":234},"Argon2i","\u002Falgorithms\u002Fargon2i","2.algorithms\u002F44.argon2i",{"title":236,"path":237,"stem":238},"Argon2d","\u002Falgorithms\u002Fargon2d","2.algorithms\u002F45.argon2d",{"title":240,"path":241,"stem":242},"bcrypt","\u002Falgorithms\u002Fbcrypt","2.algorithms\u002F46.bcrypt","i-lucide-library",{"id":245,"title":24,"body":246,"description":822,"extension":823,"links":824,"meta":825,"navigation":307,"path":25,"seo":827,"stem":26,"__hash__":829},"docs\u002F1.guide\u002F05.extend.md",{"type":247,"value":248,"toc":817},"minimark",[249,254,267,270,490,508,512,515,518,597,612,616,619,626,734,760,763,805,813],[250,251,253],"h2",{"id":252},"the-digest-is-the-state","The digest is the state",[255,256,257,258,262,263,266],"p",{},"A server signs ",[259,260,261],"code",{},"user=guest"," as ",[259,264,265],{},"md5(secret + message)",". You see the message and the signature. You don't see the secret. Safe? Not even close.",[255,268,269],{},"MD5, SHA-1, SHA-256 and SHA-512 eat their input in blocks. After the last block the digest is simply the state, written out. So pick up that state, pretend the padding was part of the message, and keep hashing. Out comes a valid signature for a longer message. The secret never shows up.",[271,272,277],"pre",{"className":273,"code":274,"language":275,"meta":276,"style":276},"language-ts shiki shiki-themes hashes hashes hashes","import { extendDigest, md5 } from \"@agntn\u002Fhashes\";\n\nconst text = (value: string) => new TextEncoder().encode(value);\nconst signature = md5(text(\"keyuser=guest\")); \u002F\u002F f7e20fd66ebbe27bcdb0fa8ef25023fb\n\nconst forged = extendDigest({\n  algorithm: \"md5\",\n  digest: signature,\n  message: text(\"user=guest\"),\n  secretLength: 3,\n  suffix: text(\"&admin=true\"),\n});\nforged.digest.toHex(); \u002F\u002F \"cf098ea633bbf37494ef7b56cdae939b\"\nforged.message.length; \u002F\u002F 72, with 51 bytes of padding in the middle\n","ts","",[259,278,279,302,309,352,384,389,405,417,423,439,445,460,466,481],{"__ignoreMap":276},[280,281,284,288,292,295,299],"span",{"class":282,"line":283},"line",1,[280,285,287],{"class":286},"skH_V","import",[280,289,291],{"class":290},"s38Sx"," { extendDigest, md5 } ",[280,293,294],{"class":286},"from",[280,296,298],{"class":297},"shU9J"," \"@agntn\u002Fhashes\"",[280,300,301],{"class":290},";\n",[280,303,305],{"class":282,"line":304},2,[280,306,308],{"emptyLinePlaceholder":307},true,"\n",[280,310,312,315,319,322,325,328,331,334,337,340,343,346,349],{"class":282,"line":311},3,[280,313,314],{"class":286},"const",[280,316,318],{"class":317},"sK71F"," text",[280,320,321],{"class":286}," =",[280,323,324],{"class":290}," (value",[280,326,327],{"class":286},":",[280,329,330],{"class":317}," string",[280,332,333],{"class":290},") ",[280,335,336],{"class":286},"=>",[280,338,339],{"class":286}," new",[280,341,342],{"class":317}," TextEncoder",[280,344,345],{"class":290},"().",[280,347,348],{"class":317},"encode",[280,350,351],{"class":290},"(value);\n",[280,353,355,357,360,363,366,369,372,374,377,380],{"class":282,"line":354},4,[280,356,314],{"class":286},[280,358,359],{"class":290}," signature ",[280,361,362],{"class":286},"=",[280,364,365],{"class":317}," md5",[280,367,368],{"class":290},"(",[280,370,371],{"class":317},"text",[280,373,368],{"class":290},[280,375,376],{"class":297},"\"keyuser=guest\"",[280,378,379],{"class":290},")); ",[280,381,383],{"class":382},"scIB-","\u002F\u002F f7e20fd66ebbe27bcdb0fa8ef25023fb\n",[280,385,387],{"class":282,"line":386},5,[280,388,308],{"emptyLinePlaceholder":307},[280,390,392,394,397,399,402],{"class":282,"line":391},6,[280,393,314],{"class":286},[280,395,396],{"class":290}," forged ",[280,398,362],{"class":286},[280,400,401],{"class":317}," extendDigest",[280,403,404],{"class":290},"({\n",[280,406,408,411,414],{"class":282,"line":407},7,[280,409,410],{"class":290},"  algorithm: ",[280,412,413],{"class":297},"\"md5\"",[280,415,416],{"class":290},",\n",[280,418,420],{"class":282,"line":419},8,[280,421,422],{"class":290},"  digest: signature,\n",[280,424,426,429,431,433,436],{"class":282,"line":425},9,[280,427,428],{"class":290},"  message: ",[280,430,371],{"class":317},[280,432,368],{"class":290},[280,434,435],{"class":297},"\"user=guest\"",[280,437,438],{"class":290},"),\n",[280,440,442],{"class":282,"line":441},10,[280,443,444],{"class":290},"  secretLength: 3,\n",[280,446,448,451,453,455,458],{"class":282,"line":447},11,[280,449,450],{"class":290},"  suffix: ",[280,452,371],{"class":317},[280,454,368],{"class":290},[280,456,457],{"class":297},"\"&admin=true\"",[280,459,438],{"class":290},[280,461,463],{"class":282,"line":462},12,[280,464,465],{"class":290},"});\n",[280,467,469,472,475,478],{"class":282,"line":468},13,[280,470,471],{"class":290},"forged.digest.",[280,473,474],{"class":317},"toHex",[280,476,477],{"class":290},"(); ",[280,479,480],{"class":382},"\u002F\u002F \"cf098ea633bbf37494ef7b56cdae939b\"\n",[280,482,484,487],{"class":282,"line":483},14,[280,485,486],{"class":290},"forged.message.length; ",[280,488,489],{"class":382},"\u002F\u002F 72, with 51 bytes of padding in the middle\n",[255,491,492,495,496,499,500,503,504,507],{},[259,493,494],{},"forged.message"," is what you send: the original, the padding, then your suffix. The server puts ",[259,497,498],{},"key"," in front and gets ",[259,501,502],{},"cf098ea6..."," too. ",[259,505,506],{},"node:crypto"," agrees.",[250,509,511],{"id":510},"what-do-you-need-to-know","What do you need to know?",[255,513,514],{},"The digest, the message, the suffix. And how long the secret is, not what it is.",[255,516,517],{},"Don't know the length? Try a range. Lengths that land in the same block give the same digest, only the padding inside the message moves:",[271,519,523],{"className":520,"code":521,"language":522,"meta":276,"style":276},"language-bash shiki shiki-themes hashes hashes hashes","hashes extend md5 f7e20fd66ebbe27bcdb0fa8ef25023fb --message user=guest --suffix '&admin=true' --secret-length 2 --secret-length-max 4 --json \\\n  | jq -r '.extensions[] | \"\\(.secretLength) \\(.digest)\"'\n# 2 cf098ea633bbf37494ef7b56cdae939b\n# 3 cf098ea633bbf37494ef7b56cdae939b\n# 4 cf098ea633bbf37494ef7b56cdae939b\n","bash",[259,524,525,568,582,587,592],{"__ignoreMap":276},[280,526,527,530,533,535,538,541,544,547,550,553,556,559,562,565],{"class":282,"line":283},[280,528,529],{"class":317},"hashes",[280,531,532],{"class":297}," extend",[280,534,365],{"class":297},[280,536,537],{"class":297}," f7e20fd66ebbe27bcdb0fa8ef25023fb",[280,539,540],{"class":297}," --message",[280,542,543],{"class":297}," user=guest",[280,545,546],{"class":297}," --suffix",[280,548,549],{"class":297}," '&admin=true'",[280,551,552],{"class":297}," --secret-length",[280,554,555],{"class":297}," 2",[280,557,558],{"class":297}," --secret-length-max",[280,560,561],{"class":297}," 4",[280,563,564],{"class":297}," --json",[280,566,567],{"class":290}," \\\n",[280,569,570,573,576,579],{"class":282,"line":304},[280,571,572],{"class":286},"  |",[280,574,575],{"class":317}," jq",[280,577,578],{"class":297}," -r",[280,580,581],{"class":297}," '.extensions[] | \"\\(.secretLength) \\(.digest)\"'\n",[280,583,584],{"class":282,"line":311},[280,585,586],{"class":382},"# 2 cf098ea633bbf37494ef7b56cdae939b\n",[280,588,589],{"class":282,"line":354},[280,590,591],{"class":382},"# 3 cf098ea633bbf37494ef7b56cdae939b\n",[280,593,594],{"class":282,"line":386},[280,595,596],{"class":382},"# 4 cf098ea633bbf37494ef7b56cdae939b\n",[255,598,599,600,603,604,607,608,611],{},"Without ",[259,601,602],{},"--json"," you get each length with its digest, message and padding in hex. The padding is binary, so hex is the only honest way to print it. The ",[259,605,606],{},"hashes_digest_extend"," tool takes the same range as ",[259,609,610],{},"secretLengthMax",", up to 64 lengths per call.",[250,613,615],{"id":614},"which-hashes-fall-for-it","Which hashes fall for it?",[255,617,618],{},"The ones whose digest is the whole state: SHA-256, SHA-512, SHA-1, SHA-0, MD5, MD4, RIPEMD-128, 160, 256 and 320, Whirlpool, Tiger and HAVAL-256. Tiger opens its padding with 0x01 instead of 0x80. Same trick, one different byte. Whirlpool keeps the 0x80 and writes the length into 32 bytes. Same trick, bigger field.",[255,620,621,622,625],{},"HAVAL-256 falls for it too, it just wants papers. Its padding carries a little ID card: two bytes before the length with the version, the pass count and the fingerprint length. The forged padding has to show the same card, so tell ",[259,623,624],{},"extendDigest"," which HAVAL signed the message:",[271,627,629],{"className":273,"code":628,"language":275,"meta":276,"style":276},"const signature = \"206c3be5e68bae6a479028c23a69b369bc643dc7d106260a89b4a8f4506334f2\"; \u002F\u002F haval256,4 of \"k3yuser=a\"\n\nconst forged = extendDigest({\n  algorithm: \"haval\",\n  parameters: { passes: 4, bits: 256 },\n  digest: Uint8Array.fromHex(signature),\n  message: text(\"user=a\"),\n  secretLength: 3,\n  suffix: text(\"&admin=1\"),\n});\nforged.digest.toHex(); \u002F\u002F \"742f315b0257b1345e7fc65dcf9fef3b963d1d3f72f19c50cec93da4676a45e0\"\n",[259,630,631,648,652,664,673,678,689,702,706,719,723],{"__ignoreMap":276},[280,632,633,635,637,639,642,645],{"class":282,"line":283},[280,634,314],{"class":286},[280,636,359],{"class":290},[280,638,362],{"class":286},[280,640,641],{"class":297}," \"206c3be5e68bae6a479028c23a69b369bc643dc7d106260a89b4a8f4506334f2\"",[280,643,644],{"class":290},"; ",[280,646,647],{"class":382},"\u002F\u002F haval256,4 of \"k3yuser=a\"\n",[280,649,650],{"class":282,"line":304},[280,651,308],{"emptyLinePlaceholder":307},[280,653,654,656,658,660,662],{"class":282,"line":311},[280,655,314],{"class":286},[280,657,396],{"class":290},[280,659,362],{"class":286},[280,661,401],{"class":317},[280,663,404],{"class":290},[280,665,666,668,671],{"class":282,"line":354},[280,667,410],{"class":290},[280,669,670],{"class":297},"\"haval\"",[280,672,416],{"class":290},[280,674,675],{"class":282,"line":386},[280,676,677],{"class":290},"  parameters: { passes: 4, bits: 256 },\n",[280,679,680,683,686],{"class":282,"line":391},[280,681,682],{"class":290},"  digest: Uint8Array.",[280,684,685],{"class":317},"fromHex",[280,687,688],{"class":290},"(signature),\n",[280,690,691,693,695,697,700],{"class":282,"line":407},[280,692,428],{"class":290},[280,694,371],{"class":317},[280,696,368],{"class":290},[280,698,699],{"class":297},"\"user=a\"",[280,701,438],{"class":290},[280,703,704],{"class":282,"line":419},[280,705,444],{"class":290},[280,707,708,710,712,714,717],{"class":282,"line":425},[280,709,450],{"class":290},[280,711,371],{"class":317},[280,713,368],{"class":290},[280,715,716],{"class":297},"\"&admin=1\"",[280,718,438],{"class":290},[280,720,721],{"class":282,"line":441},[280,722,465],{"class":290},[280,724,725,727,729,731],{"class":282,"line":447},[280,726,471],{"class":290},[280,728,474],{"class":317},[280,730,477],{"class":290},[280,732,733],{"class":382},"\u002F\u002F \"742f315b0257b1345e7fc65dcf9fef3b963d1d3f72f19c50cec93da4676a45e0\"\n",[255,735,736,737,740,741,743,744,747,748,751,752,755,756,759],{},"PHP's ",[259,738,739],{},"hash(\"haval256,4\", ...)"," of the secret and the forged message agrees. ",[259,742,606],{}," takes the same ",[259,745,746],{},"parameters",", and ",[259,749,750],{},"hashes extend"," takes them as JSON: ",[259,753,754],{},"--parameters '{\"passes\":4,\"bits\":256}'",". Forget ",[259,757,758],{},"bits"," and the error names it for you. HAVAL-128 to 224 are out of luck. They fold the spare words into the kept ones, and nothing unfolds that.",[255,761,762],{},"SHA-224, SHA-384 and SHA-512\u002Ft cut part of the state off before they print it, so there's nothing complete to resume from. SHA-3, Keccak and BLAKE aren't built that way at all. HMAC isn't either. It hashes the result once more under the key, and that outer hash is what you see. Ask for one of those and you get a list of what works:",[271,764,766],{"className":520,"code":765,"language":522,"meta":276,"style":276},"hashes extend sha384 \"$(hashes sha384 x)\" --message x --suffix y --secret-length 1\n# Invalid option algorithm=sha384: cannot be extended, use one of sha256, sha512, ripemd160, ripemd320, whirlpool, md5, md4, sha1, sha0, ripemd128, ripemd256, haval, tiger\n",[259,767,768,800],{"__ignoreMap":276},[280,769,770,772,774,777,780,782,785,787,790,792,795,797],{"class":282,"line":283},[280,771,529],{"class":317},[280,773,532],{"class":297},[280,775,776],{"class":297}," sha384",[280,778,779],{"class":297}," \"$(",[280,781,529],{"class":317},[280,783,784],{"class":297}," sha384 x)\"",[280,786,540],{"class":297},[280,788,789],{"class":297}," x",[280,791,546],{"class":297},[280,793,794],{"class":297}," y",[280,796,552],{"class":297},[280,798,799],{"class":297}," 1\n",[280,801,802],{"class":282,"line":304},[280,803,804],{"class":382},"# Invalid option algorithm=sha384: cannot be extended, use one of sha256, sha512, ripemd160, ripemd320, whirlpool, md5, md4, sha1, sha0, ripemd128, ripemd256, haval, tiger\n",[255,806,807,808,812],{},"So the fix for the server above is boring. Use ",[809,810,811],"a",{"href":17},"HMAC",". That's the whole point of it.",[814,815,816],"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 .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 .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 .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":276,"searchDepth":304,"depth":304,"links":818},[819,820,821],{"id":252,"depth":304,"text":253},{"id":510,"depth":304,"text":511},{"id":614,"depth":304,"text":615},"Forge the digest of a longer message from a known MD5 or SHA-256 digest and the length of the secret. The secret itself stays unknown","md",null,{"icon":826},"i-lucide-arrow-right-to-line",{"title":828,"description":822},"Length extension attack on SHA-256 and MD5 in TypeScript","JcllCJYjjtYTu2rvbEuRORGQc8q3K8tYHbWxBkyO44s",[831,833],{"title":20,"path":21,"stem":22,"description":832,"children":-1},"scrypt and PBKDF2 and Argon2 draw a salt when you give none and print it next to the digest. Keep it or the digest is useless",{"title":28,"path":29,"stem":30,"description":834,"children":-1},"A digest with no name on it. Read its prefix or its length and list the algorithms that fit. Each one says if hashes can compute it",1791911606468]