[{"data":1,"prerenderedAt":653},["ShallowReactive",2],{"navigation_docs":3,"-math-p384":80,"-math-p384-surround":648},[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":56,"body":82,"description":640,"extension":641,"links":642,"meta":643,"navigation":139,"path":57,"seo":645,"stem":58,"__hash__":647},"docs\u002F2.math\u002F07.p384.md",{"type":83,"value":84,"toc":630},"minimark",[85,90,94,101,195,198,202,209,349,352,355,360,363,370,374,382,385,403,407,414,450,453,459,512,516,523,565,571,579,583,597,600,603,610,617,620,626],[86,87,89],"h2",{"id":88},"p-384-also-called-secp384r1","P-384, also called secp384r1",[91,92,93],"p",{},"P-384 is here for ES384, certificates and CNSA suites. SEC 2 v2 calls it secp384r1 in section 2.5.1. OpenSSL calls it secp384r1 too.",[91,95,96,97,100],{},"It uses y² = x³ - 3x + b over a 384-bit prime. The cofactor is 1. That's the same a = -3 shape as ",[98,99,52],"a",{"href":53},".",[102,103,108],"pre",{"className":104,"code":105,"language":106,"meta":107,"style":107},"language-ts shiki shiki-themes compressions compressions compressions","import { isOnCurve, multiplyGenerator } from \"@agntn\u002Fcurves\u002Fp384\";\n\nmultiplyGenerator(1n); \u002F\u002F \"03aa87ca22be8b05…3872760ab7\"\nisOnCurve(`02${\"1\".padStart(96, \"0\")}`); \u002F\u002F false\n","ts","",[109,110,111,134,141,161],"code",{"__ignoreMap":107},[112,113,116,120,124,127,131],"span",{"class":114,"line":115},"line",1,[112,117,119],{"class":118},"skH_V","import",[112,121,123],{"class":122},"s38Sx"," { isOnCurve, multiplyGenerator } ",[112,125,126],{"class":118},"from",[112,128,130],{"class":129},"shU9J"," \"@agntn\u002Fcurves\u002Fp384\"",[112,132,133],{"class":122},";\n",[112,135,137],{"class":114,"line":136},2,[112,138,140],{"emptyLinePlaceholder":139},true,"\n",[112,142,144,148,151,154,157],{"class":114,"line":143},3,[112,145,147],{"class":146},"sK71F","multiplyGenerator",[112,149,150],{"class":122},"(1",[112,152,153],{"class":118},"n",[112,155,156],{"class":122},"); ",[112,158,160],{"class":159},"scIB-","\u002F\u002F \"03aa87ca22be8b05…3872760ab7\"\n",[112,162,164,167,170,173,175,178,181,184,187,190,192],{"class":114,"line":163},4,[112,165,166],{"class":146},"isOnCurve",[112,168,169],{"class":122},"(",[112,171,172],{"class":129},"`02${\"1\"",[112,174,100],{"class":129},[112,176,177],{"class":146},"padStart",[112,179,180],{"class":129},"(96, ",[112,182,183],{"class":129},"\"0\"",[112,185,186],{"class":129},")",[112,188,189],{"class":129},"}`",[112,191,156],{"class":122},[112,193,194],{"class":159},"\u002F\u002F false\n",[91,196,197],{},"Coordinates and scalars take 48 bytes, or 96 hex digits. P-256 takes 32 bytes. Compressed P-384 points take 49 bytes. Uncompressed points take 97.",[86,199,201],{"id":200},"verify-a-p-384-ecdsa-signature","Verify a P-384 ECDSA signature",[91,203,204,205,208],{},"Have an ES384 token or a TLS certificate to check? Import ",[109,206,207],{},"verify",", supply the digest and public key, and pass the signature.",[102,210,212],{"className":104,"code":211,"language":106,"meta":107,"style":107},"import { verify } from \"@agntn\u002Fcurves\u002Fp384\";\n\nconst publicKey =\n  \"04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc13\" +\n  \"8015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720\";\nconst digest =\n  \"9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312313bca4a9b5b890efee42c77b1ee25fe\"; \u002F\u002F SHA-384 of \"sample\"\nconst signature =\n  \"94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe46\" +\n  \"99ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8\";\n\nverify(signature, { digest, publicKey }); \u002F\u002F true\nverify(signature, { digest: `00${digest.slice(2)}`, publicKey }); \u002F\u002F false\n",[109,213,214,227,231,242,250,258,268,280,290,298,306,311,322],{"__ignoreMap":107},[112,215,216,218,221,223,225],{"class":114,"line":115},[112,217,119],{"class":118},[112,219,220],{"class":122}," { verify } ",[112,222,126],{"class":118},[112,224,130],{"class":129},[112,226,133],{"class":122},[112,228,229],{"class":114,"line":136},[112,230,140],{"emptyLinePlaceholder":139},[112,232,233,236,239],{"class":114,"line":143},[112,234,235],{"class":118},"const",[112,237,238],{"class":122}," publicKey ",[112,240,241],{"class":118},"=\n",[112,243,244,247],{"class":114,"line":163},[112,245,246],{"class":129},"  \"04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc13\"",[112,248,249],{"class":118}," +\n",[112,251,253,256],{"class":114,"line":252},5,[112,254,255],{"class":129},"  \"8015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720\"",[112,257,133],{"class":122},[112,259,261,263,266],{"class":114,"line":260},6,[112,262,235],{"class":118},[112,264,265],{"class":122}," digest ",[112,267,241],{"class":118},[112,269,271,274,277],{"class":114,"line":270},7,[112,272,273],{"class":129},"  \"9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312313bca4a9b5b890efee42c77b1ee25fe\"",[112,275,276],{"class":122},"; ",[112,278,279],{"class":159},"\u002F\u002F SHA-384 of \"sample\"\n",[112,281,283,285,288],{"class":114,"line":282},8,[112,284,235],{"class":118},[112,286,287],{"class":122}," signature ",[112,289,241],{"class":118},[112,291,293,296],{"class":114,"line":292},9,[112,294,295],{"class":129},"  \"94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe46\"",[112,297,249],{"class":118},[112,299,301,304],{"class":114,"line":300},10,[112,302,303],{"class":129},"  \"99ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8\"",[112,305,133],{"class":122},[112,307,309],{"class":114,"line":308},11,[112,310,140],{"emptyLinePlaceholder":139},[112,312,314,316,319],{"class":114,"line":313},12,[112,315,207],{"class":146},[112,317,318],{"class":122},"(signature, { digest, publicKey }); ",[112,320,321],{"class":159},"\u002F\u002F true\n",[112,323,325,327,330,333,336,339,342,344,347],{"class":114,"line":324},13,[112,326,207],{"class":146},[112,328,329],{"class":122},"(signature, { digest: ",[112,331,332],{"class":129},"`00${",[112,334,335],{"class":129},"digest.",[112,337,338],{"class":146},"slice",[112,340,341],{"class":129},"(2)",[112,343,189],{"class":129},[112,345,346],{"class":122},", publicKey }); ",[112,348,194],{"class":159},[91,350,351],{},"The key and signature come from RFC 6979 appendix A.2.6. The RFC signed the six bytes of \"sample\" with SHA-384.",[91,353,354],{},"The signature is r followed by s. That's 96 bytes, or 192 hex digits. That's a lot to paste. The public key is compressed or uncompressed SEC1 hex.",[356,357,359],"h3",{"id":358},"what-about-der-and-the-digest","What about DER and the digest?",[91,361,362],{},"A JWS ES384 signature is already r then s. X.509 sends DER, so unpack r and s first.",[91,364,365,366,369],{},"Hash the signed bytes yourself. ES384 uses SHA-384. The digest takes 1 to 64 bytes as hex, without ",[109,367,368],{},"0x",". Past 48 bytes, only the leftmost 384 bits count. SHA-512 works too. A SHA-256 digest is shorter than n and counts whole.",[356,371,373],{"id":372},"what-does-it-refuse","What does it refuse?",[102,375,380],{"className":376,"code":378,"language":379,"meta":107},[377],"language-text","verify(\"00\", { digest, publicKey })                   \u002F\u002F Signature must be 192 hex digits without 0x, r then s\nverify(signature, { digest: \"0x00\", publicKey })      \u002F\u002F Digest must be hex without 0x, 1 to 64 bytes\nverify(signature, { digest, publicKey: p256G })       \u002F\u002F Invalid SEC1 P-384 public key\nliftX(\"1\".padStart(96, \"0\"))                          \u002F\u002F No point of P-384 has this x\n","text",[109,381,378],{"__ignoreMap":107},[91,383,384],{},"Wrong shapes throw. A compressed P-256 point is 33 bytes, not 49. It's the wrong width for P-384.",[91,386,387,388,391,392,395,396,398,399,402],{},"An r or s outside 1 to n - 1 returns ",[109,389,390],{},"false",". The ",[109,393,394],{},"lowS"," option defaults to ",[109,397,390],{},". Set it to ",[109,400,401],{},"true"," to refuse s above n \u002F 2.",[356,404,406],{"id":405},"cli-and-agent-tool","CLI and agent tool",[91,408,409,410,413],{},"The CLI uses ",[109,411,412],{},"curves p384 \u003Coperation>",". Verification takes the same inputs.",[102,415,419],{"className":416,"code":417,"language":418,"meta":107,"style":107},"language-bash shiki shiki-themes compressions compressions compressions","curves p384 verify --point 04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720 --digest 9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312313bca4a9b5b890efee42c77b1ee25fe --signature 94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe4699ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8\n","bash",[109,420,421],{"__ignoreMap":107},[112,422,423,426,429,432,435,438,441,444,447],{"class":114,"line":115},[112,424,425],{"class":146},"curves",[112,427,428],{"class":129}," p384",[112,430,431],{"class":129}," verify",[112,433,434],{"class":129}," --point",[112,436,437],{"class":129}," 04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720",[112,439,440],{"class":129}," --digest",[112,442,443],{"class":129}," 9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312313bca4a9b5b890efee42c77b1ee25fe",[112,445,446],{"class":129}," --signature",[112,448,449],{"class":129}," 94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe4699ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8\n",[91,451,452],{},"It prints:",[102,454,457],{"className":455,"code":456,"language":379,"meta":107},[377],"{\"operation\":\"verify\",\"valid\":true}\n",[109,458,456],{"__ignoreMap":107},[91,460,461,462,465,466,465,469,465,472,465,475,465,478,481,482,484,485,488,489,465,492,465,495,465,498,465,501,465,504,465,507,481,509,100],{},"The CLI offers ",[109,463,464],{},"add",", ",[109,467,468],{},"subtract",[109,470,471],{},"negate",[109,473,474],{},"multiply",[109,476,477],{},"lift",[109,479,480],{},"check"," and ",[109,483,207],{},". The agent tool ",[109,486,487],{},"curves_p384_compute"," offers the same operations. Its arguments are ",[109,490,491],{},"point",[109,493,494],{},"other",[109,496,497],{},"scalar",[109,499,500],{},"x",[109,502,503],{},"digest",[109,505,506],{},"signature",[109,508,394],{},[109,510,511],{},"compressed",[86,513,515],{"id":514},"p-384-point-math","P-384 point math",[91,517,518,519,522],{},"The ",[109,520,521],{},"@agntn\u002Fcurves\u002Fp384"," entry exports:",[524,525,526,538,545,555],"ul",{},[527,528,529,465,532,481,535],"li",{},[109,530,531],{},"addPoints",[109,533,534],{},"subtractPoints",[109,536,537],{},"negatePoint",[527,539,540,481,543],{},[109,541,542],{},"multiplyPoint",[109,544,147],{},[527,546,547,465,550,481,552],{},[109,548,549],{},"liftX",[109,551,166],{},[109,553,554],{},"convertPoint",[527,556,557,465,559,481,562],{},[109,558,207],{},[109,560,561],{},"p384",[109,563,564],{},"INVALID_POINT",[91,566,567,568,570],{},"These are the same export names as P-256. The ",[109,569,561],{}," export holds the domain parameters. Multiplication accepts scalars from 1 to n - 1. Pass a bigint or hex with at most 96 digits.",[91,572,573,574,576,577,100],{},"There's no signing, key recovery or scalar math. Need more room? ",[98,575,60],{"href":61}," takes 66 bytes a number. Same width, other curve? That's ",[98,578,68],{"href":69},[86,580,582],{"id":581},"written-from-the-specs","Written from the specs",[91,584,585,586,465,588,465,590,465,592,481,594,596],{},"P-384 shares its SEC 1 code with P-256, ",[98,587,60],{"href":61},[98,589,64],{"href":65},[98,591,68],{"href":69},[98,593,72],{"href":73},[98,595,40],{"href":41},". The shared code gets its widths from the curve. Seven curves, one implementation, no copied module. That's the right way to add a curve.",[91,598,599],{},"Hex lengths, the comb and the digest cut follow those widths. The math doesn't change, only the ruler does. Multiplication walks 96 digits on P-384. It walks 64 on the 32-byte curves. The P-384 verification table has 96 rows of 15 points. Messages swap the curve's name and widths.",[91,601,602],{},"Addition and doubling use algorithms 4 and 6 from Renes, Costello and Batina (2016). They're the same a = -3 formulas as P-256. The formulas are complete. Infinity and doubling need no branch. Square roots take one power because p is 3 mod 4.",[91,604,605,606,609],{},"Multiplication takes the same steps for every scalar. ",[109,607,608],{},"test\u002Fp384.test.ts"," times 1 against n - 1. JavaScript bigints promise nothing about time. Keep real money away.",[91,611,612,613,616],{},"Verification reads G from a faster table. Its scalars are public. In a local run, G multiplication took about 1.4 ms. Another point took about 3.5 ms. Verification took about 3.6 ms. ",[109,614,615],{},"@noble\u002Fcurves"," 2.4.0 took about 5.5 ms on the same signatures.",[91,618,619],{},"The tests cover all 280 Wycheproof ECDSA P-384 SHA-384 vectors in P1363 form. That's r followed by s. They also check RFC 6979 appendix A.2.6 signatures. Those cover SHA-256, SHA-384 and SHA-512 for \"sample\" and \"test\".",[91,621,622,623,625],{},"Multiples of G are frozen from ",[109,624,615],{}," 2.4.0. OpenSSL agreed on every one when they were frozen. In a local run, noble agreed on 300 random cases and 50 signatures.",[627,628,629],"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":107,"searchDepth":136,"depth":136,"links":631},[632,633,638,639],{"id":88,"depth":136,"text":89},{"id":200,"depth":136,"text":201,"children":634},[635,636,637],{"id":358,"depth":143,"text":359},{"id":372,"depth":143,"text":373},{"id":405,"depth":143,"text":406},{"id":514,"depth":136,"text":515},{"id":581,"depth":136,"text":582},"P-384 point math and ECDSA verification for ES384 and certificates","md",null,{"icon":644},"i-lucide-shield-check",{"title":646,"description":640},"P-384 ECDSA verification and SEC1 points in TypeScript","fY75T0yokrpV5rqTVYaiCmuMNFtSZ2c2nmK1ZY3GgvM",[649,651],{"title":52,"path":53,"stem":54,"description":650,"children":-1},"P-256 point math and ECDSA verification for passkeys and ES256",{"title":60,"path":61,"stem":62,"description":652,"children":-1},"P-521 point math and ECDSA verification for ES512 and certificates",1793795813649]