{
  "manifest": {
    "name": "node-forge",
    "version": "1.3.1",
    "description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
    "homepage": "https://github.com/digitalbazaar/forge",
    "author": {
      "name": "Digital Bazaar, Inc.",
      "email": "support@digitalbazaar.com",
      "url": "http://digitalbazaar.com/"
    },
    "contributors": [
      {
        "name": "Dave Longley",
        "email": "dlongley@digitalbazaar.com"
      },
      {
        "name": "David I. Lehn",
        "email": "dlehn@digitalbazaar.com"
      },
      {
        "name": "Stefan Siegl",
        "email": "stesie@brokenpipe.de"
      },
      {
        "name": "Christoph Dorn",
        "email": "christoph@christophdorn.com"
      }
    ],
    "devDependencies": {
      "browserify": "^16.5.2",
      "commander": "^2.20.0",
      "cross-env": "^5.2.1",
      "eslint": "^7.27.0",
      "eslint-config-digitalbazaar": "^2.8.0",
      "express": "^4.16.2",
      "karma": "^4.4.1",
      "karma-browserify": "^7.0.0",
      "karma-chrome-launcher": "^3.1.0",
      "karma-edge-launcher": "^0.4.2",
      "karma-firefox-launcher": "^1.3.0",
      "karma-ie-launcher": "^1.0.0",
      "karma-mocha": "^1.3.0",
      "karma-mocha-reporter": "^2.2.5",
      "karma-safari-launcher": "^1.0.0",
      "karma-sauce-launcher": "^2.0.2",
      "karma-sourcemap-loader": "^0.3.8",
      "karma-tap-reporter": "0.0.6",
      "karma-webpack": "^4.0.2",
      "mocha": "^5.2.0",
      "mocha-lcov-reporter": "^1.2.0",
      "nodejs-websocket": "^1.7.1",
      "nyc": "^15.1.0",
      "opts": "^1.2.7",
      "webpack": "^4.44.1",
      "webpack-cli": "^3.3.12",
      "worker-loader": "^2.0.0"
    },
    "repository": {
      "type": "git",
      "url": "https://github.com/digitalbazaar/forge"
    },
    "bugs": {
      "url": "https://github.com/digitalbazaar/forge/issues",
      "email": "support@digitalbazaar.com"
    },
    "license": "(BSD-3-Clause OR GPL-2.0)",
    "main": "lib/index.js",
    "files": [
      "lib/*.js",
      "flash/swf/*.swf",
      "dist/*.min.js",
      "dist/*.min.js.map"
    ],
    "engines": {
      "node": ">= 6.13.0"
    },
    "keywords": [
      "aes",
      "asn",
      "asn.1",
      "cbc",
      "crypto",
      "cryptography",
      "csr",
      "des",
      "gcm",
      "hmac",
      "http",
      "https",
      "md5",
      "network",
      "pkcs",
      "pki",
      "prng",
      "rc2",
      "rsa",
      "sha1",
      "sha256",
      "sha384",
      "sha512",
      "ssh",
      "tls",
      "x.509",
      "x509"
    ],
    "scripts": {
      "prepublish": "npm run build",
      "build": "webpack",
      "test-build": "webpack --config webpack-tests.config.js",
      "test": "npm run test-node",
      "test-node": "cross-env NODE_ENV=test mocha -t 30000 -R ${REPORTER:-spec} tests/unit/index.js",
      "test-karma": "karma start",
      "test-karma-sauce": "karma start karma-sauce.conf",
      "test-server": "node tests/server.js",
      "test-server-ws": "node tests/websockets/server-ws.js",
      "test-server-webid": "node tests/websockets/server-webid.js",
      "coverage": "rm -rf coverage && nyc --reporter=lcov --reporter=text-summary npm test",
      "coverage-ci": "rm -rf coverage && nyc --reporter=lcovonly npm test",
      "coverage-report": "nyc report",
      "lint": "eslint *.js lib/*.js tests/*.js tests/**/*.js examples/*.js flash/*.js"
    },
    "nyc": {
      "exclude": [
        "tests"
      ]
    },
    "jspm": {
      "format": "amd"
    },
    "browser": {
      "buffer": false,
      "crypto": false,
      "process": false
    },
    "_registry": "npm",
    "_loc": "/homez.1033/heliovt/.cache/yarn/v6/npm-node-forge-1.3.1-be8da2af243b2417d5f646a770663a92b7e9ded3-integrity/node_modules/node-forge/package.json",
    "readmeFilename": "README.md",
    "readme": "# Forge\n\n[![npm package](https://nodei.co/npm/node-forge.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/node-forge/)\n\n[![Build Status](https://github.com/digitalbazaar/forge/workflows/Main%20Checks/badge.svg)](https://github.com/digitalbazaar/forge/actions?query=workflow%3A%22Main+Checks%22)\n\nA native implementation of [TLS][] (and various other cryptographic tools) in\n[JavaScript][].\n\nIntroduction\n------------\n\nThe Forge software is a fully native implementation of the [TLS][] protocol\nin JavaScript, a set of cryptography utilities, and a set of tools for\ndeveloping Web Apps that utilize many network resources.\n\nPerformance\n------------\n\nForge is fast. Benchmarks against other popular JavaScript cryptography\nlibraries can be found here:\n\n* http://dominictarr.github.io/crypto-bench/\n* http://cryptojs.altervista.org/test/simulate-threading-speed_test.html\n\nDocumentation\n-------------\n\n* [Introduction](#introduction)\n* [Performance](#performance)\n* [Installation](#installation)\n* [Testing](#testing)\n* [Contributing](#contributing)\n\n### API\n\n* [Options](#options)\n\n### Transports\n\n* [TLS](#tls)\n* [HTTP](#http)\n* [SSH](#ssh)\n* [XHR](#xhr)\n* [Sockets](#socket)\n\n### Ciphers\n\n* [CIPHER](#cipher)\n* [AES](#aes)\n* [DES](#des)\n* [RC2](#rc2)\n\n### PKI\n\n* [ED25519](#ed25519)\n* [RSA](#rsa)\n* [RSA-KEM](#rsakem)\n* [X.509](#x509)\n* [PKCS#5](#pkcs5)\n* [PKCS#7](#pkcs7)\n* [PKCS#8](#pkcs8)\n* [PKCS#10](#pkcs10)\n* [PKCS#12](#pkcs12)\n* [ASN.1](#asn)\n\n### Message Digests\n\n* [SHA1](#sha1)\n* [SHA256](#sha256)\n* [SHA384](#sha384)\n* [SHA512](#sha512)\n* [MD5](#md5)\n* [HMAC](#hmac)\n\n### Utilities\n\n* [Prime](#prime)\n* [PRNG](#prng)\n* [Tasks](#task)\n* [Utilities](#util)\n* [Logging](#log)\n* [Flash Networking Support](#flash)\n\n### Other\n\n* [Security Considerations](#security-considerations)\n* [Library Background](#library-background)\n* [Contact](#contact)\n* [Donations](#donations)\n\n---------------------------------------\n\nInstallation\n------------\n\n**Note**: Please see the [Security Considerations](#security-considerations)\nsection before using packaging systems and pre-built files.\n\nForge uses a [CommonJS][] module structure with a build process for browser\nbundles. The older [0.6.x][] branch with standalone files is available but will\nnot be regularly updated.\n\n### Node.js\n\nIf you want to use forge with [Node.js][], it is available through `npm`:\n\nhttps://www.npmjs.com/package/node-forge\n\nInstallation:\n\n    npm install node-forge\n\nYou can then use forge as a regular module:\n\n```js\nvar forge = require('node-forge');\n```\n\nThe npm package includes pre-built `forge.min.js`, `forge.all.min.js`, and\n`prime.worker.min.js` using the [UMD][] format.\n\n### jsDelivr CDN\n\nTo use it via [jsDelivr](https://www.jsdelivr.com/package/npm/node-forge) include this in your html:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/node-forge@1.0.0/dist/forge.min.js\"></script>\n```\n\n### unpkg CDN\n\nTo use it via [unpkg](https://unpkg.com/#/) include this in your html:\n\n```html\n<script src=\"https://unpkg.com/node-forge@1.0.0/dist/forge.min.js\"></script>\n```\n\n### Development Requirements\n\nThe core JavaScript has the following requirements to build and test:\n\n* Building a browser bundle:\n  * Node.js\n  * npm\n* Testing\n  * Node.js\n  * npm\n  * Chrome, Firefox, Safari (optional)\n\nSome special networking features can optionally use a Flash component.  See the\n[Flash README](./flash/README.md) for details.\n\n### Building for a web browser\n\nTo create single file bundles for use with browsers run the following:\n\n    npm install\n    npm run build\n\nThis will create single non-minimized and minimized files that can be\nincluded in the browser:\n\n    dist/forge.js\n    dist/forge.min.js\n\nA bundle that adds some utilities and networking support is also available:\n\n    dist/forge.all.js\n    dist/forge.all.min.js\n\nInclude the file via:\n\n```html\n<script src=\"YOUR_SCRIPT_PATH/forge.js\"></script>\n```\nor\n```html\n<script src=\"YOUR_SCRIPT_PATH/forge.min.js\"></script>\n```\n\nThe above bundles will synchronously create a global 'forge' object.\n\n**Note**: These bundles will not include any WebWorker scripts (eg:\n`dist/prime.worker.js`), so these will need to be accessible from the browser\nif any WebWorkers are used.\n\n### Building a custom browser bundle\n\nThe build process uses [webpack][] and the [config](./webpack.config.js) file\ncan be modified to generate a file or files that only contain the parts of\nforge you need.\n\n[Browserify][] override support is also present in `package.json`.\n\nTesting\n-------\n\n### Prepare to run tests\n\n    npm install\n\n### Running automated tests with Node.js\n\nForge natively runs in a [Node.js][] environment:\n\n    npm test\n\n### Running automated tests with Headless Chrome\n\nAutomated testing is done via [Karma][]. By default it will run the tests with\nHeadless Chrome.\n\n    npm run test-karma\n\nIs 'mocha' reporter output too verbose? Other reporters are available. Try\n'dots', 'progress', or 'tap'.\n\n    npm run test-karma -- --reporters progress\n\nBy default [webpack][] is used. [Browserify][] can also be used.\n\n    BUNDLER=browserify npm run test-karma\n\n### Running automated tests with one or more browsers\n\nYou can also specify one or more browsers to use.\n\n    npm run test-karma -- --browsers Chrome,Firefox,Safari,ChromeHeadless\n\nThe reporter option and `BUNDLER` environment variable can also be used.\n\n### Running manual tests in a browser\n\nTesting in a browser uses [webpack][] to combine forge and all tests and then\nloading the result in a browser. A simple web server is provided that will\noutput the HTTP or HTTPS URLs to load. It also will start a simple Flash Policy\nServer. Unit tests and older legacy tests are provided. Custom ports can be\nused by running `node tests/server.js` manually.\n\nTo run the unit tests in a browser a special forge build is required:\n\n    npm run test-build\n\nTo run legacy browser based tests the main forge build is required:\n\n    npm run build\n\nThe tests are run with a custom server that prints out the URLs to use:\n\n    npm run test-server\n\n### Running other tests\n\nThere are some other random tests and benchmarks available in the tests\ndirectory.\n\n### Coverage testing\n\nTo perform coverage testing of the unit tests, run the following. The results\nwill be put in the `coverage/` directory. Note that coverage testing can slow\ndown some tests considerably.\n\n    npm install\n    npm run coverage\n\nContributing\n------------\n\nAny contributions (eg: PRs) that are accepted will be brought under the same\nlicense used by the rest of the Forge project. This license allows Forge to\nbe used under the terms of either the BSD License or the GNU General Public\nLicense (GPL) Version 2.\n\nSee: [LICENSE](https://github.com/digitalbazaar/forge/blob/cbebca3780658703d925b61b2caffb1d263a6c1d/LICENSE)\n\nIf a contribution contains 3rd party source code with its own license, it\nmay retain it, so long as that license is compatible with the Forge license.\n\nAPI\n---\n\n<a name=\"options\" />\n\n### Options\n\nIf at any time you wish to disable the use of native code, where available,\nfor particular forge features like its secure random number generator, you\nmay set the ```forge.options.usePureJavaScript``` flag to ```true```. It is\nnot recommended that you set this flag as native code is typically more\nperformant and may have stronger security properties. It may be useful to\nset this flag to test certain features that you plan to run in environments\nthat are different from your testing environment.\n\nTo disable native code when including forge in the browser:\n\n```js\n// run this *after* including the forge script\nforge.options.usePureJavaScript = true;\n```\n\nTo disable native code when using Node.js:\n\n```js\nvar forge = require('node-forge');\nforge.options.usePureJavaScript = true;\n```\n\nTransports\n----------\n\n<a name=\"tls\" />\n\n### TLS\n\nProvides a native javascript client and server-side [TLS][] implementation.\n\n__Examples__\n\n```js\n// create TLS client\nvar client = forge.tls.createConnection({\n  server: false,\n  caStore: /* Array of PEM-formatted certs or a CA store object */,\n  sessionCache: {},\n  // supported cipher suites in order of preference\n  cipherSuites: [\n    forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,\n    forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],\n  virtualHost: 'example.com',\n  verify: function(connection, verified, depth, certs) {\n    if(depth === 0) {\n      var cn = certs[0].subject.getField('CN').value;\n      if(cn !== 'example.com') {\n        verified = {\n          alert: forge.tls.Alert.Description.bad_certificate,\n          message: 'Certificate common name does not match hostname.'\n        };\n      }\n    }\n    return verified;\n  },\n  connected: function(connection) {\n    console.log('connected');\n    // send message to server\n    connection.prepare(forge.util.encodeUtf8('Hi server!'));\n    /* NOTE: experimental, start heartbeat retransmission timer\n    myHeartbeatTimer = setInterval(function() {\n      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));\n    }, 5*60*1000);*/\n  },\n  /* provide a client-side cert if you want\n  getCertificate: function(connection, hint) {\n    return myClientCertificate;\n  },\n  /* the private key for the client-side cert if provided */\n  getPrivateKey: function(connection, cert) {\n    return myClientPrivateKey;\n  },\n  tlsDataReady: function(connection) {\n    // TLS data (encrypted) is ready to be sent to the server\n    sendToServerSomehow(connection.tlsData.getBytes());\n    // if you were communicating with the server below, you'd do:\n    // server.process(connection.tlsData.getBytes());\n  },\n  dataReady: function(connection) {\n    // clear data from the server is ready\n    console.log('the server sent: ' +\n      forge.util.decodeUtf8(connection.data.getBytes()));\n    // close connection\n    connection.close();\n  },\n  /* NOTE: experimental\n  heartbeatReceived: function(connection, payload) {\n    // restart retransmission timer, look at payload\n    clearInterval(myHeartbeatTimer);\n    myHeartbeatTimer = setInterval(function() {\n      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));\n    }, 5*60*1000);\n    payload.getBytes();\n  },*/\n  closed: function(connection) {\n    console.log('disconnected');\n  },\n  error: function(connection, error) {\n    console.log('uh oh', error);\n  }\n});\n\n// start the handshake process\nclient.handshake();\n\n// when encrypted TLS data is received from the server, process it\nclient.process(encryptedBytesFromServer);\n\n// create TLS server\nvar server = forge.tls.createConnection({\n  server: true,\n  caStore: /* Array of PEM-formatted certs or a CA store object */,\n  sessionCache: {},\n  // supported cipher suites in order of preference\n  cipherSuites: [\n    forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,\n    forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],\n  // require a client-side certificate if you want\n  verifyClient: true,\n  verify: function(connection, verified, depth, certs) {\n    if(depth === 0) {\n      var cn = certs[0].subject.getField('CN').value;\n      if(cn !== 'the-client') {\n        verified = {\n          alert: forge.tls.Alert.Description.bad_certificate,\n          message: 'Certificate common name does not match expected client.'\n        };\n      }\n    }\n    return verified;\n  },\n  connected: function(connection) {\n    console.log('connected');\n    // send message to client\n    connection.prepare(forge.util.encodeUtf8('Hi client!'));\n    /* NOTE: experimental, start heartbeat retransmission timer\n    myHeartbeatTimer = setInterval(function() {\n      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));\n    }, 5*60*1000);*/\n  },\n  getCertificate: function(connection, hint) {\n    return myServerCertificate;\n  },\n  getPrivateKey: function(connection, cert) {\n    return myServerPrivateKey;\n  },\n  tlsDataReady: function(connection) {\n    // TLS data (encrypted) is ready to be sent to the client\n    sendToClientSomehow(connection.tlsData.getBytes());\n    // if you were communicating with the client above you'd do:\n    // client.process(connection.tlsData.getBytes());\n  },\n  dataReady: function(connection) {\n    // clear data from the client is ready\n    console.log('the client sent: ' +\n      forge.util.decodeUtf8(connection.data.getBytes()));\n    // close connection\n    connection.close();\n  },\n  /* NOTE: experimental\n  heartbeatReceived: function(connection, payload) {\n    // restart retransmission timer, look at payload\n    clearInterval(myHeartbeatTimer);\n    myHeartbeatTimer = setInterval(function() {\n      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));\n    }, 5*60*1000);\n    payload.getBytes();\n  },*/\n  closed: function(connection) {\n    console.log('disconnected');\n  },\n  error: function(connection, error) {\n    console.log('uh oh', error);\n  }\n});\n\n// when encrypted TLS data is received from the client, process it\nserver.process(encryptedBytesFromClient);\n```\n\nConnect to a TLS server using node's net.Socket:\n\n```js\nvar socket = new net.Socket();\n\nvar client = forge.tls.createConnection({\n  server: false,\n  verify: function(connection, verified, depth, certs) {\n    // skip verification for testing\n    console.log('[tls] server certificate verified');\n    return true;\n  },\n  connected: function(connection) {\n    console.log('[tls] connected');\n    // prepare some data to send (note that the string is interpreted as\n    // 'binary' encoded, which works for HTTP which only uses ASCII, use\n    // forge.util.encodeUtf8(str) otherwise\n    client.prepare('GET / HTTP/1.0\\r\\n\\r\\n');\n  },\n  tlsDataReady: function(connection) {\n    // encrypted data is ready to be sent to the server\n    var data = connection.tlsData.getBytes();\n    socket.write(data, 'binary'); // encoding should be 'binary'\n  },\n  dataReady: function(connection) {\n    // clear data from the server is ready\n    var data = connection.data.getBytes();\n    console.log('[tls] data received from the server: ' + data);\n  },\n  closed: function() {\n    console.log('[tls] disconnected');\n  },\n  error: function(connection, error) {\n    console.log('[tls] error', error);\n  }\n});\n\nsocket.on('connect', function() {\n  console.log('[socket] connected');\n  client.handshake();\n});\nsocket.on('data', function(data) {\n  client.process(data.toString('binary')); // encoding should be 'binary'\n});\nsocket.on('end', function() {\n  console.log('[socket] disconnected');\n});\n\n// connect to google.com\nsocket.connect(443, 'google.com');\n\n// or connect to gmail's imap server (but don't send the HTTP header above)\n//socket.connect(993, 'imap.gmail.com');\n```\n\n<a name=\"http\" />\n\n### HTTP\n\nProvides a native [JavaScript][] mini-implementation of an http client that\nuses pooled sockets.\n\n__Examples__\n\n```js\n// create an HTTP GET request\nvar request = forge.http.createRequest({method: 'GET', path: url.path});\n\n// send the request somewhere\nsendSomehow(request.toString());\n\n// receive response\nvar buffer = forge.util.createBuffer();\nvar response = forge.http.createResponse();\nvar someAsyncDataHandler = function(bytes) {\n  if(!response.bodyReceived) {\n    buffer.putBytes(bytes);\n    if(!response.headerReceived) {\n      if(response.readHeader(buffer)) {\n        console.log('HTTP response header: ' + response.toString());\n      }\n    }\n    if(response.headerReceived && !response.bodyReceived) {\n      if(response.readBody(buffer)) {\n        console.log('HTTP response body: ' + response.body);\n      }\n    }\n  }\n};\n```\n\n<a name=\"ssh\" />\n\n### SSH\n\nProvides some SSH utility functions.\n\n__Examples__\n\n```js\n// encodes (and optionally encrypts) a private RSA key as a Putty PPK file\nforge.ssh.privateKeyToPutty(privateKey, passphrase, comment);\n\n// encodes a public RSA key as an OpenSSH file\nforge.ssh.publicKeyToOpenSSH(key, comment);\n\n// encodes a private RSA key as an OpenSSH file\nforge.ssh.privateKeyToOpenSSH(privateKey, passphrase);\n\n// gets the SSH public key fingerprint in a byte buffer\nforge.ssh.getPublicKeyFingerprint(key);\n\n// gets a hex-encoded, colon-delimited SSH public key fingerprint\nforge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});\n```\n\n<a name=\"xhr\" />\n\n### XHR\n\nProvides an XmlHttpRequest implementation using forge.http as a backend.\n\n__Examples__\n\n```js\n// TODO\n```\n\n<a name=\"socket\" />\n\n### Sockets\n\nProvides an interface to create and use raw sockets provided via Flash.\n\n__Examples__\n\n```js\n// TODO\n```\n\nCiphers\n-------\n\n<a name=\"cipher\" />\n\n### CIPHER\n\nProvides a basic API for block encryption and decryption. There is built-in\nsupport for the ciphers: [AES][], [3DES][], and [DES][], and for the modes\nof operation: [ECB][], [CBC][], [CFB][], [OFB][], [CTR][], and [GCM][].\n\nThese algorithms are currently supported:\n\n* AES-ECB\n* AES-CBC\n* AES-CFB\n* AES-OFB\n* AES-CTR\n* AES-GCM\n* 3DES-ECB\n* 3DES-CBC\n* DES-ECB\n* DES-CBC\n\nWhen using an [AES][] algorithm, the key size will determine whether\nAES-128, AES-192, or AES-256 is used (all are supported). When a [DES][]\nalgorithm is used, the key size will determine whether [3DES][] or regular\n[DES][] is used. Use a [3DES][] algorithm to enforce Triple-DES.\n\n__Examples__\n\n```js\n// generate a random key and IV\n// Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256\nvar key = forge.random.getBytesSync(16);\nvar iv = forge.random.getBytesSync(16);\n\n/* alternatively, generate a password-based 16-byte key\nvar salt = forge.random.getBytesSync(128);\nvar key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);\n*/\n\n// encrypt some bytes using CBC mode\n// (other modes include: ECB, CFB, OFB, CTR, and GCM)\n// Note: CBC and ECB modes use PKCS#7 padding as default\nvar cipher = forge.cipher.createCipher('AES-CBC', key);\ncipher.start({iv: iv});\ncipher.update(forge.util.createBuffer(someBytes));\ncipher.finish();\nvar encrypted = cipher.output;\n// outputs encrypted hex\nconsole.log(encrypted.toHex());\n\n// decrypt some bytes using CBC mode\n// (other modes include: CFB, OFB, CTR, and GCM)\nvar decipher = forge.cipher.createDecipher('AES-CBC', key);\ndecipher.start({iv: iv});\ndecipher.update(encrypted);\nvar result = decipher.finish(); // check 'result' for true/false\n// outputs decrypted hex\nconsole.log(decipher.output.toHex());\n\n// decrypt bytes using CBC mode and streaming\n// Performance can suffer for large multi-MB inputs due to buffer\n// manipulations. Stream processing in chunks can offer significant\n// improvement. CPU intensive update() calls could also be performed with\n// setImmediate/setTimeout to avoid blocking the main browser UI thread (not\n// shown here). Optimal block size depends on the JavaScript VM and other\n// factors. Encryption can use a simple technique for increased performance.\nvar encryptedBytes = encrypted.bytes();\nvar decipher = forge.cipher.createDecipher('AES-CBC', key);\ndecipher.start({iv: iv});\nvar length = encryptedBytes.length;\nvar chunkSize = 1024 * 64;\nvar index = 0;\nvar decrypted = '';\ndo {\n  decrypted += decipher.output.getBytes();\n  var buf = forge.util.createBuffer(encryptedBytes.substr(index, chunkSize));\n  decipher.update(buf);\n  index += chunkSize;\n} while(index < length);\nvar result = decipher.finish();\nassert(result);\ndecrypted += decipher.output.getBytes();\nconsole.log(forge.util.bytesToHex(decrypted));\n\n// encrypt some bytes using GCM mode\nvar cipher = forge.cipher.createCipher('AES-GCM', key);\ncipher.start({\n  iv: iv, // should be a 12-byte binary-encoded string or byte buffer\n  additionalData: 'binary-encoded string', // optional\n  tagLength: 128 // optional, defaults to 128 bits\n});\ncipher.update(forge.util.createBuffer(someBytes));\ncipher.finish();\nvar encrypted = cipher.output;\nvar tag = cipher.mode.tag;\n// outputs encrypted hex\nconsole.log(encrypted.toHex());\n// outputs authentication tag\nconsole.log(tag.toHex());\n\n// decrypt some bytes using GCM mode\nvar decipher = forge.cipher.createDecipher('AES-GCM', key);\ndecipher.start({\n  iv: iv,\n  additionalData: 'binary-encoded string', // optional\n  tagLength: 128, // optional, defaults to 128 bits\n  tag: tag // authentication tag from encryption\n});\ndecipher.update(encrypted);\nvar pass = decipher.finish();\n// pass is false if there was a failure (eg: authentication tag didn't match)\nif(pass) {\n  // outputs decrypted hex\n  console.log(decipher.output.toHex());\n}\n```\n\nUsing forge in Node.js to match openssl's \"enc\" command line tool (**Note**: OpenSSL \"enc\" uses a non-standard file format with a custom key derivation function and a fixed iteration count of 1, which some consider less secure than alternatives such as [OpenPGP](https://tools.ietf.org/html/rfc4880)/[GnuPG](https://www.gnupg.org/)):\n\n```js\nvar forge = require('node-forge');\nvar fs = require('fs');\n\n// openssl enc -des3 -in input.txt -out input.enc\nfunction encrypt(password) {\n  var input = fs.readFileSync('input.txt', {encoding: 'binary'});\n\n  // 3DES key and IV sizes\n  var keySize = 24;\n  var ivSize = 8;\n\n  // get derived bytes\n  // Notes:\n  // 1. If using an alternative hash (eg: \"-md sha1\") pass\n  //   \"forge.md.sha1.create()\" as the final parameter.\n  // 2. If using \"-nosalt\", set salt to null.\n  var salt = forge.random.getBytesSync(8);\n  // var md = forge.md.sha1.create(); // \"-md sha1\"\n  var derivedBytes = forge.pbe.opensslDeriveBytes(\n    password, salt, keySize + ivSize/*, md*/);\n  var buffer = forge.util.createBuffer(derivedBytes);\n  var key = buffer.getBytes(keySize);\n  var iv = buffer.getBytes(ivSize);\n\n  var cipher = forge.cipher.createCipher('3DES-CBC', key);\n  cipher.start({iv: iv});\n  cipher.update(forge.util.createBuffer(input, 'binary'));\n  cipher.finish();\n\n  var output = forge.util.createBuffer();\n\n  // if using a salt, prepend this to the output:\n  if(salt !== null) {\n    output.putBytes('Salted__'); // (add to match openssl tool output)\n    output.putBytes(salt);\n  }\n  output.putBuffer(cipher.output);\n\n  fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'});\n}\n\n// openssl enc -d -des3 -in input.enc -out input.dec.txt\nfunction decrypt(password) {\n  var input = fs.readFileSync('input.enc', {encoding: 'binary'});\n\n  // parse salt from input\n  input = forge.util.createBuffer(input, 'binary');\n  // skip \"Salted__\" (if known to be present)\n  input.getBytes('Salted__'.length);\n  // read 8-byte salt\n  var salt = input.getBytes(8);\n\n  // Note: if using \"-nosalt\", skip above parsing and use\n  // var salt = null;\n\n  // 3DES key and IV sizes\n  var keySize = 24;\n  var ivSize = 8;\n\n  var derivedBytes = forge.pbe.opensslDeriveBytes(\n    password, salt, keySize + ivSize);\n  var buffer = forge.util.createBuffer(derivedBytes);\n  var key = buffer.getBytes(keySize);\n  var iv = buffer.getBytes(ivSize);\n\n  var decipher = forge.cipher.createDecipher('3DES-CBC', key);\n  decipher.start({iv: iv});\n  decipher.update(input);\n  var result = decipher.finish(); // check 'result' for true/false\n\n  fs.writeFileSync(\n    'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'});\n}\n```\n\n<a name=\"aes\" />\n\n### AES\n\nProvides [AES][] encryption and decryption in [CBC][], [CFB][], [OFB][],\n[CTR][], and [GCM][] modes. See [CIPHER](#cipher) for examples.\n\n<a name=\"des\" />\n\n### DES\n\nProvides [3DES][] and [DES][] encryption and decryption in [ECB][] and\n[CBC][] modes. See [CIPHER](#cipher) for examples.\n\n<a name=\"rc2\" />\n\n### RC2\n\n__Examples__\n\n```js\n// generate a random key and IV\nvar key = forge.random.getBytesSync(16);\nvar iv = forge.random.getBytesSync(8);\n\n// encrypt some bytes\nvar cipher = forge.rc2.createEncryptionCipher(key);\ncipher.start(iv);\ncipher.update(forge.util.createBuffer(someBytes));\ncipher.finish();\nvar encrypted = cipher.output;\n// outputs encrypted hex\nconsole.log(encrypted.toHex());\n\n// decrypt some bytes\nvar cipher = forge.rc2.createDecryptionCipher(key);\ncipher.start(iv);\ncipher.update(encrypted);\ncipher.finish();\n// outputs decrypted hex\nconsole.log(cipher.output.toHex());\n```\n\nPKI\n---\n\nProvides [X.509][] certificate support, ED25519 key generation and\nsigning/verifying, and RSA public and private key encoding, decoding,\nencryption/decryption, and signing/verifying.\n\n<a name=\"ed25519\" />\n\n### ED25519\n\nSpecial thanks to [TweetNaCl.js][] for providing the bulk of the implementation.\n\n__Examples__\n\n```js\nvar ed25519 = forge.pki.ed25519;\n\n// generate a random ED25519 keypair\nvar keypair = ed25519.generateKeyPair();\n// `keypair.publicKey` is a node.js Buffer or Uint8Array\n// `keypair.privateKey` is a node.js Buffer or Uint8Array\n\n// generate a random ED25519 keypair based on a random 32-byte seed\nvar seed = forge.random.getBytesSync(32);\nvar keypair = ed25519.generateKeyPair({seed: seed});\n\n// generate a random ED25519 keypair based on a \"password\" 32-byte seed\nvar password = 'Mai9ohgh6ahxee0jutheew0pungoozil';\nvar seed = new forge.util.ByteBuffer(password, 'utf8');\nvar keypair = ed25519.generateKeyPair({seed: seed});\n\n// sign a UTF-8 message\nvar signature = ED25519.sign({\n  message: 'test',\n  // also accepts `binary` if you want to pass a binary string\n  encoding: 'utf8',\n  // node.js Buffer, Uint8Array, forge ByteBuffer, binary string\n  privateKey: privateKey\n});\n// `signature` is a node.js Buffer or Uint8Array\n\n// sign a message passed as a buffer\nvar signature = ED25519.sign({\n  // also accepts a forge ByteBuffer or Uint8Array\n  message: Buffer.from('test', 'utf8'),\n  privateKey: privateKey\n});\n\n// sign a message digest (shorter \"message\" == better performance)\nvar md = forge.md.sha256.create();\nmd.update('test', 'utf8');\nvar signature = ED25519.sign({\n  md: md,\n  privateKey: privateKey\n});\n\n// verify a signature on a UTF-8 message\nvar verified = ED25519.verify({\n  message: 'test',\n  encoding: 'utf8',\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  signature: signature,\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  publicKey: publicKey\n});\n// `verified` is true/false\n\n// sign a message passed as a buffer\nvar verified = ED25519.verify({\n  // also accepts a forge ByteBuffer or Uint8Array\n  message: Buffer.from('test', 'utf8'),\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  signature: signature,\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  publicKey: publicKey\n});\n\n// verify a signature on a message digest\nvar md = forge.md.sha256.create();\nmd.update('test', 'utf8');\nvar verified = ED25519.verify({\n  md: md,\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  signature: signature,\n  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string\n  publicKey: publicKey\n});\n```\n\n<a name=\"rsa\" />\n\n### RSA\n\n__Examples__\n\n```js\nvar rsa = forge.pki.rsa;\n\n// generate an RSA key pair synchronously\n// *NOT RECOMMENDED*: Can be significantly slower than async and may block\n// JavaScript execution. Will use native Node.js 10.12.0+ API if possible.\nvar keypair = rsa.generateKeyPair({bits: 2048, e: 0x10001});\n\n// generate an RSA key pair asynchronously (uses web workers if available)\n// use workers: -1 to run a fast core estimator to optimize # of workers\n// *RECOMMENDED*: Can be significantly faster than sync. Will use native\n// Node.js 10.12.0+ or WebCrypto API if possible.\nrsa.generateKeyPair({bits: 2048, workers: 2}, function(err, keypair) {\n  // keypair.privateKey, keypair.publicKey\n});\n\n// generate an RSA key pair in steps that attempt to run for a specified period\n// of time on the main JS thread\nvar state = rsa.createKeyPairGenerationState(2048, 0x10001);\nvar step = function() {\n  // run for 100 ms\n  if(!rsa.stepKeyPairGenerationState(state, 100)) {\n    setTimeout(step, 1);\n  }\n  else {\n    // done, turn off progress indicator, use state.keys\n  }\n};\n// turn on progress indicator, schedule generation to run\nsetTimeout(step);\n\n// sign data with a private key and output DigestInfo DER-encoded bytes\n// (defaults to RSASSA PKCS#1 v1.5)\nvar md = forge.md.sha1.create();\nmd.update('sign this', 'utf8');\nvar signature = privateKey.sign(md);\n\n// verify data with a public key\n// (defaults to RSASSA PKCS#1 v1.5)\nvar verified = publicKey.verify(md.digest().bytes(), signature);\n\n// sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based\n// masking function MGF1, and a 20 byte salt\nvar md = forge.md.sha1.create();\nmd.update('sign this', 'utf8');\nvar pss = forge.pss.create({\n  md: forge.md.sha1.create(),\n  mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),\n  saltLength: 20\n  // optionally pass 'prng' with a custom PRNG implementation\n  // optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt\n});\nvar signature = privateKey.sign(md, pss);\n\n// verify RSASSA-PSS signature\nvar pss = forge.pss.create({\n  md: forge.md.sha1.create(),\n  mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),\n  saltLength: 20\n  // optionally pass 'prng' with a custom PRNG implementation\n});\nvar md = forge.md.sha1.create();\nmd.update('sign this', 'utf8');\npublicKey.verify(md.digest().getBytes(), signature, pss);\n\n// encrypt data with a public key (defaults to RSAES PKCS#1 v1.5)\nvar encrypted = publicKey.encrypt(bytes);\n\n// decrypt data with a private key (defaults to RSAES PKCS#1 v1.5)\nvar decrypted = privateKey.decrypt(encrypted);\n\n// encrypt data with a public key using RSAES PKCS#1 v1.5\nvar encrypted = publicKey.encrypt(bytes, 'RSAES-PKCS1-V1_5');\n\n// decrypt data with a private key using RSAES PKCS#1 v1.5\nvar decrypted = privateKey.decrypt(encrypted, 'RSAES-PKCS1-V1_5');\n\n// encrypt data with a public key using RSAES-OAEP\nvar encrypted = publicKey.encrypt(bytes, 'RSA-OAEP');\n\n// decrypt data with a private key using RSAES-OAEP\nvar decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP');\n\n// encrypt data with a public key using RSAES-OAEP/SHA-256\nvar encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {\n  md: forge.md.sha256.create()\n});\n\n// decrypt data with a private key using RSAES-OAEP/SHA-256\nvar decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {\n  md: forge.md.sha256.create()\n});\n\n// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1\n// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding\nvar encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {\n  md: forge.md.sha256.create(),\n  mgf1: {\n    md: forge.md.sha1.create()\n  }\n});\n\n// decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1\n// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding\nvar decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {\n  md: forge.md.sha256.create(),\n  mgf1: {\n    md: forge.md.sha1.create()\n  }\n});\n\n```\n\n<a name=\"rsakem\" />\n\n### RSA-KEM\n\n__Examples__\n\n```js\n// generate an RSA key pair asynchronously (uses web workers if available)\n// use workers: -1 to run a fast core estimator to optimize # of workers\nforge.rsa.generateKeyPair({bits: 2048, workers: -1}, function(err, keypair) {\n  // keypair.privateKey, keypair.publicKey\n});\n\n// generate and encapsulate a 16-byte secret key\nvar kdf1 = new forge.kem.kdf1(forge.md.sha1.create());\nvar kem = forge.kem.rsa.create(kdf1);\nvar result = kem.encrypt(keypair.publicKey, 16);\n// result has 'encapsulation' and 'key'\n\n// encrypt some bytes\nvar iv = forge.random.getBytesSync(12);\nvar someBytes = 'hello world!';\nvar cipher = forge.cipher.createCipher('AES-GCM', result.key);\ncipher.start({iv: iv});\ncipher.update(forge.util.createBuffer(someBytes));\ncipher.finish();\nvar encrypted = cipher.output.getBytes();\nvar tag = cipher.mode.tag.getBytes();\n\n// send 'encrypted', 'iv', 'tag', and result.encapsulation to recipient\n\n// decrypt encapsulated 16-byte secret key\nvar kdf1 = new forge.kem.kdf1(forge.md.sha1.create());\nvar kem = forge.kem.rsa.create(kdf1);\nvar key = kem.decrypt(keypair.privateKey, result.encapsulation, 16);\n\n// decrypt some bytes\nvar decipher = forge.cipher.createDecipher('AES-GCM', key);\ndecipher.start({iv: iv, tag: tag});\ndecipher.update(forge.util.createBuffer(encrypted));\nvar pass = decipher.finish();\n// pass is false if there was a failure (eg: authentication tag didn't match)\nif(pass) {\n  // outputs 'hello world!'\n  console.log(decipher.output.getBytes());\n}\n\n```\n\n<a name=\"x509\" />\n\n### X.509\n\n__Examples__\n\n```js\nvar pki = forge.pki;\n\n// convert a PEM-formatted public key to a Forge public key\nvar publicKey = pki.publicKeyFromPem(pem);\n\n// convert a Forge public key to PEM-format\nvar pem = pki.publicKeyToPem(publicKey);\n\n// convert an ASN.1 SubjectPublicKeyInfo to a Forge public key\nvar publicKey = pki.publicKeyFromAsn1(subjectPublicKeyInfo);\n\n// convert a Forge public key to an ASN.1 SubjectPublicKeyInfo\nvar subjectPublicKeyInfo = pki.publicKeyToAsn1(publicKey);\n\n// gets a SHA-1 RSAPublicKey fingerprint a byte buffer\npki.getPublicKeyFingerprint(key);\n\n// gets a SHA-1 SubjectPublicKeyInfo fingerprint a byte buffer\npki.getPublicKeyFingerprint(key, {type: 'SubjectPublicKeyInfo'});\n\n// gets a hex-encoded, colon-delimited SHA-1 RSAPublicKey public key fingerprint\npki.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});\n\n// gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprint\npki.getPublicKeyFingerprint(key, {\n  type: 'SubjectPublicKeyInfo',\n  encoding: 'hex',\n  delimiter: ':'\n});\n\n// gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprint\npki.getPublicKeyFingerprint(key, {\n  md: forge.md.md5.create(),\n  encoding: 'hex',\n  delimiter: ':'\n});\n\n// creates a CA store\nvar caStore = pki.createCaStore([/* PEM-encoded cert */, ...]);\n\n// add a certificate to the CA store\ncaStore.addCertificate(certObjectOrPemString);\n\n// gets the issuer (its certificate) for the given certificate\nvar issuerCert = caStore.getIssuer(subjectCert);\n\n// verifies a certificate chain against a CA store\npki.verifyCertificateChain(caStore, chain, customVerifyCallback);\n\n// signs a certificate using the given private key\ncert.sign(privateKey);\n\n// signs a certificate using SHA-256 instead of SHA-1\ncert.sign(privateKey, forge.md.sha256.create());\n\n// verifies an issued certificate using the certificates public key\nvar verified = issuer.verify(issued);\n\n// generate a keypair and create an X.509v3 certificate\nvar keys = pki.rsa.generateKeyPair(2048);\nvar cert = pki.createCertificate();\ncert.publicKey = keys.publicKey;\n// alternatively set public key from a csr\n//cert.publicKey = csr.publicKey;\n// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.\n// Conforming CAs should ensure serialNumber is:\n// - no more than 20 octets\n// - non-negative (prefix a '00' if your value starts with a '1' bit)\ncert.serialNumber = '01';\ncert.validity.notBefore = new Date();\ncert.validity.notAfter = new Date();\ncert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);\nvar attrs = [{\n  name: 'commonName',\n  value: 'example.org'\n}, {\n  name: 'countryName',\n  value: 'US'\n}, {\n  shortName: 'ST',\n  value: 'Virginia'\n}, {\n  name: 'localityName',\n  value: 'Blacksburg'\n}, {\n  name: 'organizationName',\n  value: 'Test'\n}, {\n  shortName: 'OU',\n  value: 'Test'\n}];\ncert.setSubject(attrs);\n// alternatively set subject from a csr\n//cert.setSubject(csr.subject.attributes);\ncert.setIssuer(attrs);\ncert.setExtensions([{\n  name: 'basicConstraints',\n  cA: true\n}, {\n  name: 'keyUsage',\n  keyCertSign: true,\n  digitalSignature: true,\n  nonRepudiation: true,\n  keyEncipherment: true,\n  dataEncipherment: true\n}, {\n  name: 'extKeyUsage',\n  serverAuth: true,\n  clientAuth: true,\n  codeSigning: true,\n  emailProtection: true,\n  timeStamping: true\n}, {\n  name: 'nsCertType',\n  client: true,\n  server: true,\n  email: true,\n  objsign: true,\n  sslCA: true,\n  emailCA: true,\n  objCA: true\n}, {\n  name: 'subjectAltName',\n  altNames: [{\n    type: 6, // URI\n    value: 'http://example.org/webid#me'\n  }, {\n    type: 7, // IP\n    ip: '127.0.0.1'\n  }]\n}, {\n  name: 'subjectKeyIdentifier'\n}]);\n/* alternatively set extensions from a csr\nvar extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;\n// optionally add more extensions\nextensions.push.apply(extensions, [{\n  name: 'basicConstraints',\n  cA: true\n}, {\n  name: 'keyUsage',\n  keyCertSign: true,\n  digitalSignature: true,\n  nonRepudiation: true,\n  keyEncipherment: true,\n  dataEncipherment: true\n}]);\ncert.setExtensions(extensions);\n*/\n// self-sign certificate\ncert.sign(keys.privateKey);\n\n// convert a Forge certificate to PEM\nvar pem = pki.certificateToPem(cert);\n\n// convert a Forge certificate from PEM\nvar cert = pki.certificateFromPem(pem);\n\n// convert an ASN.1 X.509x3 object to a Forge certificate\nvar cert = pki.certificateFromAsn1(obj);\n\n// convert a Forge certificate to an ASN.1 X.509v3 object\nvar asn1Cert = pki.certificateToAsn1(cert);\n```\n\n<a name=\"pkcs5\" />\n\n### PKCS#5\n\nProvides the password-based key-derivation function from [PKCS#5][].\n\n__Examples__\n\n```js\n// generate a password-based 16-byte key\n// note an optional message digest can be passed as the final parameter\nvar salt = forge.random.getBytesSync(128);\nvar derivedKey = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);\n\n// generate key asynchronously\n// note an optional message digest can be passed before the callback\nforge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey) {\n  // do something w/derivedKey\n});\n```\n\n<a name=\"pkcs7\" />\n\n### PKCS#7\n\nProvides cryptographically protected messages from [PKCS#7][].\n\n__Examples__\n\n```js\n// convert a message from PEM\nvar p7 = forge.pkcs7.messageFromPem(pem);\n// look at p7.recipients\n\n// find a recipient by the issuer of a certificate\nvar recipient = p7.findRecipient(cert);\n\n// decrypt\np7.decrypt(p7.recipients[0], privateKey);\n\n// create a p7 enveloped message\nvar p7 = forge.pkcs7.createEnvelopedData();\n\n// add a recipient\nvar cert = forge.pki.certificateFromPem(certPem);\np7.addRecipient(cert);\n\n// set content\np7.content = forge.util.createBuffer('Hello');\n\n// encrypt\np7.encrypt();\n\n// convert message to PEM\nvar pem = forge.pkcs7.messageToPem(p7);\n\n// create a degenerate PKCS#7 certificate container\n// (CRLs not currently supported, only certificates)\nvar p7 = forge.pkcs7.createSignedData();\np7.addCertificate(certOrCertPem1);\np7.addCertificate(certOrCertPem2);\nvar pem = forge.pkcs7.messageToPem(p7);\n\n// create PKCS#7 signed data with authenticatedAttributes\n// attributes include: PKCS#9 content-type, message-digest, and signing-time\nvar p7 = forge.pkcs7.createSignedData();\np7.content = forge.util.createBuffer('Some content to be signed.', 'utf8');\np7.addCertificate(certOrCertPem);\np7.addSigner({\n  key: privateKeyAssociatedWithCert,\n  certificate: certOrCertPem,\n  digestAlgorithm: forge.pki.oids.sha256,\n  authenticatedAttributes: [{\n    type: forge.pki.oids.contentType,\n    value: forge.pki.oids.data\n  }, {\n    type: forge.pki.oids.messageDigest\n    // value will be auto-populated at signing time\n  }, {\n    type: forge.pki.oids.signingTime,\n    // value can also be auto-populated at signing time\n    value: new Date()\n  }]\n});\np7.sign();\nvar pem = forge.pkcs7.messageToPem(p7);\n\n// PKCS#7 Sign in detached mode.\n// Includes the signature and certificate without the signed data.\np7.sign({detached: true});\n\n```\n\n<a name=\"pkcs8\" />\n\n### PKCS#8\n\n__Examples__\n\n```js\nvar pki = forge.pki;\n\n// convert a PEM-formatted private key to a Forge private key\nvar privateKey = pki.privateKeyFromPem(pem);\n\n// convert a Forge private key to PEM-format\nvar pem = pki.privateKeyToPem(privateKey);\n\n// convert an ASN.1 PrivateKeyInfo or RSAPrivateKey to a Forge private key\nvar privateKey = pki.privateKeyFromAsn1(rsaPrivateKey);\n\n// convert a Forge private key to an ASN.1 RSAPrivateKey\nvar rsaPrivateKey = pki.privateKeyToAsn1(privateKey);\n\n// wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfo\nvar privateKeyInfo = pki.wrapRsaPrivateKey(rsaPrivateKey);\n\n// convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM\nvar pem = pki.privateKeyInfoToPem(privateKeyInfo);\n\n// encrypts a PrivateKeyInfo using a custom password and\n// outputs an EncryptedPrivateKeyInfo\nvar encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo(\n  privateKeyInfo, 'myCustomPasswordHere', {\n    algorithm: 'aes256', // 'aes128', 'aes192', 'aes256', '3des'\n  });\n\n// decrypts an ASN.1 EncryptedPrivateKeyInfo that was encrypted\n// with a custom password\nvar privateKeyInfo = pki.decryptPrivateKeyInfo(\n  encryptedPrivateKeyInfo, 'myCustomPasswordHere');\n\n// converts an EncryptedPrivateKeyInfo to PEM\nvar pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);\n\n// converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format\nvar encryptedPrivateKeyInfo = pki.encryptedPrivateKeyFromPem(pem);\n\n// wraps and encrypts a Forge private key and outputs it in PEM format\nvar pem = pki.encryptRsaPrivateKey(privateKey, 'password');\n\n// encrypts a Forge private key and outputs it in PEM format using OpenSSL's\n// proprietary legacy format + encapsulated PEM headers (DEK-Info)\nvar pem = pki.encryptRsaPrivateKey(privateKey, 'password', {legacy: true});\n\n// decrypts a PEM-formatted, encrypted private key\nvar privateKey = pki.decryptRsaPrivateKey(pem, 'password');\n\n// sets an RSA public key from a private key\nvar publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e);\n```\n\n<a name=\"pkcs10\" />\n\n### PKCS#10\n\nProvides certification requests or certificate signing requests (CSR) from\n[PKCS#10][].\n\n__Examples__\n\n```js\n// generate a key pair\nvar keys = forge.pki.rsa.generateKeyPair(2048);\n\n// create a certification request (CSR)\nvar csr = forge.pki.createCertificationRequest();\ncsr.publicKey = keys.publicKey;\ncsr.setSubject([{\n  name: 'commonName',\n  value: 'example.org'\n}, {\n  name: 'countryName',\n  value: 'US'\n}, {\n  shortName: 'ST',\n  value: 'Virginia'\n}, {\n  name: 'localityName',\n  value: 'Blacksburg'\n}, {\n  name: 'organizationName',\n  value: 'Test'\n}, {\n  shortName: 'OU',\n  value: 'Test'\n}]);\n// set (optional) attributes\ncsr.setAttributes([{\n  name: 'challengePassword',\n  value: 'password'\n}, {\n  name: 'unstructuredName',\n  value: 'My Company, Inc.'\n}, {\n  name: 'extensionRequest',\n  extensions: [{\n    name: 'subjectAltName',\n    altNames: [{\n      // 2 is DNS type\n      type: 2,\n      value: 'test.domain.com'\n    }, {\n      type: 2,\n      value: 'other.domain.com',\n    }, {\n      type: 2,\n      value: 'www.domain.net'\n    }]\n  }]\n}]);\n\n// sign certification request\ncsr.sign(keys.privateKey);\n\n// verify certification request\nvar verified = csr.verify();\n\n// convert certification request to PEM-format\nvar pem = forge.pki.certificationRequestToPem(csr);\n\n// convert a Forge certification request from PEM-format\nvar csr = forge.pki.certificationRequestFromPem(pem);\n\n// get an attribute\ncsr.getAttribute({name: 'challengePassword'});\n\n// get extensions array\ncsr.getAttribute({name: 'extensionRequest'}).extensions;\n\n```\n\n<a name=\"pkcs12\" />\n\n### PKCS#12\n\nProvides the cryptographic archive file format from [PKCS#12][].\n\n**Note for Chrome/Firefox/iOS/similar users**: If you have trouble importing\na PKCS#12 container, try using the TripleDES algorithm. It can be passed\nto `forge.pkcs12.toPkcs12Asn1` using the `{algorithm: '3des'}` option.\n\n__Examples__\n\n```js\n// decode p12 from base64\nvar p12Der = forge.util.decode64(p12b64);\n// get p12 as ASN.1 object\nvar p12Asn1 = forge.asn1.fromDer(p12Der);\n// decrypt p12 using the password 'password'\nvar p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');\n// decrypt p12 using non-strict parsing mode (resolves some ASN.1 parse errors)\nvar p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, 'password');\n// decrypt p12 using literally no password (eg: Mac OS X/apple push)\nvar p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1);\n// decrypt p12 using an \"empty\" password (eg: OpenSSL with no password input)\nvar p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, '');\n// p12.safeContents is an array of safe contents, each of\n// which contains an array of safeBags\n\n// get bags by friendlyName\nvar bags = p12.getBags({friendlyName: 'test'});\n// bags are key'd by attribute type (here \"friendlyName\")\n// and the key values are an array of matching objects\nvar cert = bags.friendlyName[0];\n\n// get bags by localKeyId\nvar bags = p12.getBags({localKeyId: buffer});\n// bags are key'd by attribute type (here \"localKeyId\")\n// and the key values are an array of matching objects\nvar cert = bags.localKeyId[0];\n\n// get bags by localKeyId (input in hex)\nvar bags = p12.getBags({localKeyIdHex: '7b59377ff142d0be4565e9ac3d396c01401cd879'});\n// bags are key'd by attribute type (here \"localKeyId\", *not* \"localKeyIdHex\")\n// and the key values are an array of matching objects\nvar cert = bags.localKeyId[0];\n\n// get bags by type\nvar bags = p12.getBags({bagType: forge.pki.oids.certBag});\n// bags are key'd by bagType and each bagType key's value\n// is an array of matches (in this case, certificate objects)\nvar cert = bags[forge.pki.oids.certBag][0];\n\n// get bags by friendlyName and filter on bag type\nvar bags = p12.getBags({\n  friendlyName: 'test',\n  bagType: forge.pki.oids.certBag\n});\n\n// get key bags\nvar bags = p12.getBags({bagType: forge.pki.oids.keyBag});\n// get key\nvar bag = bags[forge.pki.oids.keyBag][0];\nvar key = bag.key;\n// if the key is in a format unrecognized by forge then\n// bag.key will be `null`, use bag.asn1 to get the ASN.1\n// representation of the key\nif(bag.key === null) {\n  var keyAsn1 = bag.asn1;\n  // can now convert back to DER/PEM/etc for export\n}\n\n// generate a p12 using AES (default)\nvar p12Asn1 = forge.pkcs12.toPkcs12Asn1(\n  privateKey, certificateChain, 'password');\n\n// generate a p12 that can be imported by Chrome/Firefox/iOS\n// (requires the use of Triple DES instead of AES)\nvar p12Asn1 = forge.pkcs12.toPkcs12Asn1(\n  privateKey, certificateChain, 'password',\n  {algorithm: '3des'});\n\n// base64-encode p12\nvar p12Der = forge.asn1.toDer(p12Asn1).getBytes();\nvar p12b64 = forge.util.encode64(p12Der);\n\n// create download link for p12\nvar a = document.createElement('a');\na.download = 'example.p12';\na.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12b64);\na.appendChild(document.createTextNode('Download'));\n```\n\n<a name=\"asn\" />\n\n### ASN.1\n\nProvides [ASN.1][] DER encoding and decoding.\n\n__Examples__\n\n```js\nvar asn1 = forge.asn1;\n\n// create a SubjectPublicKeyInfo\nvar subjectPublicKeyInfo =\n  asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [\n    // AlgorithmIdentifier\n    asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [\n      // algorithm\n      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,\n        asn1.oidToDer(pki.oids['rsaEncryption']).getBytes()),\n      // parameters (null)\n      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')\n    ]),\n    // subjectPublicKey\n    asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, [\n      // RSAPublicKey\n      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [\n        // modulus (n)\n        asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,\n          _bnToBytes(key.n)),\n        // publicExponent (e)\n        asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,\n          _bnToBytes(key.e))\n      ])\n    ])\n  ]);\n\n// serialize an ASN.1 object to DER format\nvar derBuffer = asn1.toDer(subjectPublicKeyInfo);\n\n// deserialize to an ASN.1 object from a byte buffer filled with DER data\nvar object = asn1.fromDer(derBuffer);\n\n// convert an OID dot-separated string to a byte buffer\nvar derOidBuffer = asn1.oidToDer('1.2.840.113549.1.1.5');\n\n// convert a byte buffer with a DER-encoded OID to a dot-separated string\nconsole.log(asn1.derToOid(derOidBuffer));\n// output: 1.2.840.113549.1.1.5\n\n// validates that an ASN.1 object matches a particular ASN.1 structure and\n// captures data of interest from that structure for easy access\nvar publicKeyValidator = {\n  name: 'SubjectPublicKeyInfo',\n  tagClass: asn1.Class.UNIVERSAL,\n  type: asn1.Type.SEQUENCE,\n  constructed: true,\n  captureAsn1: 'subjectPublicKeyInfo',\n  value: [{\n    name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',\n    tagClass: asn1.Class.UNIVERSAL,\n    type: asn1.Type.SEQUENCE,\n    constructed: true,\n    value: [{\n      name: 'AlgorithmIdentifier.algorithm',\n      tagClass: asn1.Class.UNIVERSAL,\n      type: asn1.Type.OID,\n      constructed: false,\n      capture: 'publicKeyOid'\n    }]\n  }, {\n    // subjectPublicKey\n    name: 'SubjectPublicKeyInfo.subjectPublicKey',\n    tagClass: asn1.Class.UNIVERSAL,\n    type: asn1.Type.BITSTRING,\n    constructed: false,\n    value: [{\n      // RSAPublicKey\n      name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',\n      tagClass: asn1.Class.UNIVERSAL,\n      type: asn1.Type.SEQUENCE,\n      constructed: true,\n      optional: true,\n      captureAsn1: 'rsaPublicKey'\n    }]\n  }]\n};\n\nvar capture = {};\nvar errors = [];\nif(!asn1.validate(\n  publicKeyValidator, subjectPublicKeyInfo, validator, capture, errors)) {\n  throw 'ASN.1 object is not a SubjectPublicKeyInfo.';\n}\n// capture.subjectPublicKeyInfo contains the full ASN.1 object\n// capture.rsaPublicKey contains the full ASN.1 object for the RSA public key\n// capture.publicKeyOid only contains the value for the OID\nvar oid = asn1.derToOid(capture.publicKeyOid);\nif(oid !== pki.oids['rsaEncryption']) {\n  throw 'Unsupported OID.';\n}\n\n// pretty print an ASN.1 object to a string for debugging purposes\nasn1.prettyPrint(object);\n```\n\nMessage Digests\n----------------\n\n<a name=\"sha1\" />\n\n### SHA1\n\nProvides [SHA-1][] message digests.\n\n__Examples__\n\n```js\nvar md = forge.md.sha1.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n```\n\n<a name=\"sha256\" />\n\n### SHA256\n\nProvides [SHA-256][] message digests.\n\n__Examples__\n\n```js\nvar md = forge.md.sha256.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592\n```\n\n<a name=\"sha384\" />\n\n### SHA384\n\nProvides [SHA-384][] message digests.\n\n__Examples__\n\n```js\nvar md = forge.md.sha384.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1\n```\n\n<a name=\"sha512\" />\n\n### SHA512\n\nProvides [SHA-512][] message digests.\n\n__Examples__\n\n```js\n// SHA-512\nvar md = forge.md.sha512.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6\n\n// SHA-512/224\nvar md = forge.md.sha512.sha224.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: 944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37\n\n// SHA-512/256\nvar md = forge.md.sha512.sha256.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d\n```\n\n<a name=\"md5\" />\n\n### MD5\n\nProvides [MD5][] message digests.\n\n__Examples__\n\n```js\nvar md = forge.md.md5.create();\nmd.update('The quick brown fox jumps over the lazy dog');\nconsole.log(md.digest().toHex());\n// output: 9e107d9d372bb6826bd81d3542a419d6\n```\n\n<a name=\"hmac\" />\n\n### HMAC\n\nProvides [HMAC][] w/any supported message digest algorithm.\n\n__Examples__\n\n```js\nvar hmac = forge.hmac.create();\nhmac.start('sha1', 'Jefe');\nhmac.update('what do ya want for nothing?');\nconsole.log(hmac.digest().toHex());\n// output: effcdf6ae5eb2fa2d27416d5f184df9c259a7c79\n```\n\nUtilities\n---------\n\n<a name=\"prime\" />\n\n### Prime\n\nProvides an API for generating large, random, probable primes.\n\n__Examples__\n\n```js\n// generate a random prime on the main JS thread\nvar bits = 1024;\nforge.prime.generateProbablePrime(bits, function(err, num) {\n  console.log('random prime', num.toString(16));\n});\n\n// generate a random prime using Web Workers (if available, otherwise\n// falls back to the main thread)\nvar bits = 1024;\nvar options = {\n  algorithm: {\n    name: 'PRIMEINC',\n    workers: -1 // auto-optimize # of workers\n  }\n};\nforge.prime.generateProbablePrime(bits, options, function(err, num) {\n  console.log('random prime', num.toString(16));\n});\n```\n\n<a name=\"prng\" />\n\n### PRNG\n\nProvides a [Fortuna][]-based cryptographically-secure pseudo-random number\ngenerator, to be used with a cryptographic function backend, e.g. [AES][]. An\nimplementation using [AES][] as a backend is provided. An API for collecting\nentropy is given, though if window.crypto.getRandomValues is available, it will\nbe used automatically.\n\n__Examples__\n\n```js\n// get some random bytes synchronously\nvar bytes = forge.random.getBytesSync(32);\nconsole.log(forge.util.bytesToHex(bytes));\n\n// get some random bytes asynchronously\nforge.random.getBytes(32, function(err, bytes) {\n  console.log(forge.util.bytesToHex(bytes));\n});\n\n// collect some entropy if you'd like\nforge.random.collect(someRandomBytes);\njQuery().mousemove(function(e) {\n  forge.random.collectInt(e.clientX, 16);\n  forge.random.collectInt(e.clientY, 16);\n});\n\n// specify a seed file for use with the synchronous API if you'd like\nforge.random.seedFileSync = function(needed) {\n  // get 'needed' number of random bytes from somewhere\n  return fetchedRandomBytes;\n};\n\n// specify a seed file for use with the asynchronous API if you'd like\nforge.random.seedFile = function(needed, callback) {\n  // get the 'needed' number of random bytes from somewhere\n  callback(null, fetchedRandomBytes);\n});\n\n// register the main thread to send entropy or a Web Worker to receive\n// entropy on demand from the main thread\nforge.random.registerWorker(self);\n\n// generate a new instance of a PRNG with no collected entropy\nvar myPrng = forge.random.createInstance();\n```\n\n<a name=\"task\" />\n\n### Tasks\n\nProvides queuing and synchronizing tasks in a web application.\n\n__Examples__\n\n```js\n// TODO\n```\n\n<a name=\"util\" />\n\n### Utilities\n\nProvides utility functions, including byte buffer support, base64,\nbytes to/from hex, zlib inflate/deflate, etc.\n\n__Examples__\n\n```js\n// encode/decode base64\nvar encoded = forge.util.encode64(str);\nvar str = forge.util.decode64(encoded);\n\n// encode/decode UTF-8\nvar encoded = forge.util.encodeUtf8(str);\nvar str = forge.util.decodeUtf8(encoded);\n\n// bytes to/from hex\nvar bytes = forge.util.hexToBytes(hex);\nvar hex = forge.util.bytesToHex(bytes);\n\n// create an empty byte buffer\nvar buffer = forge.util.createBuffer();\n// create a byte buffer from raw binary bytes\nvar buffer = forge.util.createBuffer(input, 'raw');\n// create a byte buffer from utf8 bytes\nvar buffer = forge.util.createBuffer(input, 'utf8');\n\n// get the length of the buffer in bytes\nbuffer.length();\n// put bytes into the buffer\nbuffer.putBytes(bytes);\n// put a 32-bit integer into the buffer\nbuffer.putInt32(10);\n// buffer to hex\nbuffer.toHex();\n// get a copy of the bytes in the buffer\nbytes.bytes(/* count */);\n// empty this buffer and get its contents\nbytes.getBytes(/* count */);\n\n// convert a forge buffer into a Node.js Buffer\n// make sure you specify the encoding as 'binary'\nvar forgeBuffer = forge.util.createBuffer();\nvar nodeBuffer = Buffer.from(forgeBuffer.getBytes(), 'binary');\n\n// convert a Node.js Buffer into a forge buffer\n// make sure you specify the encoding as 'binary'\nvar nodeBuffer = Buffer.from('CAFE', 'hex');\nvar forgeBuffer = forge.util.createBuffer(nodeBuffer.toString('binary'));\n```\n\n<a name=\"log\" />\n\n### Logging\n\nProvides logging to a javascript console using various categories and\nlevels of verbosity.\n\n__Examples__\n\n```js\n// TODO\n```\n\n<a name=\"flash\" />\n\n### Flash Networking Support\n\nThe [flash README](./flash/README.md) provides details on rebuilding the\noptional Flash component used for networking. It also provides details on\nPolicy Server support.\n\nSecurity Considerations\n-----------------------\n\nWhen using this code please keep the following in mind:\n\n- Cryptography is hard. Please review and test this code before depending on it\n  for critical functionality.\n- The nature of JavaScript is that execution of this code depends on trusting a\n  very large set of JavaScript tools and systems. Consider runtime variations,\n  runtime characteristics, runtime optimization, code optimization, code\n  minimization, code obfuscation, bundling tools, possible bugs, the Forge code\n  itself, and so on.\n- If using pre-built bundles from [NPM][], another CDN, or similar, be aware\n  someone else ran the tools to create those files.\n- Use a secure transport channel such as [TLS][] to load scripts and consider\n  using additional security mechanisms such as [Subresource Integrity][] script\n  attributes.\n- Use \"native\" functionality where possible. This can be critical when dealing\n  with performance and random number generation. Note that the JavaScript\n  random number algorithms should perform well if given suitable entropy.\n- Understand possible attacks against cryptographic systems. For instance side\n  channel and timing attacks may be possible due to the difficulty in\n  implementing constant time algorithms in pure JavaScript.\n- Certain features in this library are less susceptible to attacks depending on\n  usage. This primarily includes features that deal with data format\n  manipulation or those that are not involved in communication.\n\nLibrary Background\n------------------\n\n* https://digitalbazaar.com/2010/07/20/javascript-tls-1/\n* https://digitalbazaar.com/2010/07/20/javascript-tls-2/\n\nContact\n-------\n\n* Code: https://github.com/digitalbazaar/forge\n* Bugs: https://github.com/digitalbazaar/forge/issues\n* Email: support@digitalbazaar.com\n* IRC: [#forgejs][] on [Libera.Chat][] (people may also be on [freenode][] for\n  historical reasons).\n\nDonations\n---------\n\nFinancial support is welcome and helps contribute to futher development:\n\n* For [PayPal][] please send to paypal@digitalbazaar.com.\n* Something else? Please contact support@digitalbazaar.com.\n\n[#forgejs]: https://webchat.freenode.net/?channels=#forgejs\n[0.6.x]: https://github.com/digitalbazaar/forge/tree/0.6.x\n[3DES]: https://en.wikipedia.org/wiki/Triple_DES\n[AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard\n[ASN.1]: https://en.wikipedia.org/wiki/ASN.1\n[Browserify]: http://browserify.org/\n[CBC]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation\n[CFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation\n[CTR]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation\n[CommonJS]: https://en.wikipedia.org/wiki/CommonJS\n[DES]: https://en.wikipedia.org/wiki/Data_Encryption_Standard\n[ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation\n[Fortuna]: https://en.wikipedia.org/wiki/Fortuna_(PRNG)\n[GCM]: https://en.wikipedia.org/wiki/GCM_mode\n[HMAC]: https://en.wikipedia.org/wiki/HMAC\n[JavaScript]: https://en.wikipedia.org/wiki/JavaScript\n[Karma]: https://karma-runner.github.io/\n[Libera.Chat]: https://libera.chat/\n[MD5]: https://en.wikipedia.org/wiki/MD5\n[NPM]: https://www.npmjs.com/\n[Node.js]: https://nodejs.org/\n[OFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation\n[PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request\n[PKCS#12]: https://en.wikipedia.org/wiki/PKCS_%E2%99%AF12\n[PKCS#5]: https://en.wikipedia.org/wiki/PKCS\n[PKCS#7]: https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax\n[PayPal]: https://www.paypal.com/\n[RC2]: https://en.wikipedia.org/wiki/RC2\n[SHA-1]: https://en.wikipedia.org/wiki/SHA-1\n[SHA-256]: https://en.wikipedia.org/wiki/SHA-256\n[SHA-384]: https://en.wikipedia.org/wiki/SHA-384\n[SHA-512]: https://en.wikipedia.org/wiki/SHA-512\n[Subresource Integrity]: https://www.w3.org/TR/SRI/\n[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security\n[UMD]: https://github.com/umdjs/umd\n[X.509]: https://en.wikipedia.org/wiki/X.509\n[freenode]: https://freenode.net/\n[unpkg]: https://unpkg.com/\n[webpack]: https://webpack.github.io/\n[TweetNaCl.js]: https://github.com/dchest/tweetnacl-js\n",
    "licenseText": "You may use the Forge project under the terms of either the BSD License or the\nGNU General Public License (GPL) Version 2.\n\nThe BSD License is recommended for most projects. It is simple and easy to\nunderstand and it places almost no restrictions on what you can do with the\nForge project.\n\nIf the GPL suits your project better you are also free to use Forge under\nthat license.\n\nYou don't have to do anything special to choose one license or the other and\nyou don't have to notify anyone which license you are using. You are free to\nuse this project in commercial projects as long as the copyright header is\nleft intact.\n\nIf you are a commercial entity and use this set of libraries in your\ncommercial software then reasonable payment to Digital Bazaar, if you can\nafford it, is not required but is expected and would be appreciated. If this\nlibrary saves you time, then it's saving you money. The cost of developing\nthe Forge software was on the order of several hundred hours and tens of\nthousands of dollars. We are attempting to strike a balance between helping\nthe development community while not being taken advantage of by lucrative\ncommercial entities for our efforts.\n\n-------------------------------------------------------------------------------\nNew BSD License (3-clause)\nCopyright (c) 2010, Digital Bazaar, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of Digital Bazaar, Inc. nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL DIGITAL BAZAAR BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\n        GNU GENERAL PUBLIC LICENSE\n           Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n          Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n        GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n          NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n"
  },
  "artifacts": [],
  "remote": {
    "resolved": "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3",
    "type": "tarball",
    "reference": "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz",
    "hash": "be8da2af243b2417d5f646a770663a92b7e9ded3",
    "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
    "registry": "npm",
    "packageName": "node-forge",
    "cacheIntegrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== sha1-vo2iryQ7JBfV9kancGY6krfp3tM="
  },
  "registry": "npm",
  "hash": "be8da2af243b2417d5f646a770663a92b7e9ded3"
}