[{"data":1,"prerenderedAt":530},["ShallowReactive",2],{"navigation_docs":3,"-math-ed448":80,"-math-ed448-surround":527},[4,24],{"title":5,"path":6,"stem":7,"children":8,"icon":23},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19],{"title":10,"path":6,"stem":7},"Getting started",{"title":12,"path":13,"stem":14},"CLI","\u002Fguide\u002Fcli","1.guide\u002F02.cli",{"title":16,"path":17,"stem":18},"Agents","\u002Fguide\u002Fagents","1.guide\u002F03.agents",{"title":20,"path":21,"stem":22},"Playground","\u002Fguide\u002Fplayground","1.guide\u002F04.playground","i-lucide-book-open",{"title":25,"path":26,"stem":27,"children":28,"icon":79},"Math","\u002Fmath","2.math\u002F00.index",[29,31,35,39,43,47,51,55,59,63,67,71,75],{"title":30,"path":26,"stem":27},"Overview",{"title":32,"path":33,"stem":34},"Curves and points","\u002Fmath\u002Fcurves","2.math\u002F01.curves",{"title":36,"path":37,"stem":38},"Orders and logs","\u002Fmath\u002Fgroups","2.math\u002F02.groups",{"title":40,"path":41,"stem":42},"secp256k1","\u002Fmath\u002Fsecp256k1","2.math\u002F03.secp256k1",{"title":44,"path":45,"stem":46},"sr25519","\u002Fmath\u002Fsr25519","2.math\u002F04.sr25519",{"title":48,"path":49,"stem":50},"ed25519","\u002Fmath\u002Fed25519","2.math\u002F05.ed25519",{"title":52,"path":53,"stem":54},"P-256","\u002Fmath\u002Fp256","2.math\u002F06.p256",{"title":56,"path":57,"stem":58},"P-384","\u002Fmath\u002Fp384","2.math\u002F07.p384",{"title":60,"path":61,"stem":62},"P-521","\u002Fmath\u002Fp521","2.math\u002F08.p521",{"title":64,"path":65,"stem":66},"brainpoolP256r1","\u002Fmath\u002Fbrainpoolp256r1","2.math\u002F09.brainpoolp256r1",{"title":68,"path":69,"stem":70},"brainpoolP384r1","\u002Fmath\u002Fbrainpoolp384r1","2.math\u002F10.brainpoolp384r1",{"title":72,"path":73,"stem":74},"brainpoolP512r1","\u002Fmath\u002Fbrainpoolp512r1","2.math\u002F11.brainpoolp512r1",{"title":76,"path":77,"stem":78},"Ed448","\u002Fmath\u002Fed448","2.math\u002F12.ed448","i-lucide-sigma",{"id":81,"title":76,"body":82,"description":519,"extension":520,"links":521,"meta":522,"navigation":189,"path":77,"seo":524,"stem":78,"__hash__":526},"docs\u002F2.math\u002F12.ed448.md",{"type":83,"value":84,"toc":509},"minimark",[85,90,99,118,145,152,286,293,297,300,309,316,320,338,345,348,353,356,364,368,371,374,378,381,423,429,436,442,468,472,477,484,495,502,505],[86,87,89],"h2",{"id":88},"verify-an-ed448-signature","Verify an Ed448 signature",[91,92,93,94,98],"p",{},"Ed448 is Ed25519's bigger sibling. Here, ",[95,96,97],"code",{},"@agntn\u002Fcurves\u002Fed448"," verifies its signatures. It doesn't sign, derive keys or export point math.",[91,100,101,102,105,106,109,110,113,114,117],{},"RFC 8032 calls the curve edwards448. Its equation is ",[95,103,104],{},"x² + y² = 1 + d x²y²",". The field is ",[95,107,108],{},"p = 2^448 - 2^224 - 1",". The curve parameter ",[95,111,112],{},"d"," is ",[95,115,116],{},"-39081",". The cofactor is 4.",[91,119,120,121,124,125,127,128,127,130,127,133,136,137,140,141,144],{},"The ",[95,122,123],{},"ed448"," export holds ",[95,126,91],{},", ",[95,129,112],{},[95,131,132],{},"l",[95,134,135],{},"h = 4n"," and ",[95,138,139],{},"g",". The other export is ",[95,142,143],{},"verify",".",[91,146,147,148,151],{},"Here's the RFC 8032 section 7.4 vector with context ",[95,149,150],{},"foo",". Change the message or drop the context, and it fails.",[153,154,159],"pre",{"className":155,"code":156,"language":157,"meta":158,"style":158},"language-ts shiki shiki-themes compressions compressions compressions","import { verify } from \"@agntn\u002Fcurves\u002Fed448\";\n\nconst publicKey = \"43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480\";\nconst signature = \"d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00\";\n\nverify(signature, { message: \"03\", publicKey, context: \"666f6f\" }); \u002F\u002F true\nverify(signature, { message: \"03\", publicKey }); \u002F\u002F false\nverify(signature, { message: \"0300\", publicKey, context: \"666f6f\" }); \u002F\u002F false\n","ts","",[95,160,161,184,191,208,223,228,253,268],{"__ignoreMap":158},[162,163,166,170,174,177,181],"span",{"class":164,"line":165},"line",1,[162,167,169],{"class":168},"skH_V","import",[162,171,173],{"class":172},"s38Sx"," { verify } ",[162,175,176],{"class":168},"from",[162,178,180],{"class":179},"shU9J"," \"@agntn\u002Fcurves\u002Fed448\"",[162,182,183],{"class":172},";\n",[162,185,187],{"class":164,"line":186},2,[162,188,190],{"emptyLinePlaceholder":189},true,"\n",[162,192,194,197,200,203,206],{"class":164,"line":193},3,[162,195,196],{"class":168},"const",[162,198,199],{"class":172}," publicKey ",[162,201,202],{"class":168},"=",[162,204,205],{"class":179}," \"43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480\"",[162,207,183],{"class":172},[162,209,211,213,216,218,221],{"class":164,"line":210},4,[162,212,196],{"class":168},[162,214,215],{"class":172}," signature ",[162,217,202],{"class":168},[162,219,220],{"class":179}," \"d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00\"",[162,222,183],{"class":172},[162,224,226],{"class":164,"line":225},5,[162,227,190],{"emptyLinePlaceholder":189},[162,229,231,234,237,240,243,246,249],{"class":164,"line":230},6,[162,232,143],{"class":233},"sK71F",[162,235,236],{"class":172},"(signature, { message: ",[162,238,239],{"class":179},"\"03\"",[162,241,242],{"class":172},", publicKey, context: ",[162,244,245],{"class":179},"\"666f6f\"",[162,247,248],{"class":172}," }); ",[162,250,252],{"class":251},"scIB-","\u002F\u002F true\n",[162,254,256,258,260,262,265],{"class":164,"line":255},7,[162,257,143],{"class":233},[162,259,236],{"class":172},[162,261,239],{"class":179},[162,263,264],{"class":172},", publicKey }); ",[162,266,267],{"class":251},"\u002F\u002F false\n",[162,269,271,273,275,278,280,282,284],{"class":164,"line":270},8,[162,272,143],{"class":233},[162,274,236],{"class":172},[162,276,277],{"class":179},"\"0300\"",[162,279,242],{"class":172},[162,281,245],{"class":179},[162,283,248],{"class":172},[162,285,267],{"class":251},[91,287,288,289,292],{},"The public key is 57 bytes, or 114 hex digits. The signature is 114 bytes, R then S. That's 228 hex digits. The message is hex of any length, including empty. Leave ",[95,290,291],{},"0x"," off everything.",[86,294,296],{"id":295},"ed448-context","Ed448 context",[91,298,299],{},"The context is part of what got signed. It's 0 to 255 bytes, passed as hex. Leave it out and it's empty.",[91,301,302,303,113,306,308],{},"Got the right message but the wrong context? The signature fails. That includes leaving out a context the signer used. ",[95,304,305],{},"666f6f",[95,307,150],{}," in ASCII. Three small bytes, one very different answer.",[91,310,311,312,315],{},"Ed448ph isn't supported. That variant prehashes with ",[95,313,314],{},"SHAKE256(M, 64)",". Pass the message itself, not an Ed448ph prehash.",[86,317,319],{"id":318},"ed448-verification-rules","Ed448 verification rules",[91,321,322,323,326,327,330,331,334,335,144],{},"The verifier follows RFC 8032 section 5.2. It checks the cofactored equation ",[95,324,325],{},"4SB = 4R + 4kA",". The challenge comes from ",[95,328,329],{},"SHAKE256(dom4(0, context) || R || A || M, 114)",". ",[95,332,333],{},"dom4"," starts with ASCII ",[95,336,337],{},"SigEd448",[91,339,340,341,344],{},"Encodings must be canonical. A y at or above p fails. So does a sign bit set on x = 0. S at or above l fails too. These return ",[95,342,343],{},"false",", not an exception.",[91,346,347],{},"A small order key isn't refused. RFC 8032 doesn't ask for that check. The key still has to pass the equation, like any other.",[349,350,352],"h3",{"id":351},"what-does-verify-refuse","What does verify refuse?",[91,354,355],{},"Wrong shapes throw. The messages say what needs fixing.",[153,357,362],{"className":358,"code":360,"language":361,"meta":158},[359],"language-text","verify(\"00\", { message: \"\", publicKey })                     \u002F\u002F Signature must be 228 hex digits without 0x, R then S\nverify(signature, { message: \"0x00\", publicKey })            \u002F\u002F Message must be hex without 0x\nverify(signature, { message: \"\", publicKey: \"00\" })          \u002F\u002F Public key must be 114 hex digits without 0x\nverify(signature, { message: \"\", publicKey, context: \"zz\" }) \u002F\u002F Context must be hex without 0x, at most 255 bytes\n","text",[95,363,360],{"__ignoreMap":158},[86,365,367],{"id":366},"openpgp-ed448-signatures","OpenPGP Ed448 signatures",[91,369,370],{},"OpenPGP uses pure Ed448 with an empty context. That's algorithm 28 in RFC 9580. The default context is already empty, so leave it out.",[91,372,373],{},"OpenPGP hashes the signed data itself. Its hash must be at least 512 bits. Feed that digest as the Ed448 message. This isn't Ed448ph.",[86,375,377],{"id":376},"ed448-cli-and-agent-tool","Ed448 CLI and agent tool",[91,379,380],{},"The CLI checks the same context vector.",[153,382,386],{"className":383,"code":384,"language":385,"meta":158,"style":158},"language-bash shiki shiki-themes compressions compressions compressions","curves ed448 verify --public-key 43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480 --message 03 --signature d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00 --context 666f6f\n","bash",[95,387,388],{"__ignoreMap":158},[162,389,390,393,396,399,402,405,408,411,414,417,420],{"class":164,"line":165},[162,391,392],{"class":233},"curves",[162,394,395],{"class":179}," ed448",[162,397,398],{"class":179}," verify",[162,400,401],{"class":179}," --public-key",[162,403,404],{"class":179}," 43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480",[162,406,407],{"class":179}," --message",[162,409,410],{"class":179}," 03",[162,412,413],{"class":179}," --signature",[162,415,416],{"class":179}," d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00",[162,418,419],{"class":179}," --context",[162,421,422],{"class":179}," 666f6f\n",[153,424,427],{"className":425,"code":426,"language":361,"meta":158},[359],"{\"operation\":\"verify\",\"valid\":true}\n",[95,428,426],{"__ignoreMap":158},[91,430,431,432,435],{},"Remove ",[95,433,434],{},"--context"," and the answer changes.",[153,437,440],{"className":438,"code":439,"language":361,"meta":158},[359],"{\"operation\":\"verify\",\"valid\":false}\n",[95,441,439],{"__ignoreMap":158},[91,443,444,445,448,449,451,452,127,455,127,458,136,461,464,465,144],{},"The agent tool is ",[95,446,447],{},"curves_ed448_compute",", with operation ",[95,450,143],{},". It takes ",[95,453,454],{},"publicKey",[95,456,457],{},"message",[95,459,460],{},"signature",[95,462,463],{},"context",". It's the same tool over MCP, Pi and OMP. The AI SDK gets it from ",[95,466,467],{},"@agntn\u002Fcurves\u002Fai",[86,469,471],{"id":470},"written-from-the-specs","Written from the specs",[91,473,474,475,144],{},"The implementation follows RFC 8032. All nine Ed448 vectors from section 7.4 run in the tests. Their messages range from empty to 1023 bytes. One uses the context ",[95,476,150],{},[91,478,479,480,483],{},"The tests also cover all 87 Wycheproof Ed448 vectors. Ten more signatures come from OpenSSL 3.6.5, through Node.js 26.12.1 ",[95,481,482],{},"crypto.sign",". Their messages sit around SHAKE256's 136-byte block. Their contexts run 1, 57 and 255 bytes.",[91,485,486,487,490,491,494],{},"SHAKE256 lives in this package. It uses the same Keccak-f",[162,488,489],{},"1600"," as the sr25519 Merlin transcripts. ",[95,492,493],{},"@agntn\u002Fhashes"," 0.6.7 doesn't export SHAKE256.",[91,496,497,498,501],{},"In a local run, verification took about 8 ms here. OpenSSL through ",[95,499,500],{},"node:crypto"," took about 0.3 ms. Slower, and not hiding it.",[91,503,504],{},"Why no signing? Secret multiplication here has to take the same steps for every scalar. Ed448 doesn't have that yet. Verification uses public input only. No signing, no secret to multiply.",[506,507,508],"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":158,"searchDepth":186,"depth":186,"links":510},[511,512,513,516,517,518],{"id":88,"depth":186,"text":89},{"id":295,"depth":186,"text":296},{"id":318,"depth":186,"text":319,"children":514},[515],{"id":351,"depth":193,"text":352},{"id":366,"depth":186,"text":367},{"id":376,"depth":186,"text":377},{"id":470,"depth":186,"text":471},"Verify RFC 8032 Ed448 signatures with context and OpenPGP support","md",null,{"icon":523},"i-lucide-shield-plus",{"title":525,"description":519},"Ed448 signature verification and context","PQiz-ysB5L0rA-t2gmGwM4azNV_XYljeLAENckyRXS4",[528,521],{"title":72,"path":73,"stem":74,"description":529,"children":-1},"brainpoolP512r1 point math and ECDSA verification for OpenPGP keys and Brainpool certificates",1793795813932]