1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[2619],{60643(e,r,s){s.r(r),s.d(r,{assets:()=>d,contentTitle:()=>c,default:()=>p,frontMatter:()=>o,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"libraries/standard_library/cryptographic_primitives/signatures","title":"Signatures","description":"Learn about signature verification in Noir, including the standard library\'s ECDSA verification over the secp256k1 and secp256r1 curves and signature libraries maintained outside of it","source":"@site/versioned_docs/version-v1.0.0-rc.0/libraries/standard_library/cryptographic_primitives/signatures.mdx","sourceDirName":"libraries/standard_library/cryptographic_primitives","slug":"/libraries/standard_library/cryptographic_primitives/signatures","permalink":"/docs/v1.0.0-rc.0/libraries/standard_library/cryptographic_primitives/signatures","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.0/libraries/standard_library/cryptographic_primitives/signatures.mdx","tags":[],"version":"v1.0.0-rc.0","frontMatter":{"title":"Signatures","description":"Learn about signature verification in Noir, including the standard library\'s ECDSA verification over the secp256k1 and secp256r1 curves and signature libraries maintained outside of it","keywords":["cryptographic primitives","Noir project","signatures","ecdsa","secp256k1","
1secp256r1","eddsa","schnorr","rsa"]},"sidebar":"sidebar","previous":{"title":"Hash methods","permalink":"/docs/v1.0.0-rc.0/libraries/standard_library/cryptographic_primitives/hashes"},"next":{"title":"fmtstr","permalink":"/docs/v1.0.0-rc.0/libraries/standard_library/fmtstr"}}');var n=s(74848),a=s(28453),t=s(8037);const o={title:"Signatures",description:"Learn about signature verification in Noir, including the standard library's ECDSA verification over the secp256k1 and secp256r1 curves and signature libraries maintained outside of it",keywords:["cryptographic primitives","Noir project","signatures","ecdsa","secp256k1","secp256r1","eddsa","schnorr","rsa"]},c=void 0,d={},l=[{value:"ecdsa_secp256k1::verify_signature",id:"ecdsa_secp256k1verify_signature",level:2},{value:"ecdsa_secp256r1::verify_signature",id:"ecdsa_secp256r1verify_signature",level:2}];function u(e){const r={a:"a",admonition:"admonition",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.admonition,{type:"tip",children:(0,n.jsxs)(r.p,{children:["Many signature schemes are maintained as independent libraries outside of the standard library (e.g. EdDSA, RSA, Schnorr). You can find the complete list in Awesome Noir's ",(0,n.jsx)(r.a,{href:"https://github.com/noir-lang/awesome-noir?tab=readme-ov-file#signatures",children:"Signatures section"}),"."]})}),"\n",(0,n.jsx)(r.h2,{id:"ecdsa_secp256k1verify_signature",children:"ecdsa_secp256k1::verify_signature"}),"\n",(0,n.jsx)(r.p,{children:"Verifier for ECDSA Secp256k1 signatures."}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-rust",metastring:'title="ecdsa_secp256k1" showLineNumbers ',children:"/// Verifies a ECDSA signature over the secp256k1 curve.\n/// - inputs:\n/// - x coordinate of public key as 32 bytes\n/// - y coordinate of public key as 32 bytes\n/// - the signature, as a 64 bytes array\n/// The signature internally will be represented as `(r, s)`,\n/// where `r` and `s` are fixed-sized big endian scalar values.\n/// As the `secp256k1` has a 256-bit modulus, we have a 64 byte signature\n/// while `r` and `s` will both be 32 bytes.\n/// We expect `s` to be normalized. This means given the curve's order,\n/// `s` should be less than or equal to `order / 2`.\n/// This is done to prevent malleability.\n/// For more context regarding malleability you can reference BIP 0062.\n/// - the hash of the message, as a vector of bytes\n/// - output: false for failure and true for success\npub fn verify_signature(\n public_key_x: [u8; 32],\n public_key_y: [u8; 32],\n signature: [u8; 64],\n message_hash: [u8; 32],\n) -> bool\n"})}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsx)("sup",{children:(0,n.jsx)("sub",{children:(0,n.jsx)("a",{href:"https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ecdsa_secp256k1.nr#L1-L23",target:"_blank",rel:"noopener noreferrer",children:"Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L1-L23"})})}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["Returns ",(0,n.jsx)(r.code,{children:"false"})," for invalid inputs (zero ",(0,n.jsx)(r.code,{children:"r"})," or ",(0,n.jsx)(r.code,{children:"s"}),", not normalized, public key not on the curve)."]}),"\n",(0,n.jsx)(r.p,{children:"example:"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-rust",children:"fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) {\n let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message);\n assert(valid_signature);\n}\n"})}),"\n",(0,n.jsx)(t.A,{to:"../black_box_fns"}),"\n",(0,n.jsx)(r.h2,{id:"ecdsa_secp256r1verify_signature",children:"ecdsa_secp256r1::verify_signature"}),"\n",(0,n.jsx)(r.p,{children:"Verifier for ECDSA Secp256r1 signatures."}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-rust",metastring:'title="ecdsa_secp256r1" showLineNumbers ',children:"/// Verifies a ECDSA signature over the secp256r1 curve.\n/// - input
1s:\n/// - x coordinate of public key as 32 bytes\n/// - y coordinate of public key as 32 bytes\n/// - the signature, as a 64 bytes array\n/// The signature internally will be represented as `(r, s)`,\n/// where `r` and `s` are fixed-sized big endian scalar values.\n/// As the `secp256r1` has a 256-bit modulus, we have a 64 byte signature\n/// while `r` and `s` will both be 32 bytes.\n/// We expect `s` to be normalized. This means given the curve's order,\n/// `s` should be less than or equal to `order / 2`.\n/// This is done to prevent malleability.\n/// For more context regarding malleability you can reference BIP 0062.\n/// - the hash of the message, as a vector of bytes\n/// - output: false for failure and true for success\npub fn verify_signature(\n public_key_x: [u8; 32],\n public_key_y: [u8; 32],\n signature: [u8; 64],\n message_hash: [u8; 32],\n) -> bool\n"})}),"\n",(0,n.jsxs)(r.blockquote,{children:["\n",(0,n.jsx)("sup",{children:(0,n.jsx)("sub",{children:(0,n.jsx)("a",{href:"https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ecdsa_secp256r1.nr#L2-L24",target:"_blank",rel:"noopener noreferrer",children:"Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L24"})})}),"\n"]}),"\n",(0,n.jsxs)(r.p,{children:["Returns ",(0,n.jsx)(r.code,{children:"false"})," for invalid inputs (zero ",(0,n.jsx)(r.code,{children:"r"})," or ",(0,n.jsx)(r.code,{children:"s"}),", not normalized, public key not on the curve)."]}),"\n",(0,n.jsx)(r.p,{children:"example:"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-rust",children:"fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) {\n let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message);\n assert(valid_signature);\n}\n"})}),"\n",(0,n.jsx)(t.A,{to:"../black_box_fns"})]})}function p(e={}){const{wrapper:r}={...(0,a.R)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8037(e,r,s){s.d(r,{A:()=>a});var i=s(28774),n=s(74848);function a({to:e}){return(0,n.jsx)("div",{children:(0,n.jsxs)("p",{children:["This is a black box function. Read ",(0,n.jsx)(i.A,{to:e,children:"this section"})," to learn more about black box functions in Noir."]})})}},28453(e,r,s){s.d(r,{R:()=>t,x:()=>o});var i=s(96540);const n={},a=i.createContext(n);function t(e){const r=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function o(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:t(e.components),i.createElement(a.Provider,{value:r},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.