[{"data":1,"prerenderedAt":4692},["ShallowReactive",2],{"/knowledge-base/crypto":3,"/knowledge-base/crypto-surround":4683},{"id":4,"title":5,"body":6,"category":4664,"contentType":4665,"date":4666,"description":4667,"extension":4668,"head":4669,"image":4670,"meta":4671,"navigation":251,"ogImage":4669,"path":4672,"readingTime":4673,"robots":4669,"schemaOrg":4669,"seo":4674,"sitemap":4675,"stem":4676,"tags":4677,"__hash__":4682},"knowledgeBase/knowledge-base/crypto.md","Key Concepts in crypto",{"type":7,"value":8,"toc":4620},"minimark",[9,18,23,30,79,83,98,105,141,147,154,181,185,209,212,216,220,223,498,503,531,535,541,835,844,876,884,904,906,914,917,936,940,1149,1154,1186,1190,1195,1238,1242,1301,1305,1316,1360,1364,1634,1640,1645,1647,1654,1657,1805,1820,1822,1832,1838,1898,1903,1957,1965,1971,2015,2019,2056,2080,2082,2086,2094,2100,2105,2207,2221,2248,2254,2258,2359,2370,2375,2377,2381,2387,2396,2410,2415,2583,2592,2606,2612,2624,2629,2819,2829,2840,2960,2962,2966,2969,2992,3435,3462,3464,3468,3474,3505,3509,3595,3597,3601,3773,3775,3779,3978,3980,3984,3987,3990,4496,4499,4542,4545,4549,4598,4616],[10,11,13,14],"h2",{"id":12},"_1-key-concepts-in-crypto","1. Key Concepts in ",[15,16,17],"code",{},"crypto",[19,20,22],"h3",{"id":21},"keyobject","KeyObject",[24,25,26,27,29],"p",{},"Internally, Node represents public keys, private keys, and symmetric keys as ",[15,28,22],{}," instances.",[31,32,33,44],"ul",{},[34,35,36,37,39,40,43],"li",{},"A ",[15,38,22],{}," wraps the raw key material in a safe, memory-managed way (it’s not just a plain ",[15,41,42],{},"Buffer",").",[34,45,46,47,49,50],{},"You obtain a ",[15,48,22],{}," by:",[31,51,52,63,73],{},[34,53,54,55,58,59,62],{},"Generating a new pair (e.g. ",[15,56,57],{},"generateKeyPair","/",[15,60,61],{},"generateKeyPairSync","),",[34,64,65,66,69,70,62],{},"Importing existing PEM/DER/JWK data (via ",[15,67,68],{},"createPrivateKey"," / ",[15,71,72],{},"createPublicKey",[34,74,75,76,43],{},"Exporting to PEM/DER/JWK (via ",[15,77,78],{},"keyObject.export()",[19,80,82],{"id":81},"signing-verification","Signing & Verification",[31,84,85,92],{},[34,86,87,91],{},[88,89,90],"strong",{},"Signing",": You prove “I (holder of the private key) authorize or attest to this exact message.”",[34,93,94,97],{},[88,95,96],{},"Verification",": Anyone with the matching public key can check that signature→message mapping.",[24,99,100,101,104],{},"In Node, you use ",[15,102,103],{},"crypto.createSign(algorithm)"," to build a “Sign” instance, feed it data, then",[106,107,112],"pre",{"className":108,"code":109,"language":110,"meta":111,"style":111},"language-js shiki shiki-themes github-light github-dark github-dark","const signature = sign.sign(privateKey);\n","js","",[15,113,114],{"__ignoreMap":111},[115,116,119,123,127,130,134,138],"span",{"class":117,"line":118},"line",1,[115,120,122],{"class":121},"so5gQ","const",[115,124,126],{"class":125},"suiK_"," signature",[115,128,129],{"class":121}," =",[115,131,133],{"class":132},"slsVL"," sign.",[115,135,137],{"class":136},"shcOC","sign",[115,139,140],{"class":132},"(privateKey);\n",[24,142,143,144,146],{},"which returns a ",[15,145,42],{},".",[24,148,149,150,153],{},"To verify, you use ",[15,151,152],{},"crypto.createVerify(algorithm)",", feed it the same data, then:",[106,155,157],{"className":108,"code":156,"language":110,"meta":111,"style":111},"const isValid = verify.verify(publicKey, signature); // boolean\n",[15,158,159],{"__ignoreMap":111},[115,160,161,163,166,168,171,174,177],{"class":117,"line":118},[115,162,122],{"class":121},[115,164,165],{"class":125}," isValid",[115,167,129],{"class":121},[115,169,170],{"class":132}," verify.",[115,172,173],{"class":136},"verify",[115,175,176],{"class":132},"(publicKey, signature); ",[115,178,180],{"class":179},"sCsY4","// boolean\n",[19,182,184],{"id":183},"asymmetric-vs-symmetric","Asymmetric vs Symmetric",[31,186,187,193],{},[34,188,189,192],{},[88,190,191],{},"Asymmetric algorithms"," (RSA, ECDSA, Ed25519, etc.) rely on a private/public key pair. The private key signs, the public key verifies.",[34,194,195,198,199,202,203,205,206,208],{},[88,196,197],{},"Symmetric algorithms"," (e.g. HMAC) use a shared secret key on both ends; Node handles HMAC via ",[15,200,201],{},"crypto.createHmac()"," and that key is just a ",[15,204,42],{}," or ",[15,207,22],{}," too.",[210,211],"hr",{},[10,213,215],{"id":214},"_2-creating-or-importing-keys","2. Creating or Importing Keys",[19,217,219],{"id":218},"_21-generating-a-new-key-pair","2.1 Generating a New Key Pair",[24,221,222],{},"If you need to generate a fresh RSA or EC key pair for signing/verification:",[106,224,226],{"className":108,"code":225,"language":110,"meta":111,"style":111},"import { generateKeyPairSync } from 'crypto';\n\n// Example: Generate an RSA key pair for signing (2048-bit, PKCS#1-style)\nconst { publicKey, privateKey } = generateKeyPairSync('rsa', {\n  modulusLength: 2048,\n  publicKeyEncoding: {\n    type: 'pkcs1',            // “pkcs1” or “spki” for public\n    format: 'pem'\n  },\n  privateKeyEncoding: {\n    type: 'pkcs1',            // “pkcs1” or “pkcs8” for private\n    format: 'pem',\n    cipher: 'aes-256-cbc',    // (optional) encrypt the PEM with a passphrase\n    passphrase: 'your-strong-passphrase'\n  }\n});\n\n// `publicKey` and `privateKey` here are PEM-encoded strings.\n// If you need KeyObject instances, you can immediately turn them into KeyObjects:\nimport { createPrivateKey, createPublicKey } from 'crypto';\nconst privKeyObject = createPrivateKey({\n  key: privateKey,\n  format: 'pem',\n  passphrase: 'your-strong-passphrase'\n});\nconst pubKeyObject = createPublicKey(publicKey);\n",[15,227,228,246,253,259,294,306,312,327,336,342,348,360,370,385,394,400,406,411,417,423,437,453,459,469,477,482],{"__ignoreMap":111},[115,229,230,233,236,239,243],{"class":117,"line":118},[115,231,232],{"class":121},"import",[115,234,235],{"class":132}," { generateKeyPairSync } ",[115,237,238],{"class":121},"from",[115,240,242],{"class":241},"sfrk1"," 'crypto'",[115,244,245],{"class":132},";\n",[115,247,249],{"class":117,"line":248},2,[115,250,252],{"emptyLinePlaceholder":251},true,"\n",[115,254,256],{"class":117,"line":255},3,[115,257,258],{"class":179},"// Example: Generate an RSA key pair for signing (2048-bit, PKCS#1-style)\n",[115,260,262,264,267,270,273,276,279,282,285,288,291],{"class":117,"line":261},4,[115,263,122],{"class":121},[115,265,266],{"class":132}," { ",[115,268,269],{"class":125},"publicKey",[115,271,272],{"class":132},", ",[115,274,275],{"class":125},"privateKey",[115,277,278],{"class":132}," } ",[115,280,281],{"class":121},"=",[115,283,284],{"class":136}," generateKeyPairSync",[115,286,287],{"class":132},"(",[115,289,290],{"class":241},"'rsa'",[115,292,293],{"class":132},", {\n",[115,295,297,300,303],{"class":117,"line":296},5,[115,298,299],{"class":132},"  modulusLength: ",[115,301,302],{"class":125},"2048",[115,304,305],{"class":132},",\n",[115,307,309],{"class":117,"line":308},6,[115,310,311],{"class":132},"  publicKeyEncoding: {\n",[115,313,315,318,321,324],{"class":117,"line":314},7,[115,316,317],{"class":132},"    type: ",[115,319,320],{"class":241},"'pkcs1'",[115,322,323],{"class":132},",            ",[115,325,326],{"class":179},"// “pkcs1” or “spki” for public\n",[115,328,330,333],{"class":117,"line":329},8,[115,331,332],{"class":132},"    format: ",[115,334,335],{"class":241},"'pem'\n",[115,337,339],{"class":117,"line":338},9,[115,340,341],{"class":132},"  },\n",[115,343,345],{"class":117,"line":344},10,[115,346,347],{"class":132},"  privateKeyEncoding: {\n",[115,349,351,353,355,357],{"class":117,"line":350},11,[115,352,317],{"class":132},[115,354,320],{"class":241},[115,356,323],{"class":132},[115,358,359],{"class":179},"// “pkcs1” or “pkcs8” for private\n",[115,361,363,365,368],{"class":117,"line":362},12,[115,364,332],{"class":132},[115,366,367],{"class":241},"'pem'",[115,369,305],{"class":132},[115,371,373,376,379,382],{"class":117,"line":372},13,[115,374,375],{"class":132},"    cipher: ",[115,377,378],{"class":241},"'aes-256-cbc'",[115,380,381],{"class":132},",    ",[115,383,384],{"class":179},"// (optional) encrypt the PEM with a passphrase\n",[115,386,388,391],{"class":117,"line":387},14,[115,389,390],{"class":132},"    passphrase: ",[115,392,393],{"class":241},"'your-strong-passphrase'\n",[115,395,397],{"class":117,"line":396},15,[115,398,399],{"class":132},"  }\n",[115,401,403],{"class":117,"line":402},16,[115,404,405],{"class":132},"});\n",[115,407,409],{"class":117,"line":408},17,[115,410,252],{"emptyLinePlaceholder":251},[115,412,414],{"class":117,"line":413},18,[115,415,416],{"class":179},"// `publicKey` and `privateKey` here are PEM-encoded strings.\n",[115,418,420],{"class":117,"line":419},19,[115,421,422],{"class":179},"// If you need KeyObject instances, you can immediately turn them into KeyObjects:\n",[115,424,426,428,431,433,435],{"class":117,"line":425},20,[115,427,232],{"class":121},[115,429,430],{"class":132}," { createPrivateKey, createPublicKey } ",[115,432,238],{"class":121},[115,434,242],{"class":241},[115,436,245],{"class":132},[115,438,440,442,445,447,450],{"class":117,"line":439},21,[115,441,122],{"class":121},[115,443,444],{"class":125}," privKeyObject",[115,446,129],{"class":121},[115,448,449],{"class":136}," createPrivateKey",[115,451,452],{"class":132},"({\n",[115,454,456],{"class":117,"line":455},22,[115,457,458],{"class":132},"  key: privateKey,\n",[115,460,462,465,467],{"class":117,"line":461},23,[115,463,464],{"class":132},"  format: ",[115,466,367],{"class":241},[115,468,305],{"class":132},[115,470,472,475],{"class":117,"line":471},24,[115,473,474],{"class":132},"  passphrase: ",[115,476,393],{"class":241},[115,478,480],{"class":117,"line":479},25,[115,481,405],{"class":132},[115,483,485,487,490,492,495],{"class":117,"line":484},26,[115,486,122],{"class":121},[115,488,489],{"class":125}," pubKeyObject",[115,491,129],{"class":121},[115,493,494],{"class":136}," createPublicKey",[115,496,497],{"class":132},"(publicKey);\n",[24,499,500],{},[88,501,502],{},"Best practice:",[31,504,505,521,524],{},[34,506,507,508,272,511,514,515,205,518,43],{},"Use at least 2048-bit RSA or a 256-bit curve (e.g. ",[15,509,510],{},"rsa",[15,512,513],{},"ec"," with ",[15,516,517],{},"namedCurve: 'secp256k1'",[15,519,520],{},"'prime256v1'",[34,522,523],{},"Protect your private key PEM with a strong passphrase if writing it to disk.",[34,525,526,527,530],{},"Use ",[15,528,529],{},"generateKeyPairSync()"," only at startup or in build scripts—avoid calling it in a hot request/response path, since key generation can be CPU-intensive.",[19,532,534],{"id":533},"_22-importing-an-existing-key-pemderjwk","2.2 Importing an Existing Key (PEM/DER/JWK)",[24,536,537,538,540],{},"Often you already have a PEM‐formatted key on disk (or in an environment variable). To use it in Node, wrap it in a ",[15,539,22],{}," via:",[106,542,544],{"className":108,"code":543,"language":110,"meta":111,"style":111},"import { createPrivateKey, createPublicKey } from 'crypto';\n\n// 1. From a PEM string (e.g. loaded from process.env or fs.readFileSync):\nconst privPem = `-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIE6TAb... (base64) ...  \n-----END ENCRYPTED PRIVATE KEY-----`;\n\nconst privateKeyObject = createPrivateKey({\n  key: privPem,\n  format: 'pem',\n  passphrase: 'your-passphrase-if-encrypted'\n});\n\n// 2. From a DER buffer:\nimport fs from 'fs';\nconst derBuffer = fs.readFileSync('./myKey.der');\nconst publicKeyObject = createPublicKey({\n  key: derBuffer,\n  format: 'der',\n  type: 'spki'       // or \"pkcs1\" if your DER is in PKCS#1 format\n});\n\n// 3. From a JWK (JSON Web Key) object:\nconst jwk = {\n  kty: 'RSA',\n  n: '0vx7...bL8',\n  e: 'AQAB',\n  d: 'X4cT...DZu6__',\n  // plus p, q, dp, dq, qi if it's a private JWK\n};\nconst importedPrivateKey = createPrivateKey({ key: jwk, format: 'jwk' });\nconst importedPublicKey  = createPublicKey({ key: jwk, format: 'jwk' });\n",[15,545,546,558,562,567,579,584,591,595,608,613,621,628,632,636,641,655,678,691,696,705,716,720,724,729,741,751,761,772,783,789,795,816],{"__ignoreMap":111},[115,547,548,550,552,554,556],{"class":117,"line":118},[115,549,232],{"class":121},[115,551,430],{"class":132},[115,553,238],{"class":121},[115,555,242],{"class":241},[115,557,245],{"class":132},[115,559,560],{"class":117,"line":248},[115,561,252],{"emptyLinePlaceholder":251},[115,563,564],{"class":117,"line":255},[115,565,566],{"class":179},"// 1. From a PEM string (e.g. loaded from process.env or fs.readFileSync):\n",[115,568,569,571,574,576],{"class":117,"line":261},[115,570,122],{"class":121},[115,572,573],{"class":125}," privPem",[115,575,129],{"class":121},[115,577,578],{"class":241}," `-----BEGIN ENCRYPTED PRIVATE KEY-----\n",[115,580,581],{"class":117,"line":296},[115,582,583],{"class":241},"MIIE6TAb... (base64) ...  \n",[115,585,586,589],{"class":117,"line":308},[115,587,588],{"class":241},"-----END ENCRYPTED PRIVATE KEY-----`",[115,590,245],{"class":132},[115,592,593],{"class":117,"line":314},[115,594,252],{"emptyLinePlaceholder":251},[115,596,597,599,602,604,606],{"class":117,"line":329},[115,598,122],{"class":121},[115,600,601],{"class":125}," privateKeyObject",[115,603,129],{"class":121},[115,605,449],{"class":136},[115,607,452],{"class":132},[115,609,610],{"class":117,"line":338},[115,611,612],{"class":132},"  key: privPem,\n",[115,614,615,617,619],{"class":117,"line":344},[115,616,464],{"class":132},[115,618,367],{"class":241},[115,620,305],{"class":132},[115,622,623,625],{"class":117,"line":350},[115,624,474],{"class":132},[115,626,627],{"class":241},"'your-passphrase-if-encrypted'\n",[115,629,630],{"class":117,"line":362},[115,631,405],{"class":132},[115,633,634],{"class":117,"line":372},[115,635,252],{"emptyLinePlaceholder":251},[115,637,638],{"class":117,"line":387},[115,639,640],{"class":179},"// 2. From a DER buffer:\n",[115,642,643,645,648,650,653],{"class":117,"line":396},[115,644,232],{"class":121},[115,646,647],{"class":132}," fs ",[115,649,238],{"class":121},[115,651,652],{"class":241}," 'fs'",[115,654,245],{"class":132},[115,656,657,659,662,664,667,670,672,675],{"class":117,"line":402},[115,658,122],{"class":121},[115,660,661],{"class":125}," derBuffer",[115,663,129],{"class":121},[115,665,666],{"class":132}," fs.",[115,668,669],{"class":136},"readFileSync",[115,671,287],{"class":132},[115,673,674],{"class":241},"'./myKey.der'",[115,676,677],{"class":132},");\n",[115,679,680,682,685,687,689],{"class":117,"line":408},[115,681,122],{"class":121},[115,683,684],{"class":125}," publicKeyObject",[115,686,129],{"class":121},[115,688,494],{"class":136},[115,690,452],{"class":132},[115,692,693],{"class":117,"line":413},[115,694,695],{"class":132},"  key: derBuffer,\n",[115,697,698,700,703],{"class":117,"line":419},[115,699,464],{"class":132},[115,701,702],{"class":241},"'der'",[115,704,305],{"class":132},[115,706,707,710,713],{"class":117,"line":425},[115,708,709],{"class":132},"  type: ",[115,711,712],{"class":241},"'spki'",[115,714,715],{"class":179},"       // or \"pkcs1\" if your DER is in PKCS#1 format\n",[115,717,718],{"class":117,"line":439},[115,719,405],{"class":132},[115,721,722],{"class":117,"line":455},[115,723,252],{"emptyLinePlaceholder":251},[115,725,726],{"class":117,"line":461},[115,727,728],{"class":179},"// 3. From a JWK (JSON Web Key) object:\n",[115,730,731,733,736,738],{"class":117,"line":471},[115,732,122],{"class":121},[115,734,735],{"class":125}," jwk",[115,737,129],{"class":121},[115,739,740],{"class":132}," {\n",[115,742,743,746,749],{"class":117,"line":479},[115,744,745],{"class":132},"  kty: ",[115,747,748],{"class":241},"'RSA'",[115,750,305],{"class":132},[115,752,753,756,759],{"class":117,"line":484},[115,754,755],{"class":132},"  n: ",[115,757,758],{"class":241},"'0vx7...bL8'",[115,760,305],{"class":132},[115,762,764,767,770],{"class":117,"line":763},27,[115,765,766],{"class":132},"  e: ",[115,768,769],{"class":241},"'AQAB'",[115,771,305],{"class":132},[115,773,775,778,781],{"class":117,"line":774},28,[115,776,777],{"class":132},"  d: ",[115,779,780],{"class":241},"'X4cT...DZu6__'",[115,782,305],{"class":132},[115,784,786],{"class":117,"line":785},29,[115,787,788],{"class":179},"  // plus p, q, dp, dq, qi if it's a private JWK\n",[115,790,792],{"class":117,"line":791},30,[115,793,794],{"class":132},"};\n",[115,796,798,800,803,805,807,810,813],{"class":117,"line":797},31,[115,799,122],{"class":121},[115,801,802],{"class":125}," importedPrivateKey",[115,804,129],{"class":121},[115,806,449],{"class":136},[115,808,809],{"class":132},"({ key: jwk, format: ",[115,811,812],{"class":241},"'jwk'",[115,814,815],{"class":132}," });\n",[115,817,819,821,824,827,829,831,833],{"class":117,"line":818},32,[115,820,122],{"class":121},[115,822,823],{"class":125}," importedPublicKey",[115,825,826],{"class":121},"  =",[115,828,494],{"class":136},[115,830,809],{"class":132},[115,832,812],{"class":241},[115,834,815],{"class":132},[24,836,837],{},[88,838,839,840,843],{},"Parameters for ",[15,841,842],{},"createPrivateKey()",":",[31,845,846,856,864,870],{},[34,847,848,851,852,855],{},[15,849,850],{},"key",": ",[15,853,854],{},"Buffer | string | object"," (e.g. JWK)",[34,857,858,851,861],{},[15,859,860],{},"format",[15,862,863],{},"'pem' | 'der' | 'jwk'",[34,865,866,867,146],{},"If the PEM is encrypted (PKCS#8 or PKCS#1), supply ",[15,868,869],{},"passphrase: string | Buffer",[34,871,872,873,146],{},"If using DER, also specify ",[15,874,875],{},"type: 'pkcs1' | 'pkcs8'",[24,877,878,883],{},[88,879,839,880],{},[15,881,882],{},"createPublicKey()"," are similar, but for public PEM/DER/JWK.",[24,885,886,887,889,890,205,893,896,897,899,900,903],{},"Once you have a ",[15,888,22],{},", you can use it directly in ",[15,891,892],{},"crypto.sign(...)",[15,894,895],{},"createSign().sign(...)",". A ",[15,898,22],{}," is safer than passing around raw ",[15,901,902],{},"Buffers"," or strings.",[210,905],{},[10,907,909,910,913],{"id":908},"_3-signing-data-createsign","3. Signing Data (",[15,911,912],{},"createSign",")",[24,915,916],{},"When you want to produce a digital signature of some data (e.g. JSON payload, message, file hash), you typically:",[918,919,920,927,930],"ol",{},[34,921,922,923,926],{},"Hash the data (internally, ",[15,924,925],{},"Sign"," does it for you).",[34,928,929],{},"Sign the hash with your private key.",[34,931,932,933,935],{},"Return a signature ",[15,934,42],{}," (or base64/hex‐encoded string).",[19,937,939],{"id":938},"_31-basic-flow","3.1 Basic Flow",[106,941,943],{"className":108,"code":942,"language":110,"meta":111,"style":111},"import { createSign, constants } from 'crypto';\n\nconst data = Buffer.from('The quick brown fox'); // or a string\n\n// 1. Choose an algorithm. Common choices: 'RSA-SHA256', 'RSA-SHA512', 'SHA256', 'SHA512', 'ecdsa-with-SHA256', etc.\nconst sign = createSign('RSA-SHA256');\n\n// 2. Feed the data into the Sign object\nsign.update(data);\nsign.end(); // mark EOF\n\n// 3. Produce the signature. Pass either:\n//    • a `KeyObject` (recommended), OR\n//    • a PEM string (or deriving from it, e.g. passphrase if encrypted)\nconst signature = sign.sign({\n  key: privateKeyObject,   // e.g. from createPrivateKey() or generateKeyPairSync()\n  padding: constants.RSA_PKCS1_PSS_PADDING,    // If using RSA-PSS\n  saltLength: constants.RSA_PSS_SALTLEN_DIGEST // Recommended for PSS\n});\n// `signature` is a Buffer. You can `.toString('base64')` if needed for transport.\nconsole.log('Signature (base64):', signature.toString('base64'));\n",[15,944,945,958,962,987,991,996,1015,1019,1024,1035,1048,1052,1057,1062,1067,1081,1089,1102,1113,1117,1122],{"__ignoreMap":111},[115,946,947,949,952,954,956],{"class":117,"line":118},[115,948,232],{"class":121},[115,950,951],{"class":132}," { createSign, constants } ",[115,953,238],{"class":121},[115,955,242],{"class":241},[115,957,245],{"class":132},[115,959,960],{"class":117,"line":248},[115,961,252],{"emptyLinePlaceholder":251},[115,963,964,966,969,971,974,976,978,981,984],{"class":117,"line":255},[115,965,122],{"class":121},[115,967,968],{"class":125}," data",[115,970,129],{"class":121},[115,972,973],{"class":132}," Buffer.",[115,975,238],{"class":136},[115,977,287],{"class":132},[115,979,980],{"class":241},"'The quick brown fox'",[115,982,983],{"class":132},"); ",[115,985,986],{"class":179},"// or a string\n",[115,988,989],{"class":117,"line":261},[115,990,252],{"emptyLinePlaceholder":251},[115,992,993],{"class":117,"line":296},[115,994,995],{"class":179},"// 1. Choose an algorithm. Common choices: 'RSA-SHA256', 'RSA-SHA512', 'SHA256', 'SHA512', 'ecdsa-with-SHA256', etc.\n",[115,997,998,1000,1003,1005,1008,1010,1013],{"class":117,"line":308},[115,999,122],{"class":121},[115,1001,1002],{"class":125}," sign",[115,1004,129],{"class":121},[115,1006,1007],{"class":136}," createSign",[115,1009,287],{"class":132},[115,1011,1012],{"class":241},"'RSA-SHA256'",[115,1014,677],{"class":132},[115,1016,1017],{"class":117,"line":314},[115,1018,252],{"emptyLinePlaceholder":251},[115,1020,1021],{"class":117,"line":329},[115,1022,1023],{"class":179},"// 2. Feed the data into the Sign object\n",[115,1025,1026,1029,1032],{"class":117,"line":338},[115,1027,1028],{"class":132},"sign.",[115,1030,1031],{"class":136},"update",[115,1033,1034],{"class":132},"(data);\n",[115,1036,1037,1039,1042,1045],{"class":117,"line":344},[115,1038,1028],{"class":132},[115,1040,1041],{"class":136},"end",[115,1043,1044],{"class":132},"(); ",[115,1046,1047],{"class":179},"// mark EOF\n",[115,1049,1050],{"class":117,"line":350},[115,1051,252],{"emptyLinePlaceholder":251},[115,1053,1054],{"class":117,"line":362},[115,1055,1056],{"class":179},"// 3. Produce the signature. Pass either:\n",[115,1058,1059],{"class":117,"line":372},[115,1060,1061],{"class":179},"//    • a `KeyObject` (recommended), OR\n",[115,1063,1064],{"class":117,"line":387},[115,1065,1066],{"class":179},"//    • a PEM string (or deriving from it, e.g. passphrase if encrypted)\n",[115,1068,1069,1071,1073,1075,1077,1079],{"class":117,"line":396},[115,1070,122],{"class":121},[115,1072,126],{"class":125},[115,1074,129],{"class":121},[115,1076,133],{"class":132},[115,1078,137],{"class":136},[115,1080,452],{"class":132},[115,1082,1083,1086],{"class":117,"line":402},[115,1084,1085],{"class":132},"  key: privateKeyObject,   ",[115,1087,1088],{"class":179},"// e.g. from createPrivateKey() or generateKeyPairSync()\n",[115,1090,1091,1094,1097,1099],{"class":117,"line":408},[115,1092,1093],{"class":132},"  padding: constants.",[115,1095,1096],{"class":125},"RSA_PKCS1_PSS_PADDING",[115,1098,381],{"class":132},[115,1100,1101],{"class":179},"// If using RSA-PSS\n",[115,1103,1104,1107,1110],{"class":117,"line":413},[115,1105,1106],{"class":132},"  saltLength: constants.",[115,1108,1109],{"class":125},"RSA_PSS_SALTLEN_DIGEST",[115,1111,1112],{"class":179}," // Recommended for PSS\n",[115,1114,1115],{"class":117,"line":419},[115,1116,405],{"class":132},[115,1118,1119],{"class":117,"line":425},[115,1120,1121],{"class":179},"// `signature` is a Buffer. You can `.toString('base64')` if needed for transport.\n",[115,1123,1124,1127,1130,1132,1135,1138,1141,1143,1146],{"class":117,"line":439},[115,1125,1126],{"class":132},"console.",[115,1128,1129],{"class":136},"log",[115,1131,287],{"class":132},[115,1133,1134],{"class":241},"'Signature (base64):'",[115,1136,1137],{"class":132},", signature.",[115,1139,1140],{"class":136},"toString",[115,1142,287],{"class":132},[115,1144,1145],{"class":241},"'base64'",[115,1147,1148],{"class":132},"));\n",[1150,1151,1153],"h4",{"id":1152},"algorithm-string","Algorithm string",[31,1155,1156,1164,1179],{},[34,1157,1158,1159,205,1161,146],{},"For RSA with PKCS#1 v1.5 padding: use ",[15,1160,1012],{},[15,1162,1163],{},"'RSA-SHA512'",[34,1165,1166,1167,1170,1171,1174,1175,1178],{},"For RSA-PSS (recommended for new designs), use ",[15,1168,1169],{},"createSign('sha256')"," (or ",[15,1172,1173],{},"'sha512'","), then in ",[15,1176,1177],{},"sign.sign({ padding: PSS_PADDING, saltLength: ... })"," you explicitly choose PSS.",[34,1180,1181,1182,1185],{},"For ECDSA (e.g. P-256), use ",[15,1183,1184],{},"createSign('SHA256')",". Node outputs a DER‐encoded signature (r || s format) by default.",[1150,1187,1189],{"id":1188},"padding","Padding",[1191,1192,1194],"h5",{"id":1193},"for-rsapss","For RSA‐PSS:",[106,1196,1198],{"className":108,"code":1197,"language":110,"meta":111,"style":111},"const signature = sign.sign({\n  key: privateKeyObject,\n  padding: constants.RSA_PKCS1_PSS_PADDING,\n  saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n});\n",[15,1199,1200,1214,1219,1227,1234],{"__ignoreMap":111},[115,1201,1202,1204,1206,1208,1210,1212],{"class":117,"line":118},[115,1203,122],{"class":121},[115,1205,126],{"class":125},[115,1207,129],{"class":121},[115,1209,133],{"class":132},[115,1211,137],{"class":136},[115,1213,452],{"class":132},[115,1215,1216],{"class":117,"line":248},[115,1217,1218],{"class":132},"  key: privateKeyObject,\n",[115,1220,1221,1223,1225],{"class":117,"line":255},[115,1222,1093],{"class":132},[115,1224,1096],{"class":125},[115,1226,305],{"class":132},[115,1228,1229,1231],{"class":117,"line":261},[115,1230,1106],{"class":132},[115,1232,1233],{"class":125},"RSA_PSS_SALTLEN_DIGEST\n",[115,1235,1236],{"class":117,"line":296},[115,1237,405],{"class":132},[1191,1239,1241],{"id":1240},"for-rsa-pkcs1-v15-legacy-but-still-common","For RSA PKCS#1 v1.5 (legacy, but still common):",[106,1243,1245],{"className":108,"code":1244,"language":110,"meta":111,"style":111},"// no need to specify padding (it defaults to PKCS#1 v1.5):\nconst signature = sign.sign(privateKeyObject);\n// or explicitly:\nconst signature = sign.sign({\n  key: privateKeyObject,\n  padding: constants.RSA_PKCS1_PADDING\n});\n",[15,1246,1247,1252,1267,1272,1286,1290,1297],{"__ignoreMap":111},[115,1248,1249],{"class":117,"line":118},[115,1250,1251],{"class":179},"// no need to specify padding (it defaults to PKCS#1 v1.5):\n",[115,1253,1254,1256,1258,1260,1262,1264],{"class":117,"line":248},[115,1255,122],{"class":121},[115,1257,126],{"class":125},[115,1259,129],{"class":121},[115,1261,133],{"class":132},[115,1263,137],{"class":136},[115,1265,1266],{"class":132},"(privateKeyObject);\n",[115,1268,1269],{"class":117,"line":255},[115,1270,1271],{"class":179},"// or explicitly:\n",[115,1273,1274,1276,1278,1280,1282,1284],{"class":117,"line":261},[115,1275,122],{"class":121},[115,1277,126],{"class":125},[115,1279,129],{"class":121},[115,1281,133],{"class":132},[115,1283,137],{"class":136},[115,1285,452],{"class":132},[115,1287,1288],{"class":117,"line":296},[115,1289,1218],{"class":132},[115,1291,1292,1294],{"class":117,"line":308},[115,1293,1093],{"class":132},[115,1295,1296],{"class":125},"RSA_PKCS1_PADDING\n",[115,1298,1299],{"class":117,"line":314},[115,1300,405],{"class":132},[1150,1302,1304],{"id":1303},"encoding","Encoding",[24,1306,1307,1308,1310,1311,205,1314,843],{},"You can have Node return a ",[15,1309,42],{},", or directly return a string in ",[15,1312,1313],{},"'hex'",[15,1315,1145],{},[106,1317,1319],{"className":108,"code":1318,"language":110,"meta":111,"style":111},"// returning as Base64 string (instead of Buffer)\nconst signatureBase64 = sign.sign({\n  key: privateKeyObject,\n  padding: constants.RSA_PKCS1_PADDING\n}, 'base64');\n",[15,1320,1321,1326,1341,1345,1351],{"__ignoreMap":111},[115,1322,1323],{"class":117,"line":118},[115,1324,1325],{"class":179},"// returning as Base64 string (instead of Buffer)\n",[115,1327,1328,1330,1333,1335,1337,1339],{"class":117,"line":248},[115,1329,122],{"class":121},[115,1331,1332],{"class":125}," signatureBase64",[115,1334,129],{"class":121},[115,1336,133],{"class":132},[115,1338,137],{"class":136},[115,1340,452],{"class":132},[115,1342,1343],{"class":117,"line":255},[115,1344,1218],{"class":132},[115,1346,1347,1349],{"class":117,"line":261},[115,1348,1093],{"class":132},[115,1350,1296],{"class":125},[115,1352,1353,1356,1358],{"class":117,"line":296},[115,1354,1355],{"class":132},"}, ",[115,1357,1145],{"class":241},[115,1359,677],{"class":132},[19,1361,1363],{"id":1362},"_32-example-with-ecdsa-elliptic-curve","3.2 Example with ECDSA (Elliptic Curve)",[106,1365,1367],{"className":108,"code":1366,"language":110,"meta":111,"style":111},"import { generateKeyPairSync, createSign, createPrivateKey, createPublicKey } from 'crypto';\n\n// 1. Generate an EC key pair (prime256v1 / secp256r1 is common)\nconst { publicKey: ecPubPem, privateKey: ecPrivPem } = generateKeyPairSync('ec', {\n  namedCurve: 'prime256v1',\n  publicKeyEncoding:  { type: 'spki', format: 'pem' },\n  privateKeyEncoding: { type: 'pkcs8', format: 'pem' }\n});\n\nconst ecPrivKeyObject = createPrivateKey({ key: ecPrivPem, format: 'pem' });\nconst ecPubKeyObject = createPublicKey(ecPubPem);\n\n// 2. Sign:\nconst payload = Buffer.from(JSON.stringify({ foo: 'bar' }));\nconst sign = createSign('SHA256');\nsign.update(payload);\nsign.end();\n\n// ECDSA uses DER-encoded signature by default (r || s).\nconst signature = sign.sign(ecPrivKeyObject); // Buffer\n\nconsole.log('ECDSA Signature (hex):', signature.toString('hex'));\n",[15,1368,1369,1382,1386,1391,1427,1436,1451,1466,1470,1474,1492,1506,1510,1515,1547,1564,1573,1582,1586,1591,1609,1613],{"__ignoreMap":111},[115,1370,1371,1373,1376,1378,1380],{"class":117,"line":118},[115,1372,232],{"class":121},[115,1374,1375],{"class":132}," { generateKeyPairSync, createSign, createPrivateKey, createPublicKey } ",[115,1377,238],{"class":121},[115,1379,242],{"class":241},[115,1381,245],{"class":132},[115,1383,1384],{"class":117,"line":248},[115,1385,252],{"emptyLinePlaceholder":251},[115,1387,1388],{"class":117,"line":255},[115,1389,1390],{"class":179},"// 1. Generate an EC key pair (prime256v1 / secp256r1 is common)\n",[115,1392,1393,1395,1397,1400,1402,1405,1407,1409,1411,1414,1416,1418,1420,1422,1425],{"class":117,"line":261},[115,1394,122],{"class":121},[115,1396,266],{"class":132},[115,1398,269],{"class":1399},"sQHwn",[115,1401,851],{"class":132},[115,1403,1404],{"class":125},"ecPubPem",[115,1406,272],{"class":132},[115,1408,275],{"class":1399},[115,1410,851],{"class":132},[115,1412,1413],{"class":125},"ecPrivPem",[115,1415,278],{"class":132},[115,1417,281],{"class":121},[115,1419,284],{"class":136},[115,1421,287],{"class":132},[115,1423,1424],{"class":241},"'ec'",[115,1426,293],{"class":132},[115,1428,1429,1432,1434],{"class":117,"line":296},[115,1430,1431],{"class":132},"  namedCurve: ",[115,1433,520],{"class":241},[115,1435,305],{"class":132},[115,1437,1438,1441,1443,1446,1448],{"class":117,"line":308},[115,1439,1440],{"class":132},"  publicKeyEncoding:  { type: ",[115,1442,712],{"class":241},[115,1444,1445],{"class":132},", format: ",[115,1447,367],{"class":241},[115,1449,1450],{"class":132}," },\n",[115,1452,1453,1456,1459,1461,1463],{"class":117,"line":314},[115,1454,1455],{"class":132},"  privateKeyEncoding: { type: ",[115,1457,1458],{"class":241},"'pkcs8'",[115,1460,1445],{"class":132},[115,1462,367],{"class":241},[115,1464,1465],{"class":132}," }\n",[115,1467,1468],{"class":117,"line":329},[115,1469,405],{"class":132},[115,1471,1472],{"class":117,"line":338},[115,1473,252],{"emptyLinePlaceholder":251},[115,1475,1476,1478,1481,1483,1485,1488,1490],{"class":117,"line":344},[115,1477,122],{"class":121},[115,1479,1480],{"class":125}," ecPrivKeyObject",[115,1482,129],{"class":121},[115,1484,449],{"class":136},[115,1486,1487],{"class":132},"({ key: ecPrivPem, format: ",[115,1489,367],{"class":241},[115,1491,815],{"class":132},[115,1493,1494,1496,1499,1501,1503],{"class":117,"line":350},[115,1495,122],{"class":121},[115,1497,1498],{"class":125}," ecPubKeyObject",[115,1500,129],{"class":121},[115,1502,494],{"class":136},[115,1504,1505],{"class":132},"(ecPubPem);\n",[115,1507,1508],{"class":117,"line":362},[115,1509,252],{"emptyLinePlaceholder":251},[115,1511,1512],{"class":117,"line":372},[115,1513,1514],{"class":179},"// 2. Sign:\n",[115,1516,1517,1519,1522,1524,1526,1528,1530,1533,1535,1538,1541,1544],{"class":117,"line":387},[115,1518,122],{"class":121},[115,1520,1521],{"class":125}," payload",[115,1523,129],{"class":121},[115,1525,973],{"class":132},[115,1527,238],{"class":136},[115,1529,287],{"class":132},[115,1531,1532],{"class":125},"JSON",[115,1534,146],{"class":132},[115,1536,1537],{"class":136},"stringify",[115,1539,1540],{"class":132},"({ foo: ",[115,1542,1543],{"class":241},"'bar'",[115,1545,1546],{"class":132}," }));\n",[115,1548,1549,1551,1553,1555,1557,1559,1562],{"class":117,"line":396},[115,1550,122],{"class":121},[115,1552,1002],{"class":125},[115,1554,129],{"class":121},[115,1556,1007],{"class":136},[115,1558,287],{"class":132},[115,1560,1561],{"class":241},"'SHA256'",[115,1563,677],{"class":132},[115,1565,1566,1568,1570],{"class":117,"line":402},[115,1567,1028],{"class":132},[115,1569,1031],{"class":136},[115,1571,1572],{"class":132},"(payload);\n",[115,1574,1575,1577,1579],{"class":117,"line":408},[115,1576,1028],{"class":132},[115,1578,1041],{"class":136},[115,1580,1581],{"class":132},"();\n",[115,1583,1584],{"class":117,"line":413},[115,1585,252],{"emptyLinePlaceholder":251},[115,1587,1588],{"class":117,"line":419},[115,1589,1590],{"class":179},"// ECDSA uses DER-encoded signature by default (r || s).\n",[115,1592,1593,1595,1597,1599,1601,1603,1606],{"class":117,"line":425},[115,1594,122],{"class":121},[115,1596,126],{"class":125},[115,1598,129],{"class":121},[115,1600,133],{"class":132},[115,1602,137],{"class":136},[115,1604,1605],{"class":132},"(ecPrivKeyObject); ",[115,1607,1608],{"class":179},"// Buffer\n",[115,1610,1611],{"class":117,"line":439},[115,1612,252],{"emptyLinePlaceholder":251},[115,1614,1615,1617,1619,1621,1624,1626,1628,1630,1632],{"class":117,"line":455},[115,1616,1126],{"class":132},[115,1618,1129],{"class":136},[115,1620,287],{"class":132},[115,1622,1623],{"class":241},"'ECDSA Signature (hex):'",[115,1625,1137],{"class":132},[115,1627,1140],{"class":136},[115,1629,287],{"class":132},[115,1631,1313],{"class":241},[115,1633,1148],{"class":132},[1635,1636,1637],"blockquote",{},[24,1638,1639],{},"For ECDSA, you do not specify padding: the default DER‐format output is correct.",[1635,1641,1642],{},[24,1643,1644],{},"Verification (below) will expect exactly that DER‐encoded signature.",[210,1646],{},[10,1648,1650,1651,913],{"id":1649},"_4-verifying-a-signature-createverify","4. Verifying a Signature (",[15,1652,1653],{},"createVerify",[24,1655,1656],{},"Use the corresponding public key to verify a signature. You must feed the same data and algorithm:",[106,1658,1660],{"className":108,"code":1659,"language":110,"meta":111,"style":111},"import { createVerify, constants } from 'crypto';\n\n// Assume `payload`, `signature`, and `publicKeyObject` are known:\nconst verify = createVerify('RSA-SHA256');\nverify.update(payload);\nverify.end();\n\nconst isValid = verify.verify(\n  {\n    key: publicKeyObject, // the KeyObject or PEM string\n    padding: constants.RSA_PKCS1_PSS_PADDING,   // if you used PSS when signing\n    saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n  },\n  signature // Buffer, or if your signature was Base64, Buffer.from(sigBase64, 'base64')\n);\n\nconsole.log('Signature valid?', isValid);\n",[15,1661,1662,1675,1679,1684,1702,1711,1719,1723,1738,1743,1751,1764,1771,1775,1783,1787,1791],{"__ignoreMap":111},[115,1663,1664,1666,1669,1671,1673],{"class":117,"line":118},[115,1665,232],{"class":121},[115,1667,1668],{"class":132}," { createVerify, constants } ",[115,1670,238],{"class":121},[115,1672,242],{"class":241},[115,1674,245],{"class":132},[115,1676,1677],{"class":117,"line":248},[115,1678,252],{"emptyLinePlaceholder":251},[115,1680,1681],{"class":117,"line":255},[115,1682,1683],{"class":179},"// Assume `payload`, `signature`, and `publicKeyObject` are known:\n",[115,1685,1686,1688,1691,1693,1696,1698,1700],{"class":117,"line":261},[115,1687,122],{"class":121},[115,1689,1690],{"class":125}," verify",[115,1692,129],{"class":121},[115,1694,1695],{"class":136}," createVerify",[115,1697,287],{"class":132},[115,1699,1012],{"class":241},[115,1701,677],{"class":132},[115,1703,1704,1707,1709],{"class":117,"line":296},[115,1705,1706],{"class":132},"verify.",[115,1708,1031],{"class":136},[115,1710,1572],{"class":132},[115,1712,1713,1715,1717],{"class":117,"line":308},[115,1714,1706],{"class":132},[115,1716,1041],{"class":136},[115,1718,1581],{"class":132},[115,1720,1721],{"class":117,"line":314},[115,1722,252],{"emptyLinePlaceholder":251},[115,1724,1725,1727,1729,1731,1733,1735],{"class":117,"line":329},[115,1726,122],{"class":121},[115,1728,165],{"class":125},[115,1730,129],{"class":121},[115,1732,170],{"class":132},[115,1734,173],{"class":136},[115,1736,1737],{"class":132},"(\n",[115,1739,1740],{"class":117,"line":338},[115,1741,1742],{"class":132},"  {\n",[115,1744,1745,1748],{"class":117,"line":344},[115,1746,1747],{"class":132},"    key: publicKeyObject, ",[115,1749,1750],{"class":179},"// the KeyObject or PEM string\n",[115,1752,1753,1756,1758,1761],{"class":117,"line":350},[115,1754,1755],{"class":132},"    padding: constants.",[115,1757,1096],{"class":125},[115,1759,1760],{"class":132},",   ",[115,1762,1763],{"class":179},"// if you used PSS when signing\n",[115,1765,1766,1769],{"class":117,"line":362},[115,1767,1768],{"class":132},"    saltLength: constants.",[115,1770,1233],{"class":125},[115,1772,1773],{"class":117,"line":372},[115,1774,341],{"class":132},[115,1776,1777,1780],{"class":117,"line":387},[115,1778,1779],{"class":132},"  signature ",[115,1781,1782],{"class":179},"// Buffer, or if your signature was Base64, Buffer.from(sigBase64, 'base64')\n",[115,1784,1785],{"class":117,"line":396},[115,1786,677],{"class":132},[115,1788,1789],{"class":117,"line":402},[115,1790,252],{"emptyLinePlaceholder":251},[115,1792,1793,1795,1797,1799,1802],{"class":117,"line":408},[115,1794,1126],{"class":132},[115,1796,1129],{"class":136},[115,1798,287],{"class":132},[115,1800,1801],{"class":241},"'Signature valid?'",[115,1803,1804],{"class":132},", isValid);\n",[31,1806,1807,1810],{},[34,1808,1809],{},"Make sure the algorithm and padding match exactly what was used during signing.",[34,1811,1812,1815,1816,1819],{},[15,1813,1814],{},"verify.verify(...)"," returns a boolean. If ",[15,1817,1818],{},"false",", either data was altered or signature/public key mismatched.",[210,1821],{},[10,1823,1825,1826,1828,1829,1831],{"id":1824},"_5-createprivatekey-createpublickey-in-detail","5. ",[15,1827,68],{}," & ",[15,1830,72],{}," in Detail",[19,1833,1835],{"id":1834},"createprivatekeyoptions",[15,1836,1837],{},"createPrivateKey(options)",[31,1839,1840,1889],{},[34,1841,1842,1845],{},[88,1843,1844],{},"Input:",[31,1846,1847,1863,1870,1879],{},[34,1848,1849,851,1852,1855],{},[15,1850,1851],{},"options.key",[15,1853,1854],{},"string | Buffer | Object",[31,1856,1857,1860],{},[34,1858,1859],{},"If string/Buffer: PEM or DER.",[34,1861,1862],{},"If object: Assume a JWK.",[34,1864,1865,851,1868,146],{},[15,1866,1867],{},"options.format",[15,1869,863],{},[34,1871,1872,851,1875,1878],{},[15,1873,1874],{},"options.type",[15,1876,1877],{},"'pkcs1' | 'pkcs8'"," (only for DER/PEM).",[34,1880,1881,1884,1885,1888],{},[15,1882,1883],{},"options.passphrase",": (",[15,1886,1887],{},"string | Buffer",") if PEM is encrypted.",[34,1890,1891,1894,1895,1897],{},[88,1892,1893],{},"Output:"," A ",[15,1896,22],{}," representing a private key.",[24,1899,1900],{},[88,1901,1902],{},"Typical usage:",[106,1904,1906],{"className":108,"code":1905,"language":110,"meta":111,"style":111},"const pemString = fs.readFileSync('/secrets/key.pem', 'utf8');\nconst privObj = createPrivateKey({ key: pemString, format: 'pem', passphrase: '...' });\n",[15,1907,1908,1933],{"__ignoreMap":111},[115,1909,1910,1912,1915,1917,1919,1921,1923,1926,1928,1931],{"class":117,"line":118},[115,1911,122],{"class":121},[115,1913,1914],{"class":125}," pemString",[115,1916,129],{"class":121},[115,1918,666],{"class":132},[115,1920,669],{"class":136},[115,1922,287],{"class":132},[115,1924,1925],{"class":241},"'/secrets/key.pem'",[115,1927,272],{"class":132},[115,1929,1930],{"class":241},"'utf8'",[115,1932,677],{"class":132},[115,1934,1935,1937,1940,1942,1944,1947,1949,1952,1955],{"class":117,"line":248},[115,1936,122],{"class":121},[115,1938,1939],{"class":125}," privObj",[115,1941,129],{"class":121},[115,1943,449],{"class":136},[115,1945,1946],{"class":132},"({ key: pemString, format: ",[115,1948,367],{"class":241},[115,1950,1951],{"class":132},", passphrase: ",[115,1953,1954],{"class":241},"'...'",[115,1956,815],{"class":132},[31,1958,1959],{},[34,1960,1961,1962,1964],{},"Store ",[15,1963,22],{}," in memory—Node will protect the key material from accidental exposure (e.g. not accidentally logged).",[19,1966,1968],{"id":1967},"createpublickeyoptions",[15,1969,1970],{},"createPublicKey(options)",[31,1972,1973,2008],{},[34,1974,1975,1977,1978,1981,1982],{},[88,1976,1844],{}," Same as above (minus ",[15,1979,1980],{},"passphrase",", since public keys aren’t encrypted).",[31,1983,1984,1993,1999],{},[34,1985,1986,1988,1989,1992],{},[15,1987,850],{},": public PEM (e.g. ",[15,1990,1991],{},"-----BEGIN PUBLIC KEY-----"," ...).",[34,1994,1995,851,1997,146],{},[15,1996,860],{},[15,1998,863],{},[34,2000,2001,851,2004,2007],{},[15,2002,2003],{},"type",[15,2005,2006],{},"'spki' | 'pkcs1'"," (for public).",[34,2009,2010,1894,2012,2014],{},[88,2011,1893],{},[15,2013,22],{}," for the public key.",[24,2016,2017],{},[88,2018,1902],{},[106,2020,2022],{"className":108,"code":2021,"language":110,"meta":111,"style":111},"const pubPem = getFromAwsKms();\nconst pubObj = createPublicKey({ key: pubPem, format: 'pem' });\n",[15,2023,2024,2038],{"__ignoreMap":111},[115,2025,2026,2028,2031,2033,2036],{"class":117,"line":118},[115,2027,122],{"class":121},[115,2029,2030],{"class":125}," pubPem",[115,2032,129],{"class":121},[115,2034,2035],{"class":136}," getFromAwsKms",[115,2037,1581],{"class":132},[115,2039,2040,2042,2045,2047,2049,2052,2054],{"class":117,"line":248},[115,2041,122],{"class":121},[115,2043,2044],{"class":125}," pubObj",[115,2046,129],{"class":121},[115,2048,494],{"class":136},[115,2050,2051],{"class":132},"({ key: pubPem, format: ",[115,2053,367],{"class":241},[115,2055,815],{"class":132},[31,2057,2058],{},[34,2059,886,2060,2062,2063,2065,2066,272,2069,2072,2073,58,2076,2079],{},[15,2061,22],{},", you never need to deal with raw PEM/DER strings again—just pass the ",[15,2064,22],{}," into ",[15,2067,2068],{},"sign()",[15,2070,2071],{},"verify()",", or even into ",[15,2074,2075],{},"encrypt()",[15,2077,2078],{},"decrypt()"," functions.",[210,2081],{},[10,2083,2085],{"id":2084},"_6-higher-level-signing-apis","6. Higher-Level Signing APIs",[24,2087,2088,2089,205,2091,2093],{},"Node also offers convenience methods so you don’t have to manage ",[15,2090,912],{},[15,2092,1653],{}," objects manually:",[19,2095,2097],{"id":2096},"cryptosignalgorithm-data-privatekey",[15,2098,2099],{},"crypto.sign(algorithm, data, privateKey)",[24,2101,2102],{},[88,2103,2104],{},"Usage:",[106,2106,2108],{"className":108,"code":2107,"language":110,"meta":111,"style":111},"import { sign, constants } from 'crypto';\n// data: Buffer or string\n// privateKey: KeyObject or PEM string or { key: pemString, passphrase, ... }\nconst signature = sign(\n  'RSA-SHA256',            // algorithm\n  Buffer.from('hello'),    // data\n  {\n    key: privateKeyObject,          // or PEM string + passphrase\n    padding: constants.RSA_PKCS1_PSS_PADDING,\n    saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n  }\n);\n",[15,2109,2110,2123,2128,2133,2145,2155,2173,2177,2185,2193,2199,2203],{"__ignoreMap":111},[115,2111,2112,2114,2117,2119,2121],{"class":117,"line":118},[115,2113,232],{"class":121},[115,2115,2116],{"class":132}," { sign, constants } ",[115,2118,238],{"class":121},[115,2120,242],{"class":241},[115,2122,245],{"class":132},[115,2124,2125],{"class":117,"line":248},[115,2126,2127],{"class":179},"// data: Buffer or string\n",[115,2129,2130],{"class":117,"line":255},[115,2131,2132],{"class":179},"// privateKey: KeyObject or PEM string or { key: pemString, passphrase, ... }\n",[115,2134,2135,2137,2139,2141,2143],{"class":117,"line":261},[115,2136,122],{"class":121},[115,2138,126],{"class":125},[115,2140,129],{"class":121},[115,2142,1002],{"class":136},[115,2144,1737],{"class":132},[115,2146,2147,2150,2152],{"class":117,"line":296},[115,2148,2149],{"class":241},"  'RSA-SHA256'",[115,2151,323],{"class":132},[115,2153,2154],{"class":179},"// algorithm\n",[115,2156,2157,2160,2162,2164,2167,2170],{"class":117,"line":308},[115,2158,2159],{"class":132},"  Buffer.",[115,2161,238],{"class":136},[115,2163,287],{"class":132},[115,2165,2166],{"class":241},"'hello'",[115,2168,2169],{"class":132},"),    ",[115,2171,2172],{"class":179},"// data\n",[115,2174,2175],{"class":117,"line":314},[115,2176,1742],{"class":132},[115,2178,2179,2182],{"class":117,"line":329},[115,2180,2181],{"class":132},"    key: privateKeyObject,          ",[115,2183,2184],{"class":179},"// or PEM string + passphrase\n",[115,2186,2187,2189,2191],{"class":117,"line":338},[115,2188,1755],{"class":132},[115,2190,1096],{"class":125},[115,2192,305],{"class":132},[115,2194,2195,2197],{"class":117,"line":344},[115,2196,1768],{"class":132},[115,2198,1233],{"class":125},[115,2200,2201],{"class":117,"line":350},[115,2202,399],{"class":132},[115,2204,2205],{"class":117,"line":362},[115,2206,677],{"class":132},[24,2208,2209,2210,2213,2214,2213,2217,2220],{},"This is exactly the same as doing ",[15,2211,2212],{},"createSign(algorithm)"," + ",[15,2215,2216],{},".update(data)",[15,2218,2219],{},".sign(privateKey)",". It’s just a one-liner:",[106,2222,2224],{"className":108,"code":2223,"language":110,"meta":111,"style":111},"// Equivalent to above:\nconst signature = sign('SHA256', data, privateKeyObject);\n",[15,2225,2226,2231],{"__ignoreMap":111},[115,2227,2228],{"class":117,"line":118},[115,2229,2230],{"class":179},"// Equivalent to above:\n",[115,2232,2233,2235,2237,2239,2241,2243,2245],{"class":117,"line":248},[115,2234,122],{"class":121},[115,2236,126],{"class":125},[115,2238,129],{"class":121},[115,2240,1002],{"class":136},[115,2242,287],{"class":132},[115,2244,1561],{"class":241},[115,2246,2247],{"class":132},", data, privateKeyObject);\n",[19,2249,2251],{"id":2250},"cryptoverifyalgorithm-data-publickey-signature",[15,2252,2253],{},"crypto.verify(algorithm, data, publicKey, signature)",[24,2255,2256],{},[88,2257,2104],{},[106,2259,2261],{"className":108,"code":2260,"language":110,"meta":111,"style":111},"import { verify, constants } from 'crypto';\nconst isOk = verify(\n  'RSA-SHA256',\n  Buffer.from('hello'),\n  {\n    key: publicKeyObject,  // or PEM string\n    padding: constants.RSA_PKCS1_PSS_PADDING,\n    saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n  },\n  signatureBuffer\n);\nconsole.log(isOk); // true or false\n",[15,2262,2263,2276,2289,2295,2308,2312,2320,2328,2334,2338,2343,2347],{"__ignoreMap":111},[115,2264,2265,2267,2270,2272,2274],{"class":117,"line":118},[115,2266,232],{"class":121},[115,2268,2269],{"class":132}," { verify, constants } ",[115,2271,238],{"class":121},[115,2273,242],{"class":241},[115,2275,245],{"class":132},[115,2277,2278,2280,2283,2285,2287],{"class":117,"line":248},[115,2279,122],{"class":121},[115,2281,2282],{"class":125}," isOk",[115,2284,129],{"class":121},[115,2286,1690],{"class":136},[115,2288,1737],{"class":132},[115,2290,2291,2293],{"class":117,"line":255},[115,2292,2149],{"class":241},[115,2294,305],{"class":132},[115,2296,2297,2299,2301,2303,2305],{"class":117,"line":261},[115,2298,2159],{"class":132},[115,2300,238],{"class":136},[115,2302,287],{"class":132},[115,2304,2166],{"class":241},[115,2306,2307],{"class":132},"),\n",[115,2309,2310],{"class":117,"line":296},[115,2311,1742],{"class":132},[115,2313,2314,2317],{"class":117,"line":308},[115,2315,2316],{"class":132},"    key: publicKeyObject,  ",[115,2318,2319],{"class":179},"// or PEM string\n",[115,2321,2322,2324,2326],{"class":117,"line":314},[115,2323,1755],{"class":132},[115,2325,1096],{"class":125},[115,2327,305],{"class":132},[115,2329,2330,2332],{"class":117,"line":329},[115,2331,1768],{"class":132},[115,2333,1233],{"class":125},[115,2335,2336],{"class":117,"line":338},[115,2337,341],{"class":132},[115,2339,2340],{"class":117,"line":344},[115,2341,2342],{"class":132},"  signatureBuffer\n",[115,2344,2345],{"class":117,"line":350},[115,2346,677],{"class":132},[115,2348,2349,2351,2353,2356],{"class":117,"line":362},[115,2350,1126],{"class":132},[115,2352,1129],{"class":136},[115,2354,2355],{"class":132},"(isOk); ",[115,2357,2358],{"class":179},"// true or false\n",[24,2360,2361,2362,2213,2365,2213,2367,146],{},"Internally, it does exactly ",[15,2363,2364],{},"createVerify(algorithm)",[15,2366,2216],{},[15,2368,2369],{},".verify(pubKey, sig)",[1635,2371,2372],{},[24,2373,2374],{},"If you only have a single piece of data to sign (rather than a streaming scenario), it’s simpler to use these one-line helpers.",[210,2376],{},[10,2378,2380],{"id":2379},"_7-other-publicprivate-keyobjectrelated-apis","7. Other “Public/Private” KeyObject–Related APIs",[24,2382,2383,2384,2386],{},"While “sign/verify” is one major use case, Node’s ",[15,2385,17],{}," module supports a few other operations on asymmetric key pairs:",[19,2388,2390,69,2393],{"id":2389},"cryptopublicencryptpublickey-buffer-cryptoprivatedecryptprivatekey-buffer",[15,2391,2392],{},"crypto.publicEncrypt(publicKey, buffer)",[15,2394,2395],{},"crypto.privateDecrypt(privateKey, buffer)",[31,2397,2398,2404],{},[34,2399,2400,2403],{},[88,2401,2402],{},"Classic RSA encryption:"," encrypt with a recipient’s public key, decrypt with your private.",[34,2405,2406,2409],{},[88,2407,2408],{},"Note:"," RSA encryption is now generally discouraged for large payloads (you’d typically do hybrid‐encryption: generate a random AES key, encrypt data with AES, then encrypt AES key with RSA).",[24,2411,2412],{},[88,2413,2414],{},"Example:",[106,2416,2418],{"className":108,"code":2417,"language":110,"meta":111,"style":111},"import { publicEncrypt, privateDecrypt, constants } from 'crypto';\n\n// Encrypt:\nconst encrypted = publicEncrypt(\n  {\n    key: publicKeyObject,\n    padding: constants.RSA_PKCS1_OAEP_PADDING, // preferred over PKCS1 v1.5\n    oaepHash: 'sha256'                              // e.g. SHA-256 for OAEP\n  },\n  Buffer.from('secret data')\n);\n// Decrypt:\nconst decrypted = privateDecrypt(\n  {\n    key: privateKeyObject,\n    padding: constants.RSA_PKCS1_OAEP_PADDING,\n    oaepHash: 'sha256'\n  },\n  encrypted\n);\nconsole.log(decrypted.toString()); // 'secret data'\n",[15,2419,2420,2433,2437,2442,2456,2460,2465,2477,2488,2492,2506,2510,2515,2529,2533,2538,2546,2553,2557,2562,2566],{"__ignoreMap":111},[115,2421,2422,2424,2427,2429,2431],{"class":117,"line":118},[115,2423,232],{"class":121},[115,2425,2426],{"class":132}," { publicEncrypt, privateDecrypt, constants } ",[115,2428,238],{"class":121},[115,2430,242],{"class":241},[115,2432,245],{"class":132},[115,2434,2435],{"class":117,"line":248},[115,2436,252],{"emptyLinePlaceholder":251},[115,2438,2439],{"class":117,"line":255},[115,2440,2441],{"class":179},"// Encrypt:\n",[115,2443,2444,2446,2449,2451,2454],{"class":117,"line":261},[115,2445,122],{"class":121},[115,2447,2448],{"class":125}," encrypted",[115,2450,129],{"class":121},[115,2452,2453],{"class":136}," publicEncrypt",[115,2455,1737],{"class":132},[115,2457,2458],{"class":117,"line":296},[115,2459,1742],{"class":132},[115,2461,2462],{"class":117,"line":308},[115,2463,2464],{"class":132},"    key: publicKeyObject,\n",[115,2466,2467,2469,2472,2474],{"class":117,"line":314},[115,2468,1755],{"class":132},[115,2470,2471],{"class":125},"RSA_PKCS1_OAEP_PADDING",[115,2473,272],{"class":132},[115,2475,2476],{"class":179},"// preferred over PKCS1 v1.5\n",[115,2478,2479,2482,2485],{"class":117,"line":329},[115,2480,2481],{"class":132},"    oaepHash: ",[115,2483,2484],{"class":241},"'sha256'",[115,2486,2487],{"class":179},"                              // e.g. SHA-256 for OAEP\n",[115,2489,2490],{"class":117,"line":338},[115,2491,341],{"class":132},[115,2493,2494,2496,2498,2500,2503],{"class":117,"line":344},[115,2495,2159],{"class":132},[115,2497,238],{"class":136},[115,2499,287],{"class":132},[115,2501,2502],{"class":241},"'secret data'",[115,2504,2505],{"class":132},")\n",[115,2507,2508],{"class":117,"line":350},[115,2509,677],{"class":132},[115,2511,2512],{"class":117,"line":362},[115,2513,2514],{"class":179},"// Decrypt:\n",[115,2516,2517,2519,2522,2524,2527],{"class":117,"line":372},[115,2518,122],{"class":121},[115,2520,2521],{"class":125}," decrypted",[115,2523,129],{"class":121},[115,2525,2526],{"class":136}," privateDecrypt",[115,2528,1737],{"class":132},[115,2530,2531],{"class":117,"line":387},[115,2532,1742],{"class":132},[115,2534,2535],{"class":117,"line":396},[115,2536,2537],{"class":132},"    key: privateKeyObject,\n",[115,2539,2540,2542,2544],{"class":117,"line":402},[115,2541,1755],{"class":132},[115,2543,2471],{"class":125},[115,2545,305],{"class":132},[115,2547,2548,2550],{"class":117,"line":408},[115,2549,2481],{"class":132},[115,2551,2552],{"class":241},"'sha256'\n",[115,2554,2555],{"class":117,"line":413},[115,2556,341],{"class":132},[115,2558,2559],{"class":117,"line":419},[115,2560,2561],{"class":132},"  encrypted\n",[115,2563,2564],{"class":117,"line":425},[115,2565,677],{"class":132},[115,2567,2568,2570,2572,2575,2577,2580],{"class":117,"line":439},[115,2569,1126],{"class":132},[115,2571,1129],{"class":136},[115,2573,2574],{"class":132},"(decrypted.",[115,2576,1140],{"class":136},[115,2578,2579],{"class":132},"()); ",[115,2581,2582],{"class":179},"// 'secret data'\n",[19,2584,2586,69,2589],{"id":2585},"cryptoprivateencryptprivatekey-buffer-cryptopublicdecryptpublickey-buffer",[15,2587,2588],{},"crypto.privateEncrypt(privateKey, buffer)",[15,2590,2591],{},"crypto.publicDecrypt(publicKey, buffer)",[31,2593,2594,2599],{},[34,2595,2596,2597,146],{},"Rarely used. “Private encrypt” is essentially “sign with raw RSA” (no hashing)—this is not a standard “signature” operation and should not be used in place of ",[15,2598,2068],{},[34,2600,2601,2602,2605],{},"You’ll see ",[15,2603,2604],{},"crypto.privateEncrypt"," if you must interoperate with some legacy system that expects raw RSA cryptography.",[19,2607,2609],{"id":2608},"cryptodiffiehellman",[15,2610,2611],{},"crypto.diffieHellman()",[31,2613,2614,2617],{},[34,2615,2616],{},"For Diffie-Hellman key exchange: both parties derive a shared secret from each other’s public parameters.",[34,2618,2619,2620,2623],{},"In modern code, you’d usually use ECDH (",[15,2621,2622],{},"crypto.createECDH(curveName)","), which returns a small, efficient key exchange mechanism (no need to deal with big integer math manually).",[24,2625,2626],{},[88,2627,2628],{},"Example (ECDH P-256):",[106,2630,2632],{"className":108,"code":2631,"language":110,"meta":111,"style":111},"import { createECDH } from 'crypto';\n\n// Party A:\nconst alice = createECDH('prime256v1');\nalice.generateKeys();\nconst alicePub = alice.getPublicKey(); // send to Bob\n\n// Party B:\nconst bob = createECDH('prime256v1');\nbob.generateKeys();\nconst bobPub = bob.getPublicKey(); // send to Alice\n\n// Each side computes the shared secret:\nconst aliceShared = alice.computeSecret(bobPub);\nconst bobShared   = bob.computeSecret(alicePub);\nconsole.log(aliceShared.equals(bobShared)); // true\n",[15,2633,2634,2647,2651,2656,2674,2684,2704,2708,2713,2730,2739,2758,2762,2767,2784,2801],{"__ignoreMap":111},[115,2635,2636,2638,2641,2643,2645],{"class":117,"line":118},[115,2637,232],{"class":121},[115,2639,2640],{"class":132}," { createECDH } ",[115,2642,238],{"class":121},[115,2644,242],{"class":241},[115,2646,245],{"class":132},[115,2648,2649],{"class":117,"line":248},[115,2650,252],{"emptyLinePlaceholder":251},[115,2652,2653],{"class":117,"line":255},[115,2654,2655],{"class":179},"// Party A:\n",[115,2657,2658,2660,2663,2665,2668,2670,2672],{"class":117,"line":261},[115,2659,122],{"class":121},[115,2661,2662],{"class":125}," alice",[115,2664,129],{"class":121},[115,2666,2667],{"class":136}," createECDH",[115,2669,287],{"class":132},[115,2671,520],{"class":241},[115,2673,677],{"class":132},[115,2675,2676,2679,2682],{"class":117,"line":296},[115,2677,2678],{"class":132},"alice.",[115,2680,2681],{"class":136},"generateKeys",[115,2683,1581],{"class":132},[115,2685,2686,2688,2691,2693,2696,2699,2701],{"class":117,"line":308},[115,2687,122],{"class":121},[115,2689,2690],{"class":125}," alicePub",[115,2692,129],{"class":121},[115,2694,2695],{"class":132}," alice.",[115,2697,2698],{"class":136},"getPublicKey",[115,2700,1044],{"class":132},[115,2702,2703],{"class":179},"// send to Bob\n",[115,2705,2706],{"class":117,"line":314},[115,2707,252],{"emptyLinePlaceholder":251},[115,2709,2710],{"class":117,"line":329},[115,2711,2712],{"class":179},"// Party B:\n",[115,2714,2715,2717,2720,2722,2724,2726,2728],{"class":117,"line":338},[115,2716,122],{"class":121},[115,2718,2719],{"class":125}," bob",[115,2721,129],{"class":121},[115,2723,2667],{"class":136},[115,2725,287],{"class":132},[115,2727,520],{"class":241},[115,2729,677],{"class":132},[115,2731,2732,2735,2737],{"class":117,"line":344},[115,2733,2734],{"class":132},"bob.",[115,2736,2681],{"class":136},[115,2738,1581],{"class":132},[115,2740,2741,2743,2746,2748,2751,2753,2755],{"class":117,"line":350},[115,2742,122],{"class":121},[115,2744,2745],{"class":125}," bobPub",[115,2747,129],{"class":121},[115,2749,2750],{"class":132}," bob.",[115,2752,2698],{"class":136},[115,2754,1044],{"class":132},[115,2756,2757],{"class":179},"// send to Alice\n",[115,2759,2760],{"class":117,"line":362},[115,2761,252],{"emptyLinePlaceholder":251},[115,2763,2764],{"class":117,"line":372},[115,2765,2766],{"class":179},"// Each side computes the shared secret:\n",[115,2768,2769,2771,2774,2776,2778,2781],{"class":117,"line":387},[115,2770,122],{"class":121},[115,2772,2773],{"class":125}," aliceShared",[115,2775,129],{"class":121},[115,2777,2695],{"class":132},[115,2779,2780],{"class":136},"computeSecret",[115,2782,2783],{"class":132},"(bobPub);\n",[115,2785,2786,2788,2791,2794,2796,2798],{"class":117,"line":396},[115,2787,122],{"class":121},[115,2789,2790],{"class":125}," bobShared",[115,2792,2793],{"class":121},"   =",[115,2795,2750],{"class":132},[115,2797,2780],{"class":136},[115,2799,2800],{"class":132},"(alicePub);\n",[115,2802,2803,2805,2807,2810,2813,2816],{"class":117,"line":402},[115,2804,1126],{"class":132},[115,2806,1129],{"class":136},[115,2808,2809],{"class":132},"(aliceShared.",[115,2811,2812],{"class":136},"equals",[115,2814,2815],{"class":132},"(bobShared)); ",[115,2817,2818],{"class":179},"// true\n",[19,2820,2822,2825,2826],{"id":2821},"cryptogeneratekeypair-and-cryptogeneratekeypairsync",[15,2823,2824],{},"crypto.generateKeyPair()"," and ",[15,2827,2828],{},"crypto.generateKeyPairSync()",[31,2830,2831,2837],{},[34,2832,2833,2834,2836],{},"Synchronous and asynchronous ways to generate new key pairs. We used ",[15,2835,529],{}," above.",[34,2838,2839],{},"If you need to generate keys at runtime without blocking the event loop, call:",[106,2841,2843],{"className":108,"code":2842,"language":110,"meta":111,"style":111},"import { generateKeyPair } from 'crypto';\ngenerateKeyPair('rsa', {\n  modulusLength: 2048,\n  publicKeyEncoding: { type: 'spki', format: 'pem' },\n  privateKeyEncoding: { type: 'pkcs8', format: 'pem', cipher: 'aes-256-cbc', passphrase: 'pass' }\n}, (err, pubPem, privPem) => {\n  if (err) throw err;\n  // pubPem / privPem are PEM strings\n});\n",[15,2844,2845,2858,2868,2876,2889,2911,2937,2951,2956],{"__ignoreMap":111},[115,2846,2847,2849,2852,2854,2856],{"class":117,"line":118},[115,2848,232],{"class":121},[115,2850,2851],{"class":132}," { generateKeyPair } ",[115,2853,238],{"class":121},[115,2855,242],{"class":241},[115,2857,245],{"class":132},[115,2859,2860,2862,2864,2866],{"class":117,"line":248},[115,2861,57],{"class":136},[115,2863,287],{"class":132},[115,2865,290],{"class":241},[115,2867,293],{"class":132},[115,2869,2870,2872,2874],{"class":117,"line":255},[115,2871,299],{"class":132},[115,2873,302],{"class":125},[115,2875,305],{"class":132},[115,2877,2878,2881,2883,2885,2887],{"class":117,"line":261},[115,2879,2880],{"class":132},"  publicKeyEncoding: { type: ",[115,2882,712],{"class":241},[115,2884,1445],{"class":132},[115,2886,367],{"class":241},[115,2888,1450],{"class":132},[115,2890,2891,2893,2895,2897,2899,2902,2904,2906,2909],{"class":117,"line":296},[115,2892,1455],{"class":132},[115,2894,1458],{"class":241},[115,2896,1445],{"class":132},[115,2898,367],{"class":241},[115,2900,2901],{"class":132},", cipher: ",[115,2903,378],{"class":241},[115,2905,1951],{"class":132},[115,2907,2908],{"class":241},"'pass'",[115,2910,1465],{"class":132},[115,2912,2913,2916,2919,2921,2924,2926,2929,2932,2935],{"class":117,"line":308},[115,2914,2915],{"class":132},"}, (",[115,2917,2918],{"class":1399},"err",[115,2920,272],{"class":132},[115,2922,2923],{"class":1399},"pubPem",[115,2925,272],{"class":132},[115,2927,2928],{"class":1399},"privPem",[115,2930,2931],{"class":132},") ",[115,2933,2934],{"class":121},"=>",[115,2936,740],{"class":132},[115,2938,2939,2942,2945,2948],{"class":117,"line":314},[115,2940,2941],{"class":121},"  if",[115,2943,2944],{"class":132}," (err) ",[115,2946,2947],{"class":121},"throw",[115,2949,2950],{"class":132}," err;\n",[115,2952,2953],{"class":117,"line":329},[115,2954,2955],{"class":179},"  // pubPem / privPem are PEM strings\n",[115,2957,2958],{"class":117,"line":338},[115,2959,405],{"class":132},[210,2961],{},[10,2963,2965],{"id":2964},"_8-putting-it-all-together-a-minimal-rsa-pss-example","8. Putting It All Together: A Minimal RSA-PSS Example",[24,2967,2968],{},"Below is a concise end-to-end example (no unnecessary extras) showing:",[918,2970,2971,2974,2979,2986],{},[34,2972,2973],{},"Generating an RSA key pair (synchronous, at startup).",[34,2975,2976,2977,29],{},"Wrapping them in ",[15,2978,22],{},[34,2980,2981,2982,2985],{},"Using ",[15,2983,2984],{},"crypto.sign"," to create an RSA-PSS signature.",[34,2987,2981,2988,2991],{},[15,2989,2990],{},"crypto.verify"," to check that signature.",[106,2993,2995],{"className":108,"code":2994,"language":110,"meta":111,"style":111},"// file: rsa_pss_demo.js\nimport fs from 'fs';\nimport { generateKeyPairSync, createPrivateKey, createPublicKey, sign, verify, constants } from 'crypto';\n\n//\n// 1. Generate a new key pair (do this once; you could instead load from PEM on disk)\n//\nconst { publicKey: pubPem, privateKey: privPem } = generateKeyPairSync('rsa', {\n  modulusLength: 2048,\n  publicKeyEncoding:  { type: 'spki', format: 'pem' },\n  privateKeyEncoding: { type: 'pkcs8', format: 'pem' } // no passphrase in this example\n});\n\n// (Optional) Persist to disk so you can reuse them later:\nfs.writeFileSync('private-key.pem', privPem);\nfs.writeFileSync('public-key.pem', pubPem);\n\n// 2. Wrap the PEMs into KeyObjects\nconst privateKeyObj = createPrivateKey({ key: privPem, format: 'pem' });\nconst publicKeyObj  = createPublicKey({ key: pubPem, format: 'pem' });\n\n//\n// 3. The data you want to sign:\nconst message = Buffer.from('Hello, world! This must be signed.');\n\n// 4. Sign with RSA-PSS (SHA-256 hash, PSS padding)\nconst signature = sign('sha256', message, {\n  key: privateKeyObj,\n  padding: constants.RSA_PKCS1_PSS_PADDING,\n  saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n});\n\n// 5. (Optional) Transmit or store `signature` (e.g. base64-encode it for JSON):\nconst signatureBase64 = signature.toString('base64');\nconsole.log('Signature (Base64):', signatureBase64);\n\n//\n// At the receiver or later in your code, verify:\nconst incomingSignature = Buffer.from(signatureBase64, 'base64');\n\nconst isValid = verify('sha256', message, {\n  key: publicKeyObj,\n  padding: constants.RSA_PKCS1_PSS_PADDING,\n  saltLength: constants.RSA_PSS_SALTLEN_DIGEST\n}, incomingSignature);\n\nconsole.log('Signature valid?', isValid); // → true\n",[15,2996,2997,3002,3014,3027,3031,3036,3041,3045,3077,3085,3097,3112,3116,3120,3125,3141,3155,3159,3164,3182,3199,3203,3207,3212,3232,3236,3241,3258,3263,3271,3277,3281,3285,3291,3311,3326,3331,3336,3342,3363,3368,3385,3391,3400,3407,3413,3418],{"__ignoreMap":111},[115,2998,2999],{"class":117,"line":118},[115,3000,3001],{"class":179},"// file: rsa_pss_demo.js\n",[115,3003,3004,3006,3008,3010,3012],{"class":117,"line":248},[115,3005,232],{"class":121},[115,3007,647],{"class":132},[115,3009,238],{"class":121},[115,3011,652],{"class":241},[115,3013,245],{"class":132},[115,3015,3016,3018,3021,3023,3025],{"class":117,"line":255},[115,3017,232],{"class":121},[115,3019,3020],{"class":132}," { generateKeyPairSync, createPrivateKey, createPublicKey, sign, verify, constants } ",[115,3022,238],{"class":121},[115,3024,242],{"class":241},[115,3026,245],{"class":132},[115,3028,3029],{"class":117,"line":261},[115,3030,252],{"emptyLinePlaceholder":251},[115,3032,3033],{"class":117,"line":296},[115,3034,3035],{"class":179},"//\n",[115,3037,3038],{"class":117,"line":308},[115,3039,3040],{"class":179},"// 1. Generate a new key pair (do this once; you could instead load from PEM on disk)\n",[115,3042,3043],{"class":117,"line":314},[115,3044,3035],{"class":179},[115,3046,3047,3049,3051,3053,3055,3057,3059,3061,3063,3065,3067,3069,3071,3073,3075],{"class":117,"line":329},[115,3048,122],{"class":121},[115,3050,266],{"class":132},[115,3052,269],{"class":1399},[115,3054,851],{"class":132},[115,3056,2923],{"class":125},[115,3058,272],{"class":132},[115,3060,275],{"class":1399},[115,3062,851],{"class":132},[115,3064,2928],{"class":125},[115,3066,278],{"class":132},[115,3068,281],{"class":121},[115,3070,284],{"class":136},[115,3072,287],{"class":132},[115,3074,290],{"class":241},[115,3076,293],{"class":132},[115,3078,3079,3081,3083],{"class":117,"line":338},[115,3080,299],{"class":132},[115,3082,302],{"class":125},[115,3084,305],{"class":132},[115,3086,3087,3089,3091,3093,3095],{"class":117,"line":344},[115,3088,1440],{"class":132},[115,3090,712],{"class":241},[115,3092,1445],{"class":132},[115,3094,367],{"class":241},[115,3096,1450],{"class":132},[115,3098,3099,3101,3103,3105,3107,3109],{"class":117,"line":350},[115,3100,1455],{"class":132},[115,3102,1458],{"class":241},[115,3104,1445],{"class":132},[115,3106,367],{"class":241},[115,3108,278],{"class":132},[115,3110,3111],{"class":179},"// no passphrase in this example\n",[115,3113,3114],{"class":117,"line":362},[115,3115,405],{"class":132},[115,3117,3118],{"class":117,"line":372},[115,3119,252],{"emptyLinePlaceholder":251},[115,3121,3122],{"class":117,"line":387},[115,3123,3124],{"class":179},"// (Optional) Persist to disk so you can reuse them later:\n",[115,3126,3127,3130,3133,3135,3138],{"class":117,"line":396},[115,3128,3129],{"class":132},"fs.",[115,3131,3132],{"class":136},"writeFileSync",[115,3134,287],{"class":132},[115,3136,3137],{"class":241},"'private-key.pem'",[115,3139,3140],{"class":132},", privPem);\n",[115,3142,3143,3145,3147,3149,3152],{"class":117,"line":402},[115,3144,3129],{"class":132},[115,3146,3132],{"class":136},[115,3148,287],{"class":132},[115,3150,3151],{"class":241},"'public-key.pem'",[115,3153,3154],{"class":132},", pubPem);\n",[115,3156,3157],{"class":117,"line":408},[115,3158,252],{"emptyLinePlaceholder":251},[115,3160,3161],{"class":117,"line":413},[115,3162,3163],{"class":179},"// 2. Wrap the PEMs into KeyObjects\n",[115,3165,3166,3168,3171,3173,3175,3178,3180],{"class":117,"line":419},[115,3167,122],{"class":121},[115,3169,3170],{"class":125}," privateKeyObj",[115,3172,129],{"class":121},[115,3174,449],{"class":136},[115,3176,3177],{"class":132},"({ key: privPem, format: ",[115,3179,367],{"class":241},[115,3181,815],{"class":132},[115,3183,3184,3186,3189,3191,3193,3195,3197],{"class":117,"line":425},[115,3185,122],{"class":121},[115,3187,3188],{"class":125}," publicKeyObj",[115,3190,826],{"class":121},[115,3192,494],{"class":136},[115,3194,2051],{"class":132},[115,3196,367],{"class":241},[115,3198,815],{"class":132},[115,3200,3201],{"class":117,"line":439},[115,3202,252],{"emptyLinePlaceholder":251},[115,3204,3205],{"class":117,"line":455},[115,3206,3035],{"class":179},[115,3208,3209],{"class":117,"line":461},[115,3210,3211],{"class":179},"// 3. The data you want to sign:\n",[115,3213,3214,3216,3219,3221,3223,3225,3227,3230],{"class":117,"line":471},[115,3215,122],{"class":121},[115,3217,3218],{"class":125}," message",[115,3220,129],{"class":121},[115,3222,973],{"class":132},[115,3224,238],{"class":136},[115,3226,287],{"class":132},[115,3228,3229],{"class":241},"'Hello, world! This must be signed.'",[115,3231,677],{"class":132},[115,3233,3234],{"class":117,"line":479},[115,3235,252],{"emptyLinePlaceholder":251},[115,3237,3238],{"class":117,"line":484},[115,3239,3240],{"class":179},"// 4. Sign with RSA-PSS (SHA-256 hash, PSS padding)\n",[115,3242,3243,3245,3247,3249,3251,3253,3255],{"class":117,"line":763},[115,3244,122],{"class":121},[115,3246,126],{"class":125},[115,3248,129],{"class":121},[115,3250,1002],{"class":136},[115,3252,287],{"class":132},[115,3254,2484],{"class":241},[115,3256,3257],{"class":132},", message, {\n",[115,3259,3260],{"class":117,"line":774},[115,3261,3262],{"class":132},"  key: privateKeyObj,\n",[115,3264,3265,3267,3269],{"class":117,"line":785},[115,3266,1093],{"class":132},[115,3268,1096],{"class":125},[115,3270,305],{"class":132},[115,3272,3273,3275],{"class":117,"line":791},[115,3274,1106],{"class":132},[115,3276,1233],{"class":125},[115,3278,3279],{"class":117,"line":797},[115,3280,405],{"class":132},[115,3282,3283],{"class":117,"line":818},[115,3284,252],{"emptyLinePlaceholder":251},[115,3286,3288],{"class":117,"line":3287},33,[115,3289,3290],{"class":179},"// 5. (Optional) Transmit or store `signature` (e.g. base64-encode it for JSON):\n",[115,3292,3294,3296,3298,3300,3303,3305,3307,3309],{"class":117,"line":3293},34,[115,3295,122],{"class":121},[115,3297,1332],{"class":125},[115,3299,129],{"class":121},[115,3301,3302],{"class":132}," signature.",[115,3304,1140],{"class":136},[115,3306,287],{"class":132},[115,3308,1145],{"class":241},[115,3310,677],{"class":132},[115,3312,3314,3316,3318,3320,3323],{"class":117,"line":3313},35,[115,3315,1126],{"class":132},[115,3317,1129],{"class":136},[115,3319,287],{"class":132},[115,3321,3322],{"class":241},"'Signature (Base64):'",[115,3324,3325],{"class":132},", signatureBase64);\n",[115,3327,3329],{"class":117,"line":3328},36,[115,3330,252],{"emptyLinePlaceholder":251},[115,3332,3334],{"class":117,"line":3333},37,[115,3335,3035],{"class":179},[115,3337,3339],{"class":117,"line":3338},38,[115,3340,3341],{"class":179},"// At the receiver or later in your code, verify:\n",[115,3343,3345,3347,3350,3352,3354,3356,3359,3361],{"class":117,"line":3344},39,[115,3346,122],{"class":121},[115,3348,3349],{"class":125}," incomingSignature",[115,3351,129],{"class":121},[115,3353,973],{"class":132},[115,3355,238],{"class":136},[115,3357,3358],{"class":132},"(signatureBase64, ",[115,3360,1145],{"class":241},[115,3362,677],{"class":132},[115,3364,3366],{"class":117,"line":3365},40,[115,3367,252],{"emptyLinePlaceholder":251},[115,3369,3371,3373,3375,3377,3379,3381,3383],{"class":117,"line":3370},41,[115,3372,122],{"class":121},[115,3374,165],{"class":125},[115,3376,129],{"class":121},[115,3378,1690],{"class":136},[115,3380,287],{"class":132},[115,3382,2484],{"class":241},[115,3384,3257],{"class":132},[115,3386,3388],{"class":117,"line":3387},42,[115,3389,3390],{"class":132},"  key: publicKeyObj,\n",[115,3392,3394,3396,3398],{"class":117,"line":3393},43,[115,3395,1093],{"class":132},[115,3397,1096],{"class":125},[115,3399,305],{"class":132},[115,3401,3403,3405],{"class":117,"line":3402},44,[115,3404,1106],{"class":132},[115,3406,1233],{"class":125},[115,3408,3410],{"class":117,"line":3409},45,[115,3411,3412],{"class":132},"}, incomingSignature);\n",[115,3414,3416],{"class":117,"line":3415},46,[115,3417,252],{"emptyLinePlaceholder":251},[115,3419,3421,3423,3425,3427,3429,3432],{"class":117,"line":3420},47,[115,3422,1126],{"class":132},[115,3424,1129],{"class":136},[115,3426,287],{"class":132},[115,3428,1801],{"class":241},[115,3430,3431],{"class":132},", isValid); ",[115,3433,3434],{"class":179},"// → true\n",[31,3436,3437,3453,3456],{},[34,3438,3439,3440,3443,3444,2213,3446,2213,3449,3452],{},"We used ",[15,3441,3442],{},"sign('sha256', data, options)"," instead of manually ",[15,3445,912],{},[15,3447,3448],{},".update",[15,3450,3451],{},".sign",", because there’s only one chunk of data here.",[34,3454,3455],{},"We explicitly chose RSA-PSS (more secure than PKCS#1 v1.5 for new applications).",[34,3457,3458,3459,146],{},"We did not encrypt the private PEM (for simplicity), but in production, store the private key on disk (or secret manager) with a passphrase and load it with ",[15,3460,3461],{},"createPrivateKey({ key: encryptedPem, passphrase: ... })",[210,3463],{},[10,3465,3467],{"id":3466},"_9-other-sign-like-operations","9. Other “Sign-like” Operations",[24,3469,3470,3471,3473],{},"Node’s ",[15,3472,17],{}," module also exposes:",[31,3475,3476,3491,3499],{},[34,3477,3478,3480,3481,3483,3484,3487,3488,146],{},[15,3479,103],{}," — returns a ",[15,3482,925],{}," object. Use this when you need to feed data in multiple chunks (e.g. streaming a large file). After streaming all chunks via ",[15,3485,3486],{},".update()",", call ",[15,3489,3490],{},".sign(privateKey, [outputEncoding])",[34,3492,3493,3480,3495,3498],{},[15,3494,152],{},[15,3496,3497],{},"Verify"," object for stream-signature verification.",[34,3500,3501,3504],{},[15,3502,3503],{},"crypto.createHmac(algorithm, key)"," — computes an HMAC of data (symmetric). Not a public/private operation. Use it when you and a known party share a secret key and just want to ensure integrity.",[24,3506,3507],{},[88,3508,2414],{},[106,3510,3512],{"className":108,"code":3511,"language":110,"meta":111,"style":111},"import { createHmac } from 'crypto';\nconst hmac = createHmac('sha256', Buffer.from('my-shared-secret'));\nhmac.update('some message');\nconst digest = hmac.digest('hex');\n// Send `digest` alongside your message. The receiver recomputes using the same shared key.\n",[15,3513,3514,3527,3555,3569,3590],{"__ignoreMap":111},[115,3515,3516,3518,3521,3523,3525],{"class":117,"line":118},[115,3517,232],{"class":121},[115,3519,3520],{"class":132}," { createHmac } ",[115,3522,238],{"class":121},[115,3524,242],{"class":241},[115,3526,245],{"class":132},[115,3528,3529,3531,3534,3536,3539,3541,3543,3546,3548,3550,3553],{"class":117,"line":248},[115,3530,122],{"class":121},[115,3532,3533],{"class":125}," hmac",[115,3535,129],{"class":121},[115,3537,3538],{"class":136}," createHmac",[115,3540,287],{"class":132},[115,3542,2484],{"class":241},[115,3544,3545],{"class":132},", Buffer.",[115,3547,238],{"class":136},[115,3549,287],{"class":132},[115,3551,3552],{"class":241},"'my-shared-secret'",[115,3554,1148],{"class":132},[115,3556,3557,3560,3562,3564,3567],{"class":117,"line":255},[115,3558,3559],{"class":132},"hmac.",[115,3561,1031],{"class":136},[115,3563,287],{"class":132},[115,3565,3566],{"class":241},"'some message'",[115,3568,677],{"class":132},[115,3570,3571,3573,3576,3578,3581,3584,3586,3588],{"class":117,"line":261},[115,3572,122],{"class":121},[115,3574,3575],{"class":125}," digest",[115,3577,129],{"class":121},[115,3579,3580],{"class":132}," hmac.",[115,3582,3583],{"class":136},"digest",[115,3585,287],{"class":132},[115,3587,1313],{"class":241},[115,3589,677],{"class":132},[115,3591,3592],{"class":117,"line":296},[115,3593,3594],{"class":179},"// Send `digest` alongside your message. The receiver recomputes using the same shared key.\n",[210,3596],{},[10,3598,3600],{"id":3599},"_10-best-practices-security-considerations","10. Best Practices & Security Considerations",[31,3602,3603,3609,3615,3618,3632,3667,3726,3752,3766],{},[34,3604,3605,3608],{},[88,3606,3607],{},"Never hard-code private keys in your source."," Load them from a secure location (environment variable, container secret, secret manager).",[34,3610,526,3611,3614],{},[15,3612,3613],{},"createPrivateKey({ key: …, passphrase: … })"," if your PEM is encrypted.",[34,3616,3617],{},"Prefer RSA-PSS (with SHA-256 or SHA-512) for signatures over plain PKCS#1 v1.5, unless you have to interoperate with an older system expecting v1.5. PSS is provably secure under modern standards.",[34,3619,3620,3621,69,3623,3626,3627,58,3629,3631],{},"Unless you need streaming signing, use the one-liner ",[15,3622,892],{},[15,3624,3625],{},"crypto.verify(...)"," instead of managing a ",[15,3628,925],{},[15,3630,3497],{}," instance manually. It’s less code and less room for mistakes.",[34,3633,526,3634,3636,3637,3639,3640],{},[15,3635,22],{}," instead of raw PEM/",[15,3638,42],{}," where possible. This prevents accidental exposure or leaking of the raw key material in logs.",[106,3641,3643],{"className":108,"code":3642,"language":110,"meta":111,"style":111},"const privObj = createPrivateKey({ key: myPem, format: 'pem' });\n// Now pass `privObj` to sign/verify/encrypt/etc.—never pass the PEM again.\n",[15,3644,3645,3662],{"__ignoreMap":111},[115,3646,3647,3649,3651,3653,3655,3658,3660],{"class":117,"line":118},[115,3648,122],{"class":121},[115,3650,1939],{"class":125},[115,3652,129],{"class":121},[115,3654,449],{"class":136},[115,3656,3657],{"class":132},"({ key: myPem, format: ",[115,3659,367],{"class":241},[115,3661,815],{"class":132},[115,3663,3664],{"class":117,"line":248},[115,3665,3666],{"class":179},"// Now pass `privObj` to sign/verify/encrypt/etc.—never pass the PEM again.\n",[34,3668,3669,3672,3673,3720,3723,3724,43],{},[88,3670,3671],{},"Store keys securely at rest."," If you must store a private key on disk, encrypt the PEM with a strong passphrase:",[106,3674,3676],{"className":108,"code":3675,"language":110,"meta":111,"style":111},"generateKeyPairSync('rsa', {\n  /* … */,\n  privateKeyEncoding: { type: 'pkcs8', format: 'pem', cipher: 'aes-256-cbc', passphrase: '…' }\n});\n",[15,3677,3678,3688,3695,3716],{"__ignoreMap":111},[115,3679,3680,3682,3684,3686],{"class":117,"line":118},[115,3681,61],{"class":136},[115,3683,287],{"class":132},[115,3685,290],{"class":241},[115,3687,293],{"class":132},[115,3689,3690,3693],{"class":117,"line":248},[115,3691,3692],{"class":179},"  /* … */",[115,3694,305],{"class":132},[115,3696,3697,3699,3701,3703,3705,3707,3709,3711,3714],{"class":117,"line":255},[115,3698,1455],{"class":132},[115,3700,1458],{"class":241},[115,3702,1445],{"class":132},[115,3704,367],{"class":241},[115,3706,2901],{"class":132},[115,3708,378],{"class":241},[115,3710,1951],{"class":132},[115,3712,3713],{"class":241},"'…'",[115,3715,1465],{"class":132},[115,3717,3718],{"class":117,"line":261},[115,3719,405],{"class":132},[3721,3722],"br",{},"Or use a cloud KMS / hardware security module (HSM) so your application never directly touches the raw private key. Node can be configured to use signer callbacks (e.g., with AWS KMS, you call sign via an API instead of passing a local ",[15,3725,22],{},[34,3727,3728,3729,3732,3733,3732,3736,3739,3740,3743,3744,3732,3747,3732,3750,146],{},"Be aware of data‐inclusion sequences. Always do ",[15,3730,3731],{},"sign.update(data)"," → ",[15,3734,3735],{},"sign.end()",[15,3737,3738],{},"sign.sign(...)",". If you mix in different data or call ",[15,3741,3742],{},"sign.sign"," prematurely, the output is invalid. Similarly for verify: ",[15,3745,3746],{},"verify.update(...)",[15,3748,3749],{},"verify.end()",[15,3751,1814],{},[34,3753,3754,3755,3758,3759,205,3762,3765],{},"Select a secure hash (",[15,3756,3757],{},"SHA-256"," or above). Never use ",[15,3760,3761],{},"MD5",[15,3763,3764],{},"SHA-1"," for new designs.",[34,3767,3768,3769,3772],{},"If you only need integrity/authenticity (not non-repudiation) in a two-party setting, consider HMAC (",[15,3770,3771],{},"createHmac",") instead: fewer moving parts and easier key management. Only use asymmetric signing when you must publish a public key for verification by third parties.",[210,3774],{},[10,3776,3778],{"id":3777},"_11-quick-reference-table","11. Quick Reference Table",[3780,3781,3782,3798],"table",{},[3783,3784,3785],"thead",{},[3786,3787,3788,3792,3795],"tr",{},[3789,3790,3791],"th",{},"API",[3789,3793,3794],{},"Purpose",[3789,3796,3797],{},"Returns",[3799,3800,3801,3818,3833,3848,3863,3881,3902,3917,3935,3949,3963],"tbody",{},[3786,3802,3803,3809,3812],{},[3804,3805,3806],"td",{},[15,3807,3808],{},"generateKeyPairSync(type, options)",[3804,3810,3811],{},"Generate a new asymmetric key pair (RSA, EC, etc.)",[3804,3813,3814,3817],{},[15,3815,3816],{},"{ publicKey, privateKey }"," (PEM/DER strings)",[3786,3819,3820,3825,3830],{},[3804,3821,3822],{},[15,3823,3824],{},"generateKeyPair(type, options, callback)",[3804,3826,3827,3828],{},"Asynchronous version of ",[15,3829,61],{},[3804,3831,3832],{},"via callback",[3786,3834,3835,3839,3844],{},[3804,3836,3837],{},[15,3838,1837],{},[3804,3840,3841,3842],{},"Import a private key (PEM/DER/JWK) into a ",[15,3843,22],{},[3804,3845,3846],{},[15,3847,22],{},[3786,3849,3850,3854,3859],{},[3804,3851,3852],{},[15,3853,1970],{},[3804,3855,3856,3857],{},"Import a public key (PEM/DER/JWK) into a ",[15,3858,22],{},[3804,3860,3861],{},[15,3862,22],{},[3786,3864,3865,3870,3876],{},[3804,3866,3867],{},[15,3868,3869],{},"sign(algorithm, data, privateKey[, encoding])",[3804,3871,3872,3873,3875],{},"One-liner: hash data, sign with private key, return ",[15,3874,42],{}," or encoded string",[3804,3877,3878,3880],{},[15,3879,42],{}," or string",[3786,3882,3883,3887,3897],{},[3804,3884,3885],{},[15,3886,2212],{},[3804,3888,3889,3890,3893,3894],{},"Streamable \"Sign\" instance: call ",[15,3891,3892],{},".update(...)",", then ",[15,3895,3896],{},".sign(...)",[3804,3898,3899,3901],{},[15,3900,925],{}," instance",[3786,3903,3904,3909,3912],{},[3804,3905,3906],{},[15,3907,3908],{},"verify(algorithm, data, publicKey, signature)",[3804,3910,3911],{},"One-liner: verify signature against data and public key",[3804,3913,3914],{},[15,3915,3916],{},"boolean",[3786,3918,3919,3923,3931],{},[3804,3920,3921],{},[15,3922,2364],{},[3804,3924,3925,3926,3893,3928],{},"Streamable \"Verify\" instance: call ",[15,3927,3892],{},[15,3929,3930],{},".verify(...)",[3804,3932,3933,3901],{},[15,3934,3497],{},[3786,3936,3937,3942,3945],{},[3804,3938,3939],{},[15,3940,3941],{},"publicEncrypt(options, buffer)",[3804,3943,3944],{},"Encrypt with public key (usually RSA-OAEP)",[3804,3946,3947],{},[15,3948,42],{},[3786,3950,3951,3956,3959],{},[3804,3952,3953],{},[15,3954,3955],{},"privateDecrypt(options, buffer)",[3804,3957,3958],{},"Decrypt with private key (usually RSA-OAEP)",[3804,3960,3961],{},[15,3962,42],{},[3786,3964,3965,3970,3973],{},[3804,3966,3967],{},[15,3968,3969],{},"createHmac(algorithm, key)",[3804,3971,3972],{},"Compute an HMAC over data chunks—symmetric MAC",[3804,3974,3975,3901],{},[15,3976,3977],{},"Hmac",[210,3979],{},[19,3981,3983],{"id":3982},"encrypting-data-with-nodejs","Encrypting Data With Node.js",[24,3985,3986],{},"In a recent side project I came upon the need to securely store credentials in a database that I can later retrieve and use as part of the application. I know that Node.js has a very extensive crypto module, so I knew it was possible, though I wasn’t sure on the specifics.",[24,3988,3989],{},"Typically when storing passwords or other similar secrets, values are hashed but in my case I needed to encrypt/decrypt data since I need to access the original value after accessing it from my database. To make this work, we can use the createCipheriv function along with a secret key and initialization vector (IV) to encrypt and decrypt our data.",[106,3991,3993],{"className":108,"code":3992,"language":110,"meta":111,"style":111},"import crypto from \"node:crypto\"\n\nconst algorithm = \"aes-256-cbc\"\nconst secretKey = process.env.SECRET_KEY\n\nif (!secretKey) {\n  throw new Error(\"SECRET_KEY environment variable is required\")\n}\n\nconst key = crypto\n  .createHash(\"sha512\")\n  .update(secretKey)\n  .digest(\"hex\")\n  .substring(0, 32)\n\nconst iv = crypto.randomBytes(16)\n\nexport function encrypt(data: string) {\n  const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv)\n  let encrypted = cipher.update(data, \"utf-8\", \"hex\")\n  encrypted += cipher.final(\"hex\")\n\n  // Package the IV and encrypted data together so it can be stored in a single\n  // column in the database.\n  return iv.toString(\"hex\") + encrypted\n}\n\nexport function decrypt(data: string) {\n  // Unpackage the combined iv + encrypted message. Since we are using a fixed\n  // size IV, we can hard code the slice length.\n  const inputIV = data.slice(0, 32)\n  const encrypted = data.slice(32)\n  const decipher = crypto.createDecipheriv(\n    algorithm,\n    Buffer.from(key),\n    Buffer.from(inputIV, \"hex\"),\n  )\n\n  let decrypted = decipher.update(encrypted, \"hex\", \"utf-8\")\n  decrypted += decipher.final(\"utf-8\")\n  return decrypted\n}\n",[15,3994,3995,4007,4011,4023,4038,4042,4056,4074,4079,4083,4095,4110,4119,4132,4151,4155,4177,4181,4205,4228,4255,4274,4278,4283,4288,4310,4314,4318,4337,4342,4347,4372,4390,4406,4411,4421,4434,4439,4443,4468,4485,4492],{"__ignoreMap":111},[115,3996,3997,3999,4002,4004],{"class":117,"line":118},[115,3998,232],{"class":121},[115,4000,4001],{"class":132}," crypto ",[115,4003,238],{"class":121},[115,4005,4006],{"class":241}," \"node:crypto\"\n",[115,4008,4009],{"class":117,"line":248},[115,4010,252],{"emptyLinePlaceholder":251},[115,4012,4013,4015,4018,4020],{"class":117,"line":255},[115,4014,122],{"class":121},[115,4016,4017],{"class":125}," algorithm",[115,4019,129],{"class":121},[115,4021,4022],{"class":241}," \"aes-256-cbc\"\n",[115,4024,4025,4027,4030,4032,4035],{"class":117,"line":261},[115,4026,122],{"class":121},[115,4028,4029],{"class":125}," secretKey",[115,4031,129],{"class":121},[115,4033,4034],{"class":132}," process.env.",[115,4036,4037],{"class":125},"SECRET_KEY\n",[115,4039,4040],{"class":117,"line":296},[115,4041,252],{"emptyLinePlaceholder":251},[115,4043,4044,4047,4050,4053],{"class":117,"line":308},[115,4045,4046],{"class":121},"if",[115,4048,4049],{"class":132}," (",[115,4051,4052],{"class":121},"!",[115,4054,4055],{"class":132},"secretKey) {\n",[115,4057,4058,4061,4064,4067,4069,4072],{"class":117,"line":314},[115,4059,4060],{"class":121},"  throw",[115,4062,4063],{"class":121}," new",[115,4065,4066],{"class":136}," Error",[115,4068,287],{"class":132},[115,4070,4071],{"class":241},"\"SECRET_KEY environment variable is required\"",[115,4073,2505],{"class":132},[115,4075,4076],{"class":117,"line":329},[115,4077,4078],{"class":132},"}\n",[115,4080,4081],{"class":117,"line":338},[115,4082,252],{"emptyLinePlaceholder":251},[115,4084,4085,4087,4090,4092],{"class":117,"line":344},[115,4086,122],{"class":121},[115,4088,4089],{"class":125}," key",[115,4091,129],{"class":121},[115,4093,4094],{"class":132}," crypto\n",[115,4096,4097,4100,4103,4105,4108],{"class":117,"line":350},[115,4098,4099],{"class":132},"  .",[115,4101,4102],{"class":136},"createHash",[115,4104,287],{"class":132},[115,4106,4107],{"class":241},"\"sha512\"",[115,4109,2505],{"class":132},[115,4111,4112,4114,4116],{"class":117,"line":362},[115,4113,4099],{"class":132},[115,4115,1031],{"class":136},[115,4117,4118],{"class":132},"(secretKey)\n",[115,4120,4121,4123,4125,4127,4130],{"class":117,"line":372},[115,4122,4099],{"class":132},[115,4124,3583],{"class":136},[115,4126,287],{"class":132},[115,4128,4129],{"class":241},"\"hex\"",[115,4131,2505],{"class":132},[115,4133,4134,4136,4139,4141,4144,4146,4149],{"class":117,"line":387},[115,4135,4099],{"class":132},[115,4137,4138],{"class":136},"substring",[115,4140,287],{"class":132},[115,4142,4143],{"class":125},"0",[115,4145,272],{"class":132},[115,4147,4148],{"class":125},"32",[115,4150,2505],{"class":132},[115,4152,4153],{"class":117,"line":396},[115,4154,252],{"emptyLinePlaceholder":251},[115,4156,4157,4159,4162,4164,4167,4170,4172,4175],{"class":117,"line":402},[115,4158,122],{"class":121},[115,4160,4161],{"class":125}," iv",[115,4163,129],{"class":121},[115,4165,4166],{"class":132}," crypto.",[115,4168,4169],{"class":136},"randomBytes",[115,4171,287],{"class":132},[115,4173,4174],{"class":125},"16",[115,4176,2505],{"class":132},[115,4178,4179],{"class":117,"line":408},[115,4180,252],{"emptyLinePlaceholder":251},[115,4182,4183,4186,4189,4192,4194,4197,4199,4202],{"class":117,"line":413},[115,4184,4185],{"class":121},"export",[115,4187,4188],{"class":121}," function",[115,4190,4191],{"class":136}," encrypt",[115,4193,287],{"class":132},[115,4195,4196],{"class":1399},"data",[115,4198,843],{"class":121},[115,4200,4201],{"class":125}," string",[115,4203,4204],{"class":132},") {\n",[115,4206,4207,4210,4213,4215,4217,4220,4223,4225],{"class":117,"line":419},[115,4208,4209],{"class":121},"  const",[115,4211,4212],{"class":125}," cipher",[115,4214,129],{"class":121},[115,4216,4166],{"class":132},[115,4218,4219],{"class":136},"createCipheriv",[115,4221,4222],{"class":132},"(algorithm, Buffer.",[115,4224,238],{"class":136},[115,4226,4227],{"class":132},"(key), iv)\n",[115,4229,4230,4233,4236,4238,4241,4243,4246,4249,4251,4253],{"class":117,"line":425},[115,4231,4232],{"class":121},"  let",[115,4234,4235],{"class":132}," encrypted ",[115,4237,281],{"class":121},[115,4239,4240],{"class":132}," cipher.",[115,4242,1031],{"class":136},[115,4244,4245],{"class":132},"(data, ",[115,4247,4248],{"class":241},"\"utf-8\"",[115,4250,272],{"class":132},[115,4252,4129],{"class":241},[115,4254,2505],{"class":132},[115,4256,4257,4260,4263,4265,4268,4270,4272],{"class":117,"line":439},[115,4258,4259],{"class":132},"  encrypted ",[115,4261,4262],{"class":121},"+=",[115,4264,4240],{"class":132},[115,4266,4267],{"class":136},"final",[115,4269,287],{"class":132},[115,4271,4129],{"class":241},[115,4273,2505],{"class":132},[115,4275,4276],{"class":117,"line":455},[115,4277,252],{"emptyLinePlaceholder":251},[115,4279,4280],{"class":117,"line":461},[115,4281,4282],{"class":179},"  // Package the IV and encrypted data together so it can be stored in a single\n",[115,4284,4285],{"class":117,"line":471},[115,4286,4287],{"class":179},"  // column in the database.\n",[115,4289,4290,4293,4296,4298,4300,4302,4304,4307],{"class":117,"line":479},[115,4291,4292],{"class":121},"  return",[115,4294,4295],{"class":132}," iv.",[115,4297,1140],{"class":136},[115,4299,287],{"class":132},[115,4301,4129],{"class":241},[115,4303,2931],{"class":132},[115,4305,4306],{"class":121},"+",[115,4308,4309],{"class":132}," encrypted\n",[115,4311,4312],{"class":117,"line":484},[115,4313,4078],{"class":132},[115,4315,4316],{"class":117,"line":763},[115,4317,252],{"emptyLinePlaceholder":251},[115,4319,4320,4322,4324,4327,4329,4331,4333,4335],{"class":117,"line":774},[115,4321,4185],{"class":121},[115,4323,4188],{"class":121},[115,4325,4326],{"class":136}," decrypt",[115,4328,287],{"class":132},[115,4330,4196],{"class":1399},[115,4332,843],{"class":121},[115,4334,4201],{"class":125},[115,4336,4204],{"class":132},[115,4338,4339],{"class":117,"line":785},[115,4340,4341],{"class":179},"  // Unpackage the combined iv + encrypted message. Since we are using a fixed\n",[115,4343,4344],{"class":117,"line":791},[115,4345,4346],{"class":179},"  // size IV, we can hard code the slice length.\n",[115,4348,4349,4351,4354,4356,4359,4362,4364,4366,4368,4370],{"class":117,"line":797},[115,4350,4209],{"class":121},[115,4352,4353],{"class":125}," inputIV",[115,4355,129],{"class":121},[115,4357,4358],{"class":132}," data.",[115,4360,4361],{"class":136},"slice",[115,4363,287],{"class":132},[115,4365,4143],{"class":125},[115,4367,272],{"class":132},[115,4369,4148],{"class":125},[115,4371,2505],{"class":132},[115,4373,4374,4376,4378,4380,4382,4384,4386,4388],{"class":117,"line":818},[115,4375,4209],{"class":121},[115,4377,2448],{"class":125},[115,4379,129],{"class":121},[115,4381,4358],{"class":132},[115,4383,4361],{"class":136},[115,4385,287],{"class":132},[115,4387,4148],{"class":125},[115,4389,2505],{"class":132},[115,4391,4392,4394,4397,4399,4401,4404],{"class":117,"line":3287},[115,4393,4209],{"class":121},[115,4395,4396],{"class":125}," decipher",[115,4398,129],{"class":121},[115,4400,4166],{"class":132},[115,4402,4403],{"class":136},"createDecipheriv",[115,4405,1737],{"class":132},[115,4407,4408],{"class":117,"line":3293},[115,4409,4410],{"class":132},"    algorithm,\n",[115,4412,4413,4416,4418],{"class":117,"line":3313},[115,4414,4415],{"class":132},"    Buffer.",[115,4417,238],{"class":136},[115,4419,4420],{"class":132},"(key),\n",[115,4422,4423,4425,4427,4430,4432],{"class":117,"line":3328},[115,4424,4415],{"class":132},[115,4426,238],{"class":136},[115,4428,4429],{"class":132},"(inputIV, ",[115,4431,4129],{"class":241},[115,4433,2307],{"class":132},[115,4435,4436],{"class":117,"line":3333},[115,4437,4438],{"class":132},"  )\n",[115,4440,4441],{"class":117,"line":3338},[115,4442,252],{"emptyLinePlaceholder":251},[115,4444,4445,4447,4450,4452,4455,4457,4460,4462,4464,4466],{"class":117,"line":3344},[115,4446,4232],{"class":121},[115,4448,4449],{"class":132}," decrypted ",[115,4451,281],{"class":121},[115,4453,4454],{"class":132}," decipher.",[115,4456,1031],{"class":136},[115,4458,4459],{"class":132},"(encrypted, ",[115,4461,4129],{"class":241},[115,4463,272],{"class":132},[115,4465,4248],{"class":241},[115,4467,2505],{"class":132},[115,4469,4470,4473,4475,4477,4479,4481,4483],{"class":117,"line":3365},[115,4471,4472],{"class":132},"  decrypted ",[115,4474,4262],{"class":121},[115,4476,4454],{"class":132},[115,4478,4267],{"class":136},[115,4480,287],{"class":132},[115,4482,4248],{"class":241},[115,4484,2505],{"class":132},[115,4486,4487,4489],{"class":117,"line":3370},[115,4488,4292],{"class":121},[115,4490,4491],{"class":132}," decrypted\n",[115,4493,4494],{"class":117,"line":3387},[115,4495,4078],{"class":132},[24,4497,4498],{},"The nice thing about this implementation is that it returns a plain string with the IV and encrypted data sandwiched together. As long as you use the decrypt function, it knows how to properly decrypt the value making it really simple to store in a database.",[106,4500,4502],{"className":108,"code":4501,"language":110,"meta":111,"style":111},"const password = \"my secret password, don't tell anyone!\"\nconst encrypted = encrypt(password)\nconst decrypted = decrypt(encrypted)\n",[15,4503,4504,4516,4529],{"__ignoreMap":111},[115,4505,4506,4508,4511,4513],{"class":117,"line":118},[115,4507,122],{"class":121},[115,4509,4510],{"class":125}," password",[115,4512,129],{"class":121},[115,4514,4515],{"class":241}," \"my secret password, don't tell anyone!\"\n",[115,4517,4518,4520,4522,4524,4526],{"class":117,"line":248},[115,4519,122],{"class":121},[115,4521,2448],{"class":125},[115,4523,129],{"class":121},[115,4525,4191],{"class":136},[115,4527,4528],{"class":132},"(password)\n",[115,4530,4531,4533,4535,4537,4539],{"class":117,"line":255},[115,4532,122],{"class":121},[115,4534,2521],{"class":125},[115,4536,129],{"class":121},[115,4538,4326],{"class":136},[115,4540,4541],{"class":132},"(encrypted)\n",[24,4543,4544],{},"I’ll probably also explore re-implementing this same logic using the web crypto API. But that’s for another day!",[10,4546,4548],{"id":4547},"bottom-line","Bottom Line",[31,4550,4551,4561,4568,4578,4591],{},[34,4552,4553,69,4555,4557,4558,4560],{},[15,4554,68],{},[15,4556,72],{},": Turn PEM/DER/JWK into safe, in-memory ",[15,4559,22],{},"s.",[34,4562,4563,69,4565,4567],{},[15,4564,912],{},[15,4566,1653],{},": Build “sign” or “verify” streams for signing data incrementally.",[34,4569,4570,69,4572,4574,4575,4577],{},[15,4571,2068],{},[15,4573,2071],{},": One-line wrappers when you just have a single ",[15,4576,42],{},"/string payload.",[34,4579,4580,4581,272,4584,4587,4588,43],{},"When using RSA, prefer PSS padding. When using EC, pick a modern curve (e.g. ",[15,4582,4583],{},"prime256v1",[15,4585,4586],{},"secp384r1",", or ",[15,4589,4590],{},"Ed25519",[34,4592,4593,4594,4597],{},"Keep private keys encrypted at rest, load them via ",[15,4595,4596],{},"createPrivateKey({ passphrase })",", and never log raw PEM.",[24,4599,4600,4601,58,4603,2825,4605,58,4607,4609,4610,4612,4613,4615],{},"With that, you should have a clear mental map of how Node’s ",[15,4602,72],{},[15,4604,68],{},[15,4606,912],{},[15,4608,1653],{}," calls all fit together. If you need to do anything beyond signing (e.g. encryption, key exchange, HMAC), the rest of the ",[15,4611,17],{}," module follows the same pattern: import or generate a ",[15,4614,22],{},", pick an algorithm, feed in data, and call the appropriate one-line helper (or use a streamable object).",[4617,4618,4619],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}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);}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}",{"title":111,"searchDepth":248,"depth":248,"links":4621},[4622,4628,4632,4637,4639,4644,4648,4657,4658,4659,4660,4663],{"id":12,"depth":248,"text":4623,"children":4624},"1. Key Concepts in crypto",[4625,4626,4627],{"id":21,"depth":255,"text":22},{"id":81,"depth":255,"text":82},{"id":183,"depth":255,"text":184},{"id":214,"depth":248,"text":215,"children":4629},[4630,4631],{"id":218,"depth":255,"text":219},{"id":533,"depth":255,"text":534},{"id":908,"depth":248,"text":4633,"children":4634},"3. Signing Data (createSign)",[4635,4636],{"id":938,"depth":255,"text":939},{"id":1362,"depth":255,"text":1363},{"id":1649,"depth":248,"text":4638},"4. Verifying a Signature (createVerify)",{"id":1824,"depth":248,"text":4640,"children":4641},"5. createPrivateKey & createPublicKey in Detail",[4642,4643],{"id":1834,"depth":255,"text":1837},{"id":1967,"depth":255,"text":1970},{"id":2084,"depth":248,"text":2085,"children":4645},[4646,4647],{"id":2096,"depth":255,"text":2099},{"id":2250,"depth":255,"text":2253},{"id":2379,"depth":248,"text":2380,"children":4649},[4650,4652,4654,4655],{"id":2389,"depth":255,"text":4651},"crypto.publicEncrypt(publicKey, buffer) / crypto.privateDecrypt(privateKey, buffer)",{"id":2585,"depth":255,"text":4653},"crypto.privateEncrypt(privateKey, buffer) / crypto.publicDecrypt(publicKey, buffer)",{"id":2608,"depth":255,"text":2611},{"id":2821,"depth":255,"text":4656},"crypto.generateKeyPair() and crypto.generateKeyPairSync()",{"id":2964,"depth":248,"text":2965},{"id":3466,"depth":248,"text":3467},{"id":3599,"depth":248,"text":3600},{"id":3777,"depth":248,"text":3778,"children":4661},[4662],{"id":3982,"depth":255,"text":3983},{"id":4547,"depth":248,"text":4548},"backend","guide","2026-07-15","Key Concepts in nodejs crypto","md",null,"/knowledge-base/nodejs-crypto.png",{},"/knowledge-base/crypto","15",{"title":5,"description":4667},{"loc":4672},"knowledge-base/crypto",[4678,4679,4680,4681],"Node.js","Crypto","Security","Cryptography","e-Pcom4XcyKqkXmiL83E-Xw0D4u7lB5iiNT6hBRCeA4",[4684,4688],{"title":4685,"path":4686,"stem":4687,"children":-1},"CORS Header Selection Cheatsheet","/knowledge-base/cors","knowledge-base/cors",{"title":4689,"path":4690,"stem":4691,"children":-1},"Introduction to iptables","/knowledge-base/iptables","knowledge-base/iptables",1784306722458]