| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -243,14 +243,30 @@ added: v0.3.4 | |||
| 243 | 243 | * `requestListener` {Function} A listener to be added to the `'request'` event. | |
| 244 | 244 | * Returns: {https.Server} | |
| 245 | 245 | ||
| 246 | - ```js | ||
| 246 | + ```mjs | ||
| 247 | + // curl -k https://localhost:8000/ | ||
| 248 | + import { createServer } from 'node:https'; | ||
| 249 | + import { readFileSync } from 'node:fs'; | ||
| 250 | + | ||
| 251 | + const options = { | ||
| 252 | + key: readFileSync('private-key.pem'), | ||
| 253 | + cert: readFileSync('certificate.pem'), | ||
| 254 | + }; | ||
| 255 | + | ||
| 256 | + createServer(options, (req, res) => { | ||
| 257 | + res.writeHead(200); | ||
| 258 | + res.end('hello world\n'); | ||
| 259 | + }).listen(8000); | ||
| 260 | + ``` | ||
| 261 | + | ||
| 262 | + ```cjs | ||
| 247 | 263 | // curl -k https://localhost:8000/ | |
| 248 | 264 | const https = require('node:https'); | |
| 249 | 265 | const fs = require('node:fs'); | |
| 250 | 266 | ||
| 251 | 267 | const options = { | |
| 252 | - key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), | ||
| 253 | - cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), | ||
| 268 | + key: fs.readFileSync('private-key.pem'), | ||
| 269 | + cert: fs.readFileSync('certificate.pem'), | ||
| 254 | 270 | }; | |
| 255 | 271 | ||
| 256 | 272 | https.createServer(options, (req, res) => { | |
@@ -261,12 +277,27 @@ https.createServer(options, (req, res) => { | |||
| 261 | 277 | ||
| 262 | 278 | Or | |
| 263 | 279 | ||
| 264 | - ```js | ||
| 280 | + ```mjs | ||
| 281 | + import { createServer } from 'node:https'; | ||
| 282 | + import { readFileSync } from 'node:fs'; | ||
| 283 | + | ||
| 284 | + const options = { | ||
| 285 | + pfx: readFileSync('test_cert.pfx'), | ||
| 286 | + passphrase: 'sample', | ||
| 287 | + }; | ||
| 288 | + | ||
| 289 | + createServer(options, (req, res) => { | ||
| 290 | + res.writeHead(200); | ||
| 291 | + res.end('hello world\n'); | ||
| 292 | + }).listen(8000); | ||
| 293 | + ``` | ||
| 294 | + | ||
| 295 | + ```cjs | ||
| 265 | 296 | const https = require('node:https'); | |
| 266 | 297 | const fs = require('node:fs'); | |
| 267 | 298 | ||
| 268 | 299 | const options = { | |
| 269 | - pfx: fs.readFileSync('test/fixtures/test_cert.pfx'), | ||
| 300 | + pfx: fs.readFileSync('test_cert.pfx'), | ||
| 270 | 301 | passphrase: 'sample', | |
| 271 | 302 | }; | |
| 272 | 303 | ||
@@ -276,6 +307,20 @@ https.createServer(options, (req, res) => { | |||
| 276 | 307 | }).listen(8000); | |
| 277 | 308 | ``` | |
| 278 | 309 | ||
| 310 | + To generate the certificate and key for this example, run: | ||
| 311 | + | ||
| 312 | + ```bash | ||
| 313 | + openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \ | ||
| 314 | + -keyout private-key.pem -out certificate.pem | ||
| 315 | + ``` | ||
| 316 | + | ||
| 317 | + Then, to generate the `pfx` certificate for this example, run: | ||
| 318 | + | ||
| 319 | + ```bash | ||
| 320 | + openssl pkcs12 -certpbe AES-256-CBC -export -out test_cert.pfx \ | ||
| 321 | + -inkey private-key.pem -in certificate.pem -passout pass:sample | ||
| 322 | + ``` | ||
| 323 | + | ||
| 279 | 324 | ## `https.get(options[, callback])` | |
| 280 | 325 | ||
| 281 | 326 | ## `https.get(url[, options][, callback])` | |
@@ -303,7 +348,24 @@ Like [`http.get()`][] but for HTTPS. | |||
| 303 | 348 | string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][] | |
| 304 | 349 | object, it will be automatically converted to an ordinary `options` object. | |
| 305 | 350 | ||
| 306 | - ```js | ||
| 351 | + ```mjs | ||
| 352 | + import { get } from 'node:https'; | ||
| 353 | + import process from 'node:process'; | ||
| 354 | + | ||
| 355 | + get('https://encrypted.google.com/', (res) => { | ||
| 356 | + console.log('statusCode:', res.statusCode); | ||
| 357 | + console.log('headers:', res.headers); | ||
| 358 | + | ||
| 359 | + res.on('data', (d) => { | ||
| 360 | + process.stdout.write(d); | ||
| 361 | + }); | ||
| 362 | + | ||
| 363 | + }).on('error', (e) => { | ||
| 364 | + console.error(e); | ||
| 365 | + }); | ||
| 366 | + ``` | ||
| 367 | + | ||
| 368 | + ```cjs | ||
| 307 | 369 | const https = require('node:https'); | |
| 308 | 370 | ||
| 309 | 371 | https.get('https://encrypted.google.com/', (res) => { | |
@@ -394,7 +456,33 @@ object, it will be automatically converted to an ordinary `options` object. | |||
| 394 | 456 | class. The `ClientRequest` instance is a writable stream. If one needs to | |
| 395 | 457 | upload a file with a POST request, then write to the `ClientRequest` object. | |
| 396 | 458 | ||
| 397 | - ```js | ||
| 459 | + ```mjs | ||
| 460 | + import { request } from 'node:https'; | ||
| 461 | + import process from 'node:process'; | ||
| 462 | + | ||
| 463 | + const options = { | ||
| 464 | + hostname: 'encrypted.google.com', | ||
| 465 | + port: 443, | ||
| 466 | + path: '/', | ||
| 467 | + method: 'GET', | ||
| 468 | + }; | ||
| 469 | + | ||
| 470 | + const req = request(options, (res) => { | ||
| 471 | + console.log('statusCode:', res.statusCode); | ||
| 472 | + console.log('headers:', res.headers); | ||
| 473 | + | ||
| 474 | + res.on('data', (d) => { | ||
| 475 | + process.stdout.write(d); | ||
| 476 | + }); | ||
| 477 | + }); | ||
| 478 | + | ||
| 479 | + req.on('error', (e) => { | ||
| 480 | + console.error(e); | ||
| 481 | + }); | ||
| 482 | + req.end(); | ||
| 483 | + ``` | ||
| 484 | + | ||
| 485 | + ```cjs | ||
| 398 | 486 | const https = require('node:https'); | |
| 399 | 487 | ||
| 400 | 488 | const options = { | |
@@ -427,8 +515,8 @@ const options = { | |||
| 427 | 515 | port: 443, | |
| 428 | 516 | path: '/', | |
| 429 | 517 | method: 'GET', | |
| 430 | - key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), | ||
| 431 | - cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), | ||
| 518 | + key: fs.readFileSync('private-key.pem'), | ||
| 519 | + cert: fs.readFileSync('certificate.pem'), | ||
| 432 | 520 | }; | |
| 433 | 521 | options.agent = new https.Agent(options); | |
| 434 | 522 | ||
@@ -445,8 +533,8 @@ const options = { | |||
| 445 | 533 | port: 443, | |
| 446 | 534 | path: '/', | |
| 447 | 535 | method: 'GET', | |
| 448 | - key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), | ||
| 449 | - cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), | ||
| 536 | + key: fs.readFileSync('private-key.pem'), | ||
| 537 | + cert: fs.readFileSync('certificate.pem'), | ||
| 450 | 538 | agent: false, | |
| 451 | 539 | }; | |
| 452 | 540 | ||
@@ -468,7 +556,80 @@ const req = https.request(options, (res) => { | |||
| 468 | 556 | Example pinning on certificate fingerprint, or the public key (similar to | |
| 469 | 557 | `pin-sha256`): | |
| 470 | 558 | ||
| 471 | - ```js | ||
| 559 | + ```mjs | ||
| 560 | + import { checkServerIdentity } from 'node:tls'; | ||
| 561 | + import { Agent, request } from 'node:https'; | ||
| 562 | + import { createHash } from 'node:crypto'; | ||
| 563 | + | ||
| 564 | + function sha256(s) { | ||
| 565 | + return createHash('sha256').update(s).digest('base64'); | ||
| 566 | + } | ||
| 567 | + const options = { | ||
| 568 | + hostname: 'github.com', | ||
| 569 | + port: 443, | ||
| 570 | + path: '/', | ||
| 571 | + method: 'GET', | ||
| 572 | + checkServerIdentity: function(host, cert) { | ||
| 573 | + // Make sure the certificate is issued to the host we are connected to | ||
| 574 | + const err = checkServerIdentity(host, cert); | ||
| 575 | + if (err) { | ||
| 576 | + return err; | ||
| 577 | + } | ||
| 578 | + | ||
| 579 | + // Pin the public key, similar to HPKP pin-sha256 pinning | ||
| 580 | + const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='; | ||
| 581 | + if (sha256(cert.pubkey) !== pubkey256) { | ||
| 582 | + const msg = 'Certificate verification error: ' + | ||
| 583 | + `The public key of '${cert.subject.CN}' ` + | ||
| 584 | + 'does not match our pinned fingerprint'; | ||
| 585 | + return new Error(msg); | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + // Pin the exact certificate, rather than the pub key | ||
| 589 | + const cert256 = 'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + | ||
| 590 | + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'; | ||
| 591 | + if (cert.fingerprint256 !== cert256) { | ||
| 592 | + const msg = 'Certificate verification error: ' + | ||
| 593 | + `The certificate of '${cert.subject.CN}' ` + | ||
| 594 | + 'does not match our pinned fingerprint'; | ||
| 595 | + return new Error(msg); | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + // This loop is informational only. | ||
| 599 | + // Print the certificate and public key fingerprints of all certs in the | ||
| 600 | + // chain. Its common to pin the public key of the issuer on the public | ||
| 601 | + // internet, while pinning the public key of the service in sensitive | ||
| 602 | + // environments. | ||
| 603 | + let lastprint256; | ||
| 604 | + do { | ||
| 605 | + console.log('Subject Common Name:', cert.subject.CN); | ||
| 606 | + console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256); | ||
| 607 | + | ||
| 608 | + const hash = createHash('sha256'); | ||
| 609 | + console.log(' Public key ping-sha256:', sha256(cert.pubkey)); | ||
| 610 | + | ||
| 611 | + lastprint256 = cert.fingerprint256; | ||
| 612 | + cert = cert.issuerCertificate; | ||
| 613 | + } while (cert.fingerprint256 !== lastprint256); | ||
| 614 | + | ||
| 615 | + }, | ||
| 616 | + }; | ||
| 617 | + | ||
| 618 | + options.agent = new Agent(options); | ||
| 619 | + const req = request(options, (res) => { | ||
| 620 | + console.log('All OK. Server matched our pinned cert or public key'); | ||
| 621 | + console.log('statusCode:', res.statusCode); | ||
| 622 | + | ||
| 623 | + res.on('data', (d) => {}); | ||
| 624 | + }); | ||
| 625 | + | ||
| 626 | + req.on('error', (e) => { | ||
| 627 | + console.error(e.message); | ||
| 628 | + }); | ||
| 629 | + req.end(); | ||
| 630 | + ``` | ||
| 631 | + | ||
| 632 | + ```cjs | ||
| 472 | 633 | const tls = require('node:tls'); | |
| 473 | 634 | const https = require('node:https'); | |
| 474 | 635 | const crypto = require('node:crypto'); | |
@@ -489,7 +650,7 @@ const options = { | |||
| 489 | 650 | } | |
| 490 | 651 | ||
| 491 | 652 | // Pin the public key, similar to HPKP pin-sha256 pinning | |
| 492 | - const pubkey256 = 'pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU='; | ||
| 653 | + const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='; | ||
| 493 | 654 | if (sha256(cert.pubkey) !== pubkey256) { | |
| 494 | 655 | const msg = 'Certificate verification error: ' + | |
| 495 | 656 | `The public key of '${cert.subject.CN}' ` + | |
@@ -498,8 +659,8 @@ const options = { | |||
| 498 | 659 | } | |
| 499 | 660 | ||
| 500 | 661 | // Pin the exact certificate, rather than the pub key | |
| 501 | - const cert256 = '25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' + | ||
| 502 | - 'D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16'; | ||
| 662 | + const cert256 = 'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + | ||
| 663 | + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'; | ||
| 503 | 664 | if (cert.fingerprint256 !== cert256) { | |
| 504 | 665 | const msg = 'Certificate verification error: ' + | |
| 505 | 666 | `The certificate of '${cert.subject.CN}' ` + | |
@@ -530,8 +691,6 @@ options.agent = new https.Agent(options); | |||
| 530 | 691 | const req = https.request(options, (res) => { | |
| 531 | 692 | console.log('All OK. Server matched our pinned cert or public key'); | |
| 532 | 693 | console.log('statusCode:', res.statusCode); | |
| 533 | - // Print the HPKP values | ||
| 534 | - console.log('headers:', res.headers['public-key-pins']); | ||
| 535 | 694 | ||
| 536 | 695 | res.on('data', (d) => {}); | |
| 537 | 696 | }); | |
@@ -546,17 +705,19 @@ Outputs for example: | |||
| 546 | 705 | ||
| 547 | 706 | ```text | |
| 548 | 707 | Subject Common Name: github.com | |
| 549 | - Certificate SHA256 fingerprint: 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16 | ||
| 550 | - Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU= | ||
| 551 | - Subject Common Name: DigiCert SHA2 Extended Validation Server CA | ||
| 552 | - Certificate SHA256 fingerprint: 40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A | ||
| 553 | - Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho= | ||
| 554 | - Subject Common Name: DigiCert High Assurance EV Root CA | ||
| 555 | - Certificate SHA256 fingerprint: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF | ||
| 556 | - Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18= | ||
| 708 | + Certificate SHA256 fingerprint: FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65 | ||
| 709 | + Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8= | ||
| 710 | + Subject Common Name: Sectigo ECC Domain Validation Secure Server CA | ||
| 711 | + Certificate SHA256 fingerprint: 61:E9:73:75:E9:F6:DA:98:2F:F5:C1:9E:2F:94:E6:6C:4E:35:B6:83:7C:E3:B9:14:D2:24:5C:7F:5F:65:82:5F | ||
| 712 | + Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g= | ||
| 713 | + Subject Common Name: USERTrust ECC Certification Authority | ||
| 714 | + Certificate SHA256 fingerprint: A6:CF:64:DB:B4:C8:D5:FD:19:CE:48:89:60:68:DB:03:B5:33:A8:D1:33:6C:62:56:A8:7D:00:CB:B3:DE:F3:EA | ||
| 715 | + Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw= | ||
| 716 | + Subject Common Name: AAA Certificate Services | ||
| 717 | + Certificate SHA256 fingerprint: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 | ||
| 718 | + Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM= | ||
| 557 | 719 | All OK. Server matched our pinned cert or public key | |
| 558 | 720 | statusCode: 200 | |
| 559 | - headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains | ||
| 560 | 721 | ``` | |
| 561 | 722 | ||
| 562 | 723 | [`Agent`]: #class-httpsagent | |
| Back | FazBrowse Home | New Git URL |
0 commit comments