Forge

A native implementation of TLS in Javascript and tools to write crypto-base...

README

Forge

npm package
Build Status

A native implementation of [TLS][] (and various other cryptographic tools) in
[JavaScript][].

Introduction

The Forge software is a fully native implementation of the [TLS][] protocol
in JavaScript, a set of cryptography utilities, and a set of tools for
developing Web Apps that utilize many network resources.

Performance

Forge is fast. Benchmarks against other popular JavaScript cryptography
libraries can be found here:

http://dominictarr.github.io/crypto-bench/
http://cryptojs.altervista.org/test/simulate-threading-speed_test.html

Documentation


API



Transports



Ciphers



PKI



Message Digests



Utilities



Other




Installation

Note: Please see the Security Considerations
section before using packaging systems and pre-built files.

Forge uses a [CommonJS][] module structure with a build process for browser
bundles. The older [0.6.x][] branch with standalone files is available but will
not be regularly updated.

Node.js


If you want to use forge with [Node.js][], it is available through npm:

https://www.npmjs.com/package/node-forge

Installation:

    npm install node-forge

You can then use forge as a regular module:

  1. ``` js
  2. var forge = require('node-forge');
  3. ```

The npm package includes pre-built forge.min.js, forge.all.min.js, and
prime.worker.min.js using the [UMD][] format.

jsDelivr CDN


To use it via jsDelivr include this in your html:

  1. ``` html
  2. <script src="https://cdn.jsdelivr.net/npm/node-forge@1.0.0/dist/forge.min.js"></script>
  3. ```

unpkg CDN


To use it via unpkg include this in your html:

  1. ``` html
  2. <script src="https://unpkg.com/node-forge@1.0.0/dist/forge.min.js"></script>
  3. ```

Development Requirements


The core JavaScript has the following requirements to build and test:

Building a browser bundle:
  Node.js
  npm
Testing
  Node.js
  npm
  Chrome, Firefox, Safari (optional)

Some special networking features can optionally use a Flash component.  See the
Flash README for details.

Building for a web browser


To create single file bundles for use with browsers run the following:

    npm install
    npm run build

This will create single non-minimized and minimized files that can be
included in the browser:

    dist/forge.js
    dist/forge.min.js

A bundle that adds some utilities and networking support is also available:

    dist/forge.all.js
    dist/forge.all.min.js

Include the file via:

  1. ``` html
  2. <script src="YOUR_SCRIPT_PATH/forge.js"></script>
  3. ```
or
  1. ``` html
  2. <script src="YOUR_SCRIPT_PATH/forge.min.js"></script>
  3. ```

The above bundles will synchronously create a global 'forge' object.

Note: These bundles will not include any WebWorker scripts (eg:
dist/prime.worker.js), so these will need to be accessible from the browser
if any WebWorkers are used.

Building a custom browser bundle


The build process uses [webpack][] and the config file
can be modified to generate a file or files that only contain the parts of
forge you need.

[Browserify][] override support is also present in package.json.

Testing

Prepare to run tests


    npm install

Running automated tests with Node.js


Forge natively runs in a [Node.js][] environment:

    npm test

Running automated tests with Headless Chrome


Automated testing is done via [Karma][]. By default it will run the tests with
Headless Chrome.

    npm run test-karma

Is 'mocha' reporter output too verbose? Other reporters are available. Try
'dots', 'progress', or 'tap'.

    npm run test-karma -- --reporters progress

By default [webpack][] is used. [Browserify][] can also be used.

    BUNDLER=browserify npm run test-karma

Running automated tests with one or more browsers


You can also specify one or more browsers to use.

    npm run test-karma -- --browsers Chrome,Firefox,Safari,ChromeHeadless

The reporter option and BUNDLER environment variable can also be used.

Running manual tests in a browser


Testing in a browser uses [webpack][] to combine forge and all tests and then
loading the result in a browser. A simple web server is provided that will
output the HTTP or HTTPS URLs to load. It also will start a simple Flash Policy
Server. Unit tests and older legacy tests are provided. Custom ports can be
used by running node tests/server.js manually.

To run the unit tests in a browser a special forge build is required:

    npm run test-build

To run legacy browser based tests the main forge build is required:

    npm run build

The tests are run with a custom server that prints out the URLs to use:

    npm run test-server

Running other tests


There are some other random tests and benchmarks available in the tests
directory.

Coverage testing


To perform coverage testing of the unit tests, run the following. The results
will be put in the coverage/ directory. Note that coverage testing can slow
down some tests considerably.

    npm install
    npm run coverage

Contributing

Any contributions (eg: PRs) that are accepted will be brought under the same
license used by the rest of the Forge project. This license allows Forge to
be used under the terms of either the BSD License or the GNU General Public
License (GPL) Version 2.

See: LICENSE

If a contribution contains 3rd party source code with its own license, it
may retain it, so long as that license is compatible with the Forge license.

API


Options


If at any time you wish to disable the use of native code, where available,
for particular forge features like its secure random number generator, you
may set the forge.options.usePureJavaScript flag to true . It is
not recommended that you set this flag as native code is typically more
performant and may have stronger security properties. It may be useful to
set this flag to test certain features that you plan to run in environments
that are different from your testing environment.

To disable native code when including forge in the browser:

  1. ``` js
  2. // run this *after* including the forge script
  3. forge.options.usePureJavaScript = true;
  4. ```

To disable native code when using Node.js:

  1. ``` js
  2. var forge = require('node-forge');
  3. forge.options.usePureJavaScript = true;
  4. ```

Transports


TLS


Provides a native javascript client and server-side [TLS][] implementation.

__Examples__

  1. ``` js
  2. // create TLS client
  3. var client = forge.tls.createConnection({
  4.   server: false,
  5.   caStore: /* Array of PEM-formatted certs or a CA store object */,
  6.   sessionCache: {},
  7.   // supported cipher suites in order of preference
  8.   cipherSuites: [
  9.     forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
  10.     forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
  11.   virtualHost: 'example.com',
  12.   verify: function(connection, verified, depth, certs) {
  13.     if(depth === 0) {
  14.       var cn = certs[0].subject.getField('CN').value;
  15.       if(cn !== 'example.com') {
  16.         verified = {
  17.           alert: forge.tls.Alert.Description.bad_certificate,
  18.           message: 'Certificate common name does not match hostname.'
  19.         };
  20.       }
  21.     }
  22.     return verified;
  23.   },
  24.   connected: function(connection) {
  25.     console.log('connected');
  26.     // send message to server
  27.     connection.prepare(forge.util.encodeUtf8('Hi server!'));
  28.     /* NOTE: experimental, start heartbeat retransmission timer
  29.     myHeartbeatTimer = setInterval(function() {
  30.       connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
  31.     }, 5*60*1000);*/
  32.   },
  33.   /* provide a client-side cert if you want
  34.   getCertificate: function(connection, hint) {
  35.     return myClientCertificate;
  36.   },
  37.   /* the private key for the client-side cert if provided */
  38.   getPrivateKey: function(connection, cert) {
  39.     return myClientPrivateKey;
  40.   },
  41.   tlsDataReady: function(connection) {
  42.     // TLS data (encrypted) is ready to be sent to the server
  43.     sendToServerSomehow(connection.tlsData.getBytes());
  44.     // if you were communicating with the server below, you'd do:
  45.     // server.process(connection.tlsData.getBytes());
  46.   },
  47.   dataReady: function(connection) {
  48.     // clear data from the server is ready
  49.     console.log('the server sent: ' +
  50.       forge.util.decodeUtf8(connection.data.getBytes()));
  51.     // close connection
  52.     connection.close();
  53.   },
  54.   /* NOTE: experimental
  55.   heartbeatReceived: function(connection, payload) {
  56.     // restart retransmission timer, look at payload
  57.     clearInterval(myHeartbeatTimer);
  58.     myHeartbeatTimer = setInterval(function() {
  59.       connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
  60.     }, 5*60*1000);
  61.     payload.getBytes();
  62.   },*/
  63.   closed: function(connection) {
  64.     console.log('disconnected');
  65.   },
  66.   error: function(connection, error) {
  67.     console.log('uh oh', error);
  68.   }
  69. });

  70. // start the handshake process
  71. client.handshake();

  72. // when encrypted TLS data is received from the server, process it
  73. client.process(encryptedBytesFromServer);

  74. // create TLS server
  75. var server = forge.tls.createConnection({
  76.   server: true,
  77.   caStore: /* Array of PEM-formatted certs or a CA store object */,
  78.   sessionCache: {},
  79.   // supported cipher suites in order of preference
  80.   cipherSuites: [
  81.     forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
  82.     forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
  83.   // require a client-side certificate if you want
  84.   verifyClient: true,
  85.   verify: function(connection, verified, depth, certs) {
  86.     if(depth === 0) {
  87.       var cn = certs[0].subject.getField('CN').value;
  88.       if(cn !== 'the-client') {
  89.         verified = {
  90.           alert: forge.tls.Alert.Description.bad_certificate,
  91.           message: 'Certificate common name does not match expected client.'
  92.         };
  93.       }
  94.     }
  95.     return verified;
  96.   },
  97.   connected: function(connection) {
  98.     console.log('connected');
  99.     // send message to client
  100.     connection.prepare(forge.util.encodeUtf8('Hi client!'));
  101.     /* NOTE: experimental, start heartbeat retransmission timer
  102.     myHeartbeatTimer = setInterval(function() {
  103.       connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
  104.     }, 5*60*1000);*/
  105.   },
  106.   getCertificate: function(connection, hint) {
  107.     return myServerCertificate;
  108.   },
  109.   getPrivateKey: function(connection, cert) {
  110.     return myServerPrivateKey;
  111.   },
  112.   tlsDataReady: function(connection) {
  113.     // TLS data (encrypted) is ready to be sent to the client
  114.     sendToClientSomehow(connection.tlsData.getBytes());
  115.     // if you were communicating with the client above you'd do:
  116.     // client.process(connection.tlsData.getBytes());
  117.   },
  118.   dataReady: function(connection) {
  119.     // clear data from the client is ready
  120.     console.log('the client sent: ' +
  121.       forge.util.decodeUtf8(connection.data.getBytes()));
  122.     // close connection
  123.     connection.close();
  124.   },
  125.   /* NOTE: experimental
  126.   heartbeatReceived: function(connection, payload) {
  127.     // restart retransmission timer, look at payload
  128.     clearInterval(myHeartbeatTimer);
  129.     myHeartbeatTimer = setInterval(function() {
  130.       connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
  131.     }, 5*60*1000);
  132.     payload.getBytes();
  133.   },*/
  134.   closed: function(connection) {
  135.     console.log('disconnected');
  136.   },
  137.   error: function(connection, error) {
  138.     console.log('uh oh', error);
  139.   }
  140. });

  141. // when encrypted TLS data is received from the client, process it
  142. server.process(encryptedBytesFromClient);
  143. ```

Connect to a TLS server using node's net.Socket:

  1. ``` js
  2. var socket = new net.Socket();

  3. var client = forge.tls.createConnection({
  4.   server: false,
  5.   verify: function(connection, verified, depth, certs) {
  6.     // skip verification for testing
  7.     console.log('[tls] server certificate verified');
  8.     return true;
  9.   },
  10.   connected: function(connection) {
  11.     console.log('[tls] connected');
  12.     // prepare some data to send (note that the string is interpreted as
  13.     // 'binary' encoded, which works for HTTP which only uses ASCII, use
  14.     // forge.util.encodeUtf8(str) otherwise
  15.     client.prepare('GET / HTTP/1.0\r\n\r\n');
  16.   },
  17.   tlsDataReady: function(connection) {
  18.     // encrypted data is ready to be sent to the server
  19.     var data = connection.tlsData.getBytes();
  20.     socket.write(data, 'binary'); // encoding should be 'binary'
  21.   },
  22.   dataReady: function(connection) {
  23.     // clear data from the server is ready
  24.     var data = connection.data.getBytes();
  25.     console.log('[tls] data received from the server: ' + data);
  26.   },
  27.   closed: function() {
  28.     console.log('[tls] disconnected');
  29.   },
  30.   error: function(connection, error) {
  31.     console.log('[tls] error', error);
  32.   }
  33. });

  34. socket.on('connect', function() {
  35.   console.log('[socket] connected');
  36.   client.handshake();
  37. });
  38. socket.on('data', function(data) {
  39.   client.process(data.toString('binary')); // encoding should be 'binary'
  40. });
  41. socket.on('end', function() {
  42.   console.log('[socket] disconnected');
  43. });

  44. // connect to google.com
  45. socket.connect(443, 'google.com');

  46. // or connect to gmail's imap server (but don't send the HTTP header above)
  47. //socket.connect(993, 'imap.gmail.com');
  48. ```


HTTP


Provides a native [JavaScript][] mini-implementation of an http client that
uses pooled sockets.

__Examples__

  1. ``` js
  2. // create an HTTP GET request
  3. var request = forge.http.createRequest({method: 'GET', path: url.path});

  4. // send the request somewhere
  5. sendSomehow(request.toString());

  6. // receive response
  7. var buffer = forge.util.createBuffer();
  8. var response = forge.http.createResponse();
  9. var someAsyncDataHandler = function(bytes) {
  10.   if(!response.bodyReceived) {
  11.     buffer.putBytes(bytes);
  12.     if(!response.headerReceived) {
  13.       if(response.readHeader(buffer)) {
  14.         console.log('HTTP response header: ' + response.toString());
  15.       }
  16.     }
  17.     if(response.headerReceived && !response.bodyReceived) {
  18.       if(response.readBody(buffer)) {
  19.         console.log('HTTP response body: ' + response.body);
  20.       }
  21.     }
  22.   }
  23. };
  24. ```


SSH


Provides some SSH utility functions.

__Examples__

  1. ``` js
  2. // encodes (and optionally encrypts) a private RSA key as a Putty PPK file
  3. forge.ssh.privateKeyToPutty(privateKey, passphrase, comment);

  4. // encodes a public RSA key as an OpenSSH file
  5. forge.ssh.publicKeyToOpenSSH(key, comment);

  6. // encodes a private RSA key as an OpenSSH file
  7. forge.ssh.privateKeyToOpenSSH(privateKey, passphrase);

  8. // gets the SSH public key fingerprint in a byte buffer
  9. forge.ssh.getPublicKeyFingerprint(key);

  10. // gets a hex-encoded, colon-delimited SSH public key fingerprint
  11. forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
  12. ```


XHR


Provides an XmlHttpRequest implementation using forge.http as a backend.

__Examples__

  1. ``` js
  2. // TODO
  3. ```


Sockets


Provides an interface to create and use raw sockets provided via Flash.

__Examples__

  1. ``` js
  2. // TODO
  3. ```

Ciphers


CIPHER


Provides a basic API for block encryption and decryption. There is built-in
support for the ciphers: [AES][], [3DES][], and [DES][], and for the modes
of operation: [ECB][], [CBC][], [CFB][], [OFB][], [CTR][], and [GCM][].

These algorithms are currently supported:

AES-ECB
AES-CBC
AES-CFB
AES-OFB
AES-CTR
AES-GCM
3DES-ECB
3DES-CBC
DES-ECB
DES-CBC

When using an [AES][] algorithm, the key size will determine whether
AES-128, AES-192, or AES-256 is used (all are supported). When a [DES][]
algorithm is used, the key size will determine whether [3DES][] or regular
[DES][] is used. Use a [3DES][] algorithm to enforce Triple-DES.

__Examples__

  1. ``` js
  2. // generate a random key and IV
  3. // Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256
  4. var key = forge.random.getBytesSync(16);
  5. var iv = forge.random.getBytesSync(16);

  6. /* alternatively, generate a password-based 16-byte key
  7. var salt = forge.random.getBytesSync(128);
  8. var key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
  9. */

  10. // encrypt some bytes using CBC mode
  11. // (other modes include: ECB, CFB, OFB, CTR, and GCM)
  12. // Note: CBC and ECB modes use PKCS#7 padding as default
  13. var cipher = forge.cipher.createCipher('AES-CBC', key);
  14. cipher.start({iv: iv});
  15. cipher.update(forge.util.createBuffer(someBytes));
  16. cipher.finish();
  17. var encrypted = cipher.output;
  18. // outputs encrypted hex
  19. console.log(encrypted.toHex());

  20. // decrypt some bytes using CBC mode
  21. // (other modes include: CFB, OFB, CTR, and GCM)
  22. var decipher = forge.cipher.createDecipher('AES-CBC', key);
  23. decipher.start({iv: iv});
  24. decipher.update(encrypted);
  25. var result = decipher.finish(); // check 'result' for true/false
  26. // outputs decrypted hex
  27. console.log(decipher.output.toHex());

  28. // decrypt bytes using CBC mode and streaming
  29. // Performance can suffer for large multi-MB inputs due to buffer
  30. // manipulations. Stream processing in chunks can offer significant
  31. // improvement. CPU intensive update() calls could also be performed with
  32. // setImmediate/setTimeout to avoid blocking the main browser UI thread (not
  33. // shown here). Optimal block size depends on the JavaScript VM and other
  34. // factors. Encryption can use a simple technique for increased performance.
  35. var encryptedBytes = encrypted.bytes();
  36. var decipher = forge.cipher.createDecipher('AES-CBC', key);
  37. decipher.start({iv: iv});
  38. var length = encryptedBytes.length;
  39. var chunkSize = 1024 * 64;
  40. var index = 0;
  41. var decrypted = '';
  42. do {
  43.   decrypted += decipher.output.getBytes();
  44.   var buf = forge.util.createBuffer(encryptedBytes.substr(index, chunkSize));
  45.   decipher.update(buf);
  46.   index += chunkSize;
  47. } while(index < length);
  48. var result = decipher.finish();
  49. assert(result);
  50. decrypted += decipher.output.getBytes();
  51. console.log(forge.util.bytesToHex(decrypted));

  52. // encrypt some bytes using GCM mode
  53. var cipher = forge.cipher.createCipher('AES-GCM', key);
  54. cipher.start({
  55.   iv: iv, // should be a 12-byte binary-encoded string or byte buffer
  56.   additionalData: 'binary-encoded string', // optional
  57.   tagLength: 128 // optional, defaults to 128 bits
  58. });
  59. cipher.update(forge.util.createBuffer(someBytes));
  60. cipher.finish();
  61. var encrypted = cipher.output;
  62. var tag = cipher.mode.tag;
  63. // outputs encrypted hex
  64. console.log(encrypted.toHex());
  65. // outputs authentication tag
  66. console.log(tag.toHex());

  67. // decrypt some bytes using GCM mode
  68. var decipher = forge.cipher.createDecipher('AES-GCM', key);
  69. decipher.start({
  70.   iv: iv,
  71.   additionalData: 'binary-encoded string', // optional
  72.   tagLength: 128, // optional, defaults to 128 bits
  73.   tag: tag // authentication tag from encryption
  74. });
  75. decipher.update(encrypted);
  76. var pass = decipher.finish();
  77. // pass is false if there was a failure (eg: authentication tag didn't match)
  78. if(pass) {
  79.   // outputs decrypted hex
  80.   console.log(decipher.output.toHex());
  81. }
  82. ```


  1. ``` js
  2. var forge = require('node-forge');
  3. var fs = require('fs');

  4. // openssl enc -des3 -in input.txt -out input.enc
  5. function encrypt(password) {
  6.   var input = fs.readFileSync('input.txt', {encoding: 'binary'});

  7.   // 3DES key and IV sizes
  8.   var keySize = 24;
  9.   var ivSize = 8;

  10.   // get derived bytes
  11.   // Notes:
  12.   // 1. If using an alternative hash (eg: "-md sha1") pass
  13.   //   "forge.md.sha1.create()" as the final parameter.
  14.   // 2. If using "-nosalt", set salt to null.
  15.   var salt = forge.random.getBytesSync(8);
  16.   // var md = forge.md.sha1.create(); // "-md sha1"
  17.   var derivedBytes = forge.pbe.opensslDeriveBytes(
  18.     password, salt, keySize + ivSize/*, md*/);
  19.   var buffer = forge.util.createBuffer(derivedBytes);
  20.   var key = buffer.getBytes(keySize);
  21.   var iv = buffer.getBytes(ivSize);

  22.   var cipher = forge.cipher.createCipher('3DES-CBC', key);
  23.   cipher.start({iv: iv});
  24.   cipher.update(forge.util.createBuffer(input, 'binary'));
  25.   cipher.finish();

  26.   var output = forge.util.createBuffer();

  27.   // if using a salt, prepend this to the output:
  28.   if(salt !== null) {
  29.     output.putBytes('Salted__'); // (add to match openssl tool output)
  30.     output.putBytes(salt);
  31.   }
  32.   output.putBuffer(cipher.output);

  33.   fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'});
  34. }

  35. // openssl enc -d -des3 -in input.enc -out input.dec.txt
  36. function decrypt(password) {
  37.   var input = fs.readFileSync('input.enc', {encoding: 'binary'});

  38.   // parse salt from input
  39.   input = forge.util.createBuffer(input, 'binary');
  40.   // skip "Salted__" (if known to be present)
  41.   input.getBytes('Salted__'.length);
  42.   // read 8-byte salt
  43.   var salt = input.getBytes(8);

  44.   // Note: if using "-nosalt", skip above parsing and use
  45.   // var salt = null;

  46.   // 3DES key and IV sizes
  47.   var keySize = 24;
  48.   var ivSize = 8;

  49.   var derivedBytes = forge.pbe.opensslDeriveBytes(
  50.     password, salt, keySize + ivSize);
  51.   var buffer = forge.util.createBuffer(derivedBytes);
  52.   var key = buffer.getBytes(keySize);
  53.   var iv = buffer.getBytes(ivSize);

  54.   var decipher = forge.cipher.createDecipher('3DES-CBC', key);
  55.   decipher.start({iv: iv});
  56.   decipher.update(input);
  57.   var result = decipher.finish(); // check 'result' for true/false

  58.   fs.writeFileSync(
  59.     'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'});
  60. }
  61. ```


AES


Provides [AES][] encryption and decryption in [CBC][], [CFB][], [OFB][],


DES


Provides [3DES][] and [DES][] encryption and decryption in [ECB][] and


RC2


__Examples__

  1. ``` js
  2. // generate a random key and IV
  3. var key = forge.random.getBytesSync(16);
  4. var iv = forge.random.getBytesSync(8);

  5. // encrypt some bytes
  6. var cipher = forge.rc2.createEncryptionCipher(key);
  7. cipher.start(iv);
  8. cipher.update(forge.util.createBuffer(someBytes));
  9. cipher.finish();
  10. var encrypted = cipher.output;
  11. // outputs encrypted hex
  12. console.log(encrypted.toHex());

  13. // decrypt some bytes
  14. var cipher = forge.rc2.createDecryptionCipher(key);
  15. cipher.start(iv);
  16. cipher.update(encrypted);
  17. cipher.finish();
  18. // outputs decrypted hex
  19. console.log(cipher.output.toHex());
  20. ```

PKI

Provides [X.509][] certificate support, ED25519 key generation and
signing/verifying, and RSA public and private key encoding, decoding,
encryption/decryption, and signing/verifying.


ED25519


Special thanks to [TweetNaCl.js][] for providing the bulk of the implementation.

__Examples__

  1. ``` js
  2. var ed25519 = forge.pki.ed25519;

  3. // generate a random ED25519 keypair
  4. var keypair = ed25519.generateKeyPair();
  5. // `keypair.publicKey` is a node.js Buffer or Uint8Array
  6. // `keypair.privateKey` is a node.js Buffer or Uint8Array

  7. // generate a random ED25519 keypair based on a random 32-byte seed
  8. var seed = forge.random.getBytesSync(32);
  9. var keypair = ed25519.generateKeyPair({seed: seed});

  10. // generate a random ED25519 keypair based on a "password" 32-byte seed
  11. var password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
  12. var seed = new forge.util.ByteBuffer(password, 'utf8');
  13. var keypair = ed25519.generateKeyPair({seed: seed});

  14. // sign a UTF-8 message
  15. var signature = ED25519.sign({
  16.   message: 'test',
  17.   // also accepts `binary` if you want to pass a binary string
  18.   encoding: 'utf8',
  19.   // node.js Buffer, Uint8Array, forge ByteBuffer, binary string
  20.   privateKey: privateKey
  21. });
  22. // `signature` is a node.js Buffer or Uint8Array

  23. // sign a message passed as a buffer
  24. var signature = ED25519.sign({
  25.   // also accepts a forge ByteBuffer or Uint8Array
  26.   message: Buffer.from('test', 'utf8'),
  27.   privateKey: privateKey
  28. });

  29. // sign a message digest (shorter "message" == better performance)
  30. var md = forge.md.sha256.create();
  31. md.update('test', 'utf8');
  32. var signature = ED25519.sign({
  33.   md: md,
  34.   privateKey: privateKey
  35. });

  36. // verify a signature on a UTF-8 message
  37. var verified = ED25519.verify({
  38.   message: 'test',
  39.   encoding: 'utf8',
  40.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  41.   signature: signature,
  42.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  43.   publicKey: publicKey
  44. });
  45. // `verified` is true/false

  46. // sign a message passed as a buffer
  47. var verified = ED25519.verify({
  48.   // also accepts a forge ByteBuffer or Uint8Array
  49.   message: Buffer.from('test', 'utf8'),
  50.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  51.   signature: signature,
  52.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  53.   publicKey: publicKey
  54. });

  55. // verify a signature on a message digest
  56. var md = forge.md.sha256.create();
  57. md.update('test', 'utf8');
  58. var verified = ED25519.verify({
  59.   md: md,
  60.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  61.   signature: signature,
  62.   // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
  63.   publicKey: publicKey
  64. });
  65. ```


RSA


__Examples__

  1. ``` js
  2. var rsa = forge.pki.rsa;

  3. // generate an RSA key pair synchronously
  4. // *NOT RECOMMENDED*: Can be significantly slower than async and may block
  5. // JavaScript execution. Will use native Node.js 10.12.0+ API if possible.
  6. var keypair = rsa.generateKeyPair({bits: 2048, e: 0x10001});

  7. // generate an RSA key pair asynchronously (uses web workers if available)
  8. // use workers: -1 to run a fast core estimator to optimize # of workers
  9. // *RECOMMENDED*: Can be significantly faster than sync. Will use native
  10. // Node.js 10.12.0+ or WebCrypto API if possible.
  11. rsa.generateKeyPair({bits: 2048, workers: 2}, function(err, keypair) {
  12.   // keypair.privateKey, keypair.publicKey
  13. });

  14. // generate an RSA key pair in steps that attempt to run for a specified period
  15. // of time on the main JS thread
  16. var state = rsa.createKeyPairGenerationState(2048, 0x10001);
  17. var step = function() {
  18.   // run for 100 ms
  19.   if(!rsa.stepKeyPairGenerationState(state, 100)) {
  20.     setTimeout(step, 1);
  21.   }
  22.   else {
  23.     // done, turn off progress indicator, use state.keys
  24.   }
  25. };
  26. // turn on progress indicator, schedule generation to run
  27. setTimeout(step);

  28. // sign data with a private key and output DigestInfo DER-encoded bytes
  29. // (defaults to RSASSA PKCS#1 v1.5)
  30. var md = forge.md.sha1.create();
  31. md.update('sign this', 'utf8');
  32. var signature = privateKey.sign(md);

  33. // verify data with a public key
  34. // (defaults to RSASSA PKCS#1 v1.5)
  35. var verified = publicKey.verify(md.digest().bytes(), signature);

  36. // sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based
  37. // masking function MGF1, and a 20 byte salt
  38. var md = forge.md.sha1.create();
  39. md.update('sign this', 'utf8');
  40. var pss = forge.pss.create({
  41.   md: forge.md.sha1.create(),
  42.   mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
  43.   saltLength: 20
  44.   // optionally pass 'prng' with a custom PRNG implementation
  45.   // optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt
  46. });
  47. var signature = privateKey.sign(md, pss);

  48. // verify RSASSA-PSS signature
  49. var pss = forge.pss.create({
  50.   md: forge.md.sha1.create(),
  51.   mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
  52.   saltLength: 20
  53.   // optionally pass 'prng' with a custom PRNG implementation
  54. });
  55. var md = forge.md.sha1.create();
  56. md.update('sign this', 'utf8');
  57. publicKey.verify(md.digest().getBytes(), signature, pss);

  58. // encrypt data with a public key (defaults to RSAES PKCS#1 v1.5)
  59. var encrypted = publicKey.encrypt(bytes);

  60. // decrypt data with a private key (defaults to RSAES PKCS#1 v1.5)
  61. var decrypted = privateKey.decrypt(encrypted);

  62. // encrypt data with a public key using RSAES PKCS#1 v1.5
  63. var encrypted = publicKey.encrypt(bytes, 'RSAES-PKCS1-V1_5');

  64. // decrypt data with a private key using RSAES PKCS#1 v1.5
  65. var decrypted = privateKey.decrypt(encrypted, 'RSAES-PKCS1-V1_5');

  66. // encrypt data with a public key using RSAES-OAEP
  67. var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP');

  68. // decrypt data with a private key using RSAES-OAEP
  69. var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP');

  70. // encrypt data with a public key using RSAES-OAEP/SHA-256
  71. var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
  72.   md: forge.md.sha256.create()
  73. });

  74. // decrypt data with a private key using RSAES-OAEP/SHA-256
  75. var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
  76.   md: forge.md.sha256.create()
  77. });

  78. // encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
  79. // compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
  80. var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
  81.   md: forge.md.sha256.create(),
  82.   mgf1: {
  83.     md: forge.md.sha1.create()
  84.   }
  85. });

  86. // decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1
  87. // compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
  88. var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
  89.   md: forge.md.sha256.create(),
  90.   mgf1: {
  91.     md: forge.md.sha1.create()
  92.   }
  93. });

  94. ```


RSA-KEM


__Examples__

  1. ``` js
  2. // generate an RSA key pair asynchronously (uses web workers if available)
  3. // use workers: -1 to run a fast core estimator to optimize # of workers
  4. forge.rsa.generateKeyPair({bits: 2048, workers: -1}, function(err, keypair) {
  5.   // keypair.privateKey, keypair.publicKey
  6. });

  7. // generate and encapsulate a 16-byte secret key
  8. var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
  9. var kem = forge.kem.rsa.create(kdf1);
  10. var result = kem.encrypt(keypair.publicKey, 16);
  11. // result has 'encapsulation' and 'key'

  12. // encrypt some bytes
  13. var iv = forge.random.getBytesSync(12);
  14. var someBytes = 'hello world!';
  15. var cipher = forge.cipher.createCipher('AES-GCM', result.key);
  16. cipher.start({iv: iv});
  17. cipher.update(forge.util.createBuffer(someBytes));
  18. cipher.finish();
  19. var encrypted = cipher.output.getBytes();
  20. var tag = cipher.mode.tag.getBytes();

  21. // send 'encrypted', 'iv', 'tag', and result.encapsulation to recipient

  22. // decrypt encapsulated 16-byte secret key
  23. var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
  24. var kem = forge.kem.rsa.create(kdf1);
  25. var key = kem.decrypt(keypair.privateKey, result.encapsulation, 16);

  26. // decrypt some bytes
  27. var decipher = forge.cipher.createDecipher('AES-GCM', key);
  28. decipher.start({iv: iv, tag: tag});
  29. decipher.update(forge.util.createBuffer(encrypted));
  30. var pass = decipher.finish();
  31. // pass is false if there was a failure (eg: authentication tag didn't match)
  32. if(pass) {
  33.   // outputs 'hello world!'
  34.   console.log(decipher.output.getBytes());
  35. }

  36. ```


X.509


__Examples__

  1. ``` js
  2. var pki = forge.pki;

  3. // convert a PEM-formatted public key to a Forge public key
  4. var publicKey = pki.publicKeyFromPem(pem);

  5. // convert a Forge public key to PEM-format
  6. var pem = pki.publicKeyToPem(publicKey);

  7. // convert an ASN.1 SubjectPublicKeyInfo to a Forge public key
  8. var publicKey = pki.publicKeyFromAsn1(subjectPublicKeyInfo);

  9. // convert a Forge public key to an ASN.1 SubjectPublicKeyInfo
  10. var subjectPublicKeyInfo = pki.publicKeyToAsn1(publicKey);

  11. // gets a SHA-1 RSAPublicKey fingerprint a byte buffer
  12. pki.getPublicKeyFingerprint(key);

  13. // gets a SHA-1 SubjectPublicKeyInfo fingerprint a byte buffer
  14. pki.getPublicKeyFingerprint(key, {type: 'SubjectPublicKeyInfo'});

  15. // gets a hex-encoded, colon-delimited SHA-1 RSAPublicKey public key fingerprint
  16. pki.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});

  17. // gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprint
  18. pki.getPublicKeyFingerprint(key, {
  19.   type: 'SubjectPublicKeyInfo',
  20.   encoding: 'hex',
  21.   delimiter: ':'
  22. });

  23. // gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprint
  24. pki.getPublicKeyFingerprint(key, {
  25.   md: forge.md.md5.create(),
  26.   encoding: 'hex',
  27.   delimiter: ':'
  28. });

  29. // creates a CA store
  30. var caStore = pki.createCaStore([/* PEM-encoded cert */, ...]);

  31. // add a certificate to the CA store
  32. caStore.addCertificate(certObjectOrPemString);

  33. // gets the issuer (its certificate) for the given certificate
  34. var issuerCert = caStore.getIssuer(subjectCert);

  35. // verifies a certificate chain against a CA store
  36. pki.verifyCertificateChain(caStore, chain, customVerifyCallback);

  37. // signs a certificate using the given private key
  38. cert.sign(privateKey);

  39. // signs a certificate using SHA-256 instead of SHA-1
  40. cert.sign(privateKey, forge.md.sha256.create());

  41. // verifies an issued certificate using the certificates public key
  42. var verified = issuer.verify(issued);

  43. // generate a keypair and create an X.509v3 certificate
  44. var keys = pki.rsa.generateKeyPair(2048);
  45. var cert = pki.createCertificate();
  46. cert.publicKey = keys.publicKey;
  47. // alternatively set public key from a csr
  48. //cert.publicKey = csr.publicKey;
  49. // NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
  50. // Conforming CAs should ensure serialNumber is:
  51. // - no more than 20 octets
  52. // - non-negative (prefix a '00' if your value starts with a '1' bit)
  53. cert.serialNumber = '01';
  54. cert.validity.notBefore = new Date();
  55. cert.validity.notAfter = new Date();
  56. cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
  57. var attrs = [{
  58.   name: 'commonName',
  59.   value: 'example.org'
  60. }, {
  61.   name: 'countryName',
  62.   value: 'US'
  63. }, {
  64.   shortName: 'ST',
  65.   value: 'Virginia'
  66. }, {
  67.   name: 'localityName',
  68.   value: 'Blacksburg'
  69. }, {
  70.   name: 'organizationName',
  71.   value: 'Test'
  72. }, {
  73.   shortName: 'OU',
  74.   value: 'Test'
  75. }];
  76. cert.setSubject(attrs);
  77. // alternatively set subject from a csr
  78. //cert.setSubject(csr.subject.attributes);
  79. cert.setIssuer(attrs);
  80. cert.setExtensions([{
  81.   name: 'basicConstraints',
  82.   cA: true
  83. }, {
  84.   name: 'keyUsage',
  85.   keyCertSign: true,
  86.   digitalSignature: true,
  87.   nonRepudiation: true,
  88.   keyEncipherment: true,
  89.   dataEncipherment: true
  90. }, {
  91.   name: 'extKeyUsage',
  92.   serverAuth: true,
  93.   clientAuth: true,
  94.   codeSigning: true,
  95.   emailProtection: true,
  96.   timeStamping: true
  97. }, {
  98.   name: 'nsCertType',
  99.   client: true,
  100.   server: true,
  101.   email: true,
  102.   objsign: true,
  103.   sslCA: true,
  104.   emailCA: true,
  105.   objCA: true
  106. }, {
  107.   name: 'subjectAltName',
  108.   altNames: [{
  109.     type: 6, // URI
  110.     value: 'http://example.org/webid#me'
  111.   }, {
  112.     type: 7, // IP
  113.     ip: '127.0.0.1'
  114.   }]
  115. }, {
  116.   name: 'subjectKeyIdentifier'
  117. }]);
  118. /* alternatively set extensions from a csr
  119. var extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;
  120. // optionally add more extensions
  121. extensions.push.apply(extensions, [{
  122.   name: 'basicConstraints',
  123.   cA: true
  124. }, {
  125.   name: 'keyUsage',
  126.   keyCertSign: true,
  127.   digitalSignature: true,
  128.   nonRepudiation: true,
  129.   keyEncipherment: true,
  130.   dataEncipherment: true
  131. }]);
  132. cert.setExtensions(extensions);
  133. */
  134. // self-sign certificate
  135. cert.sign(keys.privateKey);

  136. // convert a Forge certificate to PEM
  137. var pem = pki.certificateToPem(cert);

  138. // convert a Forge certificate from PEM
  139. var cert = pki.certificateFromPem(pem);

  140. // convert an ASN.1 X.509x3 object to a Forge certificate
  141. var cert = pki.certificateFromAsn1(obj);

  142. // convert a Forge certificate to an ASN.1 X.509v3 object
  143. var asn1Cert = pki.certificateToAsn1(cert);
  144. ```


PKCS#5


Provides the password-based key-derivation function from [PKCS#5][].

__Examples__

  1. ``` js
  2. // generate a password-based 16-byte key
  3. // note an optional message digest can be passed as the final parameter
  4. var salt = forge.random.getBytesSync(128);
  5. var derivedKey = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);

  6. // generate key asynchronously
  7. // note an optional message digest can be passed before the callback
  8. forge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey) {
  9.   // do something w/derivedKey
  10. });
  11. ```


PKCS#7


Provides cryptographically protected messages from [PKCS#7][].

__Examples__

  1. ``` js
  2. // convert a message from PEM
  3. var p7 = forge.pkcs7.messageFromPem(pem);
  4. // look at p7.recipients

  5. // find a recipient by the issuer of a certificate
  6. var recipient = p7.findRecipient(cert);

  7. // decrypt
  8. p7.decrypt(p7.recipients[0], privateKey);

  9. // create a p7 enveloped message
  10. var p7 = forge.pkcs7.createEnvelopedData();

  11. // add a recipient
  12. var cert = forge.pki.certificateFromPem(certPem);
  13. p7.addRecipient(cert);

  14. // set content
  15. p7.content = forge.util.createBuffer('Hello');

  16. // encrypt
  17. p7.encrypt();

  18. // convert message to PEM
  19. var pem = forge.pkcs7.messageToPem(p7);

  20. // create a degenerate PKCS#7 certificate container
  21. // (CRLs not currently supported, only certificates)
  22. var p7 = forge.pkcs7.createSignedData();
  23. p7.addCertificate(certOrCertPem1);
  24. p7.addCertificate(certOrCertPem2);
  25. var pem = forge.pkcs7.messageToPem(p7);

  26. // create PKCS#7 signed data with authenticatedAttributes
  27. // attributes include: PKCS#9 content-type, message-digest, and signing-time
  28. var p7 = forge.pkcs7.createSignedData();
  29. p7.content = forge.util.createBuffer('Some content to be signed.', 'utf8');
  30. p7.addCertificate(certOrCertPem);
  31. p7.addSigner({
  32.   key: privateKeyAssociatedWithCert,
  33.   certificate: certOrCertPem,
  34.   digestAlgorithm: forge.pki.oids.sha256,
  35.   authenticatedAttributes: [{
  36.     type: forge.pki.oids.contentType,
  37.     value: forge.pki.oids.data
  38.   }, {
  39.     type: forge.pki.oids.messageDigest
  40.     // value will be auto-populated at signing time
  41.   }, {
  42.     type: forge.pki.oids.signingTime,
  43.     // value can also be auto-populated at signing time
  44.     value: new Date()
  45.   }]
  46. });
  47. p7.sign();
  48. var pem = forge.pkcs7.messageToPem(p7);

  49. // PKCS#7 Sign in detached mode.
  50. // Includes the signature and certificate without the signed data.
  51. p7.sign({detached: true});

  52. ```


PKCS#8


__Examples__

  1. ``` js
  2. var pki = forge.pki;

  3. // convert a PEM-formatted private key to a Forge private key
  4. var privateKey = pki.privateKeyFromPem(pem);

  5. // convert a Forge private key to PEM-format
  6. var pem = pki.privateKeyToPem(privateKey);

  7. // convert an ASN.1 PrivateKeyInfo or RSAPrivateKey to a Forge private key
  8. var privateKey = pki.privateKeyFromAsn1(rsaPrivateKey);

  9. // convert a Forge private key to an ASN.1 RSAPrivateKey
  10. var rsaPrivateKey = pki.privateKeyToAsn1(privateKey);

  11. // wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfo
  12. var privateKeyInfo = pki.wrapRsaPrivateKey(rsaPrivateKey);

  13. // convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM
  14. var pem = pki.privateKeyInfoToPem(privateKeyInfo);

  15. // encrypts a PrivateKeyInfo using a custom password and
  16. // outputs an EncryptedPrivateKeyInfo
  17. var encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo(
  18.   privateKeyInfo, 'myCustomPasswordHere', {
  19.     algorithm: 'aes256', // 'aes128', 'aes192', 'aes256', '3des'
  20.   });

  21. // decrypts an ASN.1 EncryptedPrivateKeyInfo that was encrypted
  22. // with a custom password
  23. var privateKeyInfo = pki.decryptPrivateKeyInfo(
  24.   encryptedPrivateKeyInfo, 'myCustomPasswordHere');

  25. // converts an EncryptedPrivateKeyInfo to PEM
  26. var pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);

  27. // converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format
  28. var encryptedPrivateKeyInfo = pki.encryptedPrivateKeyFromPem(pem);

  29. // wraps and encrypts a Forge private key and outputs it in PEM format
  30. var pem = pki.encryptRsaPrivateKey(privateKey, 'password');

  31. // encrypts a Forge private key and outputs it in PEM format using OpenSSL's
  32. // proprietary legacy format + encapsulated PEM headers (DEK-Info)
  33. var pem = pki.encryptRsaPrivateKey(privateKey, 'password', {legacy: true});

  34. // decrypts a PEM-formatted, encrypted private key
  35. var privateKey = pki.decryptRsaPrivateKey(pem, 'password');

  36. // sets an RSA public key from a private key
  37. var publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e);
  38. ```


PKCS#10


Provides certification requests or certificate signing requests (CSR) from
[PKCS#10][].

__Examples__

  1. ``` js
  2. // generate a key pair
  3. var keys = forge.pki.rsa.generateKeyPair(2048);

  4. // create a certification request (CSR)
  5. var csr = forge.pki.createCertificationRequest();
  6. csr.publicKey = keys.publicKey;
  7. csr.setSubject([{
  8.   name: 'commonName',
  9.   value: 'example.org'
  10. }, {
  11.   name: 'countryName',
  12.   value: 'US'
  13. }, {
  14.   shortName: 'ST',
  15.   value: 'Virginia'
  16. }, {
  17.   name: 'localityName',
  18.   value: 'Blacksburg'
  19. }, {
  20.   name: 'organizationName',
  21.   value: 'Test'
  22. }, {
  23.   shortName: 'OU',
  24.   value: 'Test'
  25. }]);
  26. // set (optional) attributes
  27. csr.setAttributes([{
  28.   name: 'challengePassword',
  29.   value: 'password'
  30. }, {
  31.   name: 'unstructuredName',
  32.   value: 'My Company, Inc.'
  33. }, {
  34.   name: 'extensionRequest',
  35.   extensions: [{
  36.     name: 'subjectAltName',
  37.     altNames: [{
  38.       // 2 is DNS type
  39.       type: 2,
  40.       value: 'test.domain.com'
  41.     }, {
  42.       type: 2,
  43.       value: 'other.domain.com',
  44.     }, {
  45.       type: 2,
  46.       value: 'www.domain.net'
  47.     }]
  48.   }]
  49. }]);

  50. // sign certification request
  51. csr.sign(keys.privateKey);

  52. // verify certification request
  53. var verified = csr.verify();

  54. // convert certification request to PEM-format
  55. var pem = forge.pki.certificationRequestToPem(csr);

  56. // convert a Forge certification request from PEM-format
  57. var csr = forge.pki.certificationRequestFromPem(pem);

  58. // get an attribute
  59. csr.getAttribute({name: 'challengePassword'});

  60. // get extensions array
  61. csr.getAttribute({name: 'extensionRequest'}).extensions;

  62. ```


PKCS#12


Provides the cryptographic archive file format from [PKCS#12][].

Note for Chrome/Firefox/iOS/similar users: If you have trouble importing
a PKCS#12 container, try using the TripleDES algorithm. It can be passed
to forge.pkcs12.toPkcs12Asn1 using the {algorithm: '3des'} option.

__Examples__

  1. ``` js
  2. // decode p12 from base64
  3. var p12Der = forge.util.decode64(p12b64);
  4. // get p12 as ASN.1 object
  5. var p12Asn1 = forge.asn1.fromDer(p12Der);
  6. // decrypt p12 using the password 'password'
  7. var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');
  8. // decrypt p12 using non-strict parsing mode (resolves some ASN.1 parse errors)
  9. var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, 'password');
  10. // decrypt p12 using literally no password (eg: Mac OS X/apple push)
  11. var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1);
  12. // decrypt p12 using an "empty" password (eg: OpenSSL with no password input)
  13. var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, '');
  14. // p12.safeContents is an array of safe contents, each of
  15. // which contains an array of safeBags

  16. // get bags by friendlyName
  17. var bags = p12.getBags({friendlyName: 'test'});
  18. // bags are key'd by attribute type (here "friendlyName")
  19. // and the key values are an array of matching objects
  20. var cert = bags.friendlyName[0];

  21. // get bags by localKeyId
  22. var bags = p12.getBags({localKeyId: buffer});
  23. // bags are key'd by attribute type (here "localKeyId")
  24. // and the key values are an array of matching objects
  25. var cert = bags.localKeyId[0];

  26. // get bags by localKeyId (input in hex)
  27. var bags = p12.getBags({localKeyIdHex: '7b59377ff142d0be4565e9ac3d396c01401cd879'});
  28. // bags are key'd by attribute type (here "localKeyId", *not* "localKeyIdHex")
  29. // and the key values are an array of matching objects
  30. var cert = bags.localKeyId[0];

  31. // get bags by type
  32. var bags = p12.getBags({bagType: forge.pki.oids.certBag});
  33. // bags are key'd by bagType and each bagType key's value
  34. // is an array of matches (in this case, certificate objects)
  35. var cert = bags[forge.pki.oids.certBag][0];

  36. // get bags by friendlyName and filter on bag type
  37. var bags = p12.getBags({
  38.   friendlyName: 'test',
  39.   bagType: forge.pki.oids.certBag
  40. });

  41. // get key bags
  42. var bags = p12.getBags({bagType: forge.pki.oids.keyBag});
  43. // get key
  44. var bag = bags[forge.pki.oids.keyBag][0];
  45. var key = bag.key;
  46. // if the key is in a format unrecognized by forge then
  47. // bag.key will be `null`, use bag.asn1 to get the ASN.1
  48. // representation of the key
  49. if(bag.key === null) {
  50.   var keyAsn1 = bag.asn1;
  51.   // can now convert back to DER/PEM/etc for export
  52. }

  53. // generate a p12 using AES (default)
  54. var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
  55.   privateKey, certificateChain, 'password');

  56. // generate a p12 that can be imported by Chrome/Firefox/iOS
  57. // (requires the use of Triple DES instead of AES)
  58. var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
  59.   privateKey, certificateChain, 'password',
  60.   {algorithm: '3des'});

  61. // base64-encode p12
  62. var p12Der = forge.asn1.toDer(p12Asn1).getBytes();
  63. var p12b64 = forge.util.encode64(p12Der);

  64. // create download link for p12
  65. var a = document.createElement('a');
  66. a.download = 'example.p12';
  67. a.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12b64);
  68. a.appendChild(document.createTextNode('Download'));
  69. ```


ASN.1


Provides [ASN.1][] DER encoding and decoding.

__Examples__

  1. ``` js
  2. var asn1 = forge.asn1;

  3. // create a SubjectPublicKeyInfo
  4. var subjectPublicKeyInfo =
  5.   asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
  6.     // AlgorithmIdentifier
  7.     asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
  8.       // algorithm
  9.       asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
  10.         asn1.oidToDer(pki.oids['rsaEncryption']).getBytes()),
  11.       // parameters (null)
  12.       asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')
  13.     ]),
  14.     // subjectPublicKey
  15.     asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, [
  16.       // RSAPublicKey
  17.       asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
  18.         // modulus (n)
  19.         asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
  20.           _bnToBytes(key.n)),
  21.         // publicExponent (e)
  22.         asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
  23.           _bnToBytes(key.e))
  24.       ])
  25.     ])
  26.   ]);

  27. // serialize an ASN.1 object to DER format
  28. var derBuffer = asn1.toDer(subjectPublicKeyInfo);

  29. // deserialize to an ASN.1 object from a byte buffer filled with DER data
  30. var object = asn1.fromDer(derBuffer);

  31. // convert an OID dot-separated string to a byte buffer
  32. var derOidBuffer = asn1.oidToDer('1.2.840.113549.1.1.5');

  33. // convert a byte buffer with a DER-encoded OID to a dot-separated string
  34. console.log(asn1.derToOid(derOidBuffer));
  35. // output: 1.2.840.113549.1.1.5

  36. // validates that an ASN.1 object matches a particular ASN.1 structure and
  37. // captures data of interest from that structure for easy access
  38. var publicKeyValidator = {
  39.   name: 'SubjectPublicKeyInfo',
  40.   tagClass: asn1.Class.UNIVERSAL,
  41.   type: asn1.Type.SEQUENCE,
  42.   constructed: true,
  43.   captureAsn1: 'subjectPublicKeyInfo',
  44.   value: [{
  45.     name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',
  46.     tagClass: asn1.Class.UNIVERSAL,
  47.     type: asn1.Type.SEQUENCE,
  48.     constructed: true,
  49.     value: [{
  50.       name: 'AlgorithmIdentifier.algorithm',
  51.       tagClass: asn1.Class.UNIVERSAL,
  52.       type: asn1.Type.OID,
  53.       constructed: false,
  54.       capture: 'publicKeyOid'
  55.     }]
  56.   }, {
  57.     // subjectPublicKey
  58.     name: 'SubjectPublicKeyInfo.subjectPublicKey',
  59.     tagClass: asn1.Class.UNIVERSAL,
  60.     type: asn1.Type.BITSTRING,
  61.     constructed: false,
  62.     value: [{
  63.       // RSAPublicKey
  64.       name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',
  65.       tagClass: asn1.Class.UNIVERSAL,
  66.       type: asn1.Type.SEQUENCE,
  67.       constructed: true,
  68.       optional: true,
  69.       captureAsn1: 'rsaPublicKey'
  70.     }]
  71.   }]
  72. };

  73. var capture = {};
  74. var errors = [];
  75. if(!asn1.validate(
  76.   publicKeyValidator, subjectPublicKeyInfo, validator, capture, errors)) {
  77.   throw 'ASN.1 object is not a SubjectPublicKeyInfo.';
  78. }
  79. // capture.subjectPublicKeyInfo contains the full ASN.1 object
  80. // capture.rsaPublicKey contains the full ASN.1 object for the RSA public key
  81. // capture.publicKeyOid only contains the value for the OID
  82. var oid = asn1.derToOid(capture.publicKeyOid);
  83. if(oid !== pki.oids['rsaEncryption']) {
  84.   throw 'Unsupported OID.';
  85. }

  86. // pretty print an ASN.1 object to a string for debugging purposes
  87. asn1.prettyPrint(object);
  88. ```

Message Digests


SHA1


Provides [SHA-1][] message digests.

__Examples__

  1. ``` js
  2. var md = forge.md.sha1.create();
  3. md.update('The quick brown fox jumps over the lazy dog');
  4. console.log(md.digest().toHex());
  5. // output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
  6. ```


SHA256


Provides [SHA-256][] message digests.

__Examples__

  1. ``` js
  2. var md = forge.md.sha256.create();
  3. md.update('The quick brown fox jumps over the lazy dog');
  4. console.log(md.digest().toHex());
  5. // output: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
  6. ```


SHA384


Provides [SHA-384][] message digests.

__Examples__

  1. ``` js
  2. var md = forge.md.sha384.create();
  3. md.update('The quick brown fox jumps over the lazy dog');
  4. console.log(md.digest().toHex());
  5. // output: ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1
  6. ```


SHA512


Provides [SHA-512][] message digests.

__Examples__

  1. ``` js
  2. // SHA-512
  3. var md = forge.md.sha512.create();
  4. md.update('The quick brown fox jumps over the lazy dog');
  5. console.log(md.digest().toHex());
  6. // output: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6

  7. // SHA-512/224
  8. var md = forge.md.sha512.sha224.create();
  9. md.update('The quick brown fox jumps over the lazy dog');
  10. console.log(md.digest().toHex());
  11. // output: 944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37

  12. // SHA-512/256
  13. var md = forge.md.sha512.sha256.create();
  14. md.update('The quick brown fox jumps over the lazy dog');
  15. console.log(md.digest().toHex());
  16. // output: dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d
  17. ```


MD5


Provides [MD5][] message digests.

__Examples__

  1. ``` js
  2. var md = forge.md.md5.create();
  3. md.update('The quick brown fox jumps over the lazy dog');
  4. console.log(md.digest().toHex());
  5. // output: 9e107d9d372bb6826bd81d3542a419d6
  6. ```


HMAC


Provides [HMAC][] w/any supported message digest algorithm.

__Examples__

  1. ``` js
  2. var hmac = forge.hmac.create();
  3. hmac.start('sha1', 'Jefe');
  4. hmac.update('what do ya want for nothing?');
  5. console.log(hmac.digest().toHex());
  6. // output: effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
  7. ```

Utilities


Prime


Provides an API for generating large, random, probable primes.

__Examples__

  1. ``` js
  2. // generate a random prime on the main JS thread
  3. var bits = 1024;
  4. forge.prime.generateProbablePrime(bits, function(err, num) {
  5.   console.log('random prime', num.toString(16));
  6. });

  7. // generate a random prime using Web Workers (if available, otherwise
  8. // falls back to the main thread)
  9. var bits = 1024;
  10. var options = {
  11.   algorithm: {
  12.     name: 'PRIMEINC',
  13.     workers: -1 // auto-optimize # of workers
  14.   }
  15. };
  16. forge.prime.generateProbablePrime(bits, options, function(err, num) {
  17.   console.log('random prime', num.toString(16));
  18. });
  19. ```


PRNG


Provides a [Fortuna][]-based cryptographically-secure pseudo-random number
generator, to be used with a cryptographic function backend, e.g. [AES][]. An
implementation using [AES][] as a backend is provided. An API for collecting
entropy is given, though if window.crypto.getRandomValues is available, it will
be used automatically.

__Examples__

  1. ``` js
  2. // get some random bytes synchronously
  3. var bytes = forge.random.getBytesSync(32);
  4. console.log(forge.util.bytesToHex(bytes));

  5. // get some random bytes asynchronously
  6. forge.random.getBytes(32, function(err, bytes) {
  7.   console.log(forge.util.bytesToHex(bytes));
  8. });

  9. // collect some entropy if you'd like
  10. forge.random.collect(someRandomBytes);
  11. jQuery().mousemove(function(e) {
  12.   forge.random.collectInt(e.clientX, 16);
  13.   forge.random.collectInt(e.clientY, 16);
  14. });

  15. // specify a seed file for use with the synchronous API if you'd like
  16. forge.random.seedFileSync = function(needed) {
  17.   // get 'needed' number of random bytes from somewhere
  18.   return fetchedRandomBytes;
  19. };

  20. // specify a seed file for use with the asynchronous API if you'd like
  21. forge.random.seedFile = function(needed, callback) {
  22.   // get the 'needed' number of random bytes from somewhere
  23.   callback(null, fetchedRandomBytes);
  24. });

  25. // register the main thread to send entropy or a Web Worker to receive
  26. // entropy on demand from the main thread
  27. forge.random.registerWorker(self);

  28. // generate a new instance of a PRNG with no collected entropy
  29. var myPrng = forge.random.createInstance();
  30. ```


Tasks


Provides queuing and synchronizing tasks in a web application.

__Examples__

  1. ``` js
  2. // TODO
  3. ```


Utilities


Provides utility functions, including byte buffer support, base64,
bytes to/from hex, zlib inflate/deflate, etc.

__Examples__

  1. ``` js
  2. // encode/decode base64
  3. var encoded = forge.util.encode64(str);
  4. var str = forge.util.decode64(encoded);

  5. // encode/decode UTF-8
  6. var encoded = forge.util.encodeUtf8(str);
  7. var str = forge.util.decodeUtf8(encoded);

  8. // bytes to/from hex
  9. var bytes = forge.util.hexToBytes(hex);
  10. var hex = forge.util.bytesToHex(bytes);

  11. // create an empty byte buffer
  12. var buffer = forge.util.createBuffer();
  13. // create a byte buffer from raw binary bytes
  14. var buffer = forge.util.createBuffer(input, 'raw');
  15. // create a byte buffer from utf8 bytes
  16. var buffer = forge.util.createBuffer(input, 'utf8');

  17. // get the length of the buffer in bytes
  18. buffer.length();
  19. // put bytes into the buffer
  20. buffer.putBytes(bytes);
  21. // put a 32-bit integer into the buffer
  22. buffer.putInt32(10);
  23. // buffer to hex
  24. buffer.toHex();
  25. // get a copy of the bytes in the buffer
  26. bytes.bytes(/* count */);
  27. // empty this buffer and get its contents
  28. bytes.getBytes(/* count */);

  29. // convert a forge buffer into a Node.js Buffer
  30. // make sure you specify the encoding as 'binary'
  31. var forgeBuffer = forge.util.createBuffer();
  32. var nodeBuffer = Buffer.from(forgeBuffer.getBytes(), 'binary');

  33. // convert a Node.js Buffer into a forge buffer
  34. // make sure you specify the encoding as 'binary'
  35. var nodeBuffer = Buffer.from('CAFE', 'hex');
  36. var forgeBuffer = forge.util.createBuffer(nodeBuffer.toString('binary'));
  37. ```


Logging


Provides logging to a javascript console using various categories and
levels of verbosity.

__Examples__

  1. ``` js
  2. // TODO
  3. ```


Flash Networking Support


The flash README provides details on rebuilding the
optional Flash component used for networking. It also provides details on
Policy Server support.

Security Considerations

When using this code please keep the following in mind:

- Cryptography is hard. Please review and test this code before depending on it
  for critical functionality.
- The nature of JavaScript is that execution of this code depends on trusting a
  very large set of JavaScript tools and systems. Consider runtime variations,
  runtime characteristics, runtime optimization, code optimization, code
  minimization, code obfuscation, bundling tools, possible bugs, the Forge code
  itself, and so on.
- If using pre-built bundles from [NPM][], another CDN, or similar, be aware
  someone else ran the tools to create those files.
- Use a secure transport channel such as [TLS][] to load scripts and consider
  using additional security mechanisms such as [Subresource Integrity][] script
  attributes.
- Use "native" functionality where possible. This can be critical when dealing
  with performance and random number generation. Note that the JavaScript
  random number algorithms should perform well if given suitable entropy.
- Understand possible attacks against cryptographic systems. For instance side
  channel and timing attacks may be possible due to the difficulty in
  implementing constant time algorithms in pure JavaScript.
- Certain features in this library are less susceptible to attacks depending on
  usage. This primarily includes features that deal with data format
  manipulation or those that are not involved in communication.

Library Background

https://digitalbazaar.com/2010/07/20/javascript-tls-1/
https://digitalbazaar.com/2010/07/20/javascript-tls-2/

Contact

Code: https://github.com/digitalbazaar/forge
Bugs: https://github.com/digitalbazaar/forge/issues
Email: support@digitalbazaar.com
IRC: [#forgejs][] on [Libera.Chat][] (people may also be on [freenode][] for
  historical reasons).

Donations

Financial support is welcome and helps contribute to futher development:

For [PayPal][] please send to paypal@digitalbazaar.com.
Something else? Please contact support@digitalbazaar.com.

[#forgejs]: https://webchat.freenode.net/?channels=#forgejs
[0.6.x]: https://github.com/digitalbazaar/forge/tree/0.6.x
[3DES]: https://en.wikipedia.org/wiki/Triple_DES
[AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
[ASN.1]: https://en.wikipedia.org/wiki/ASN.1
[Browserify]: http://browserify.org/
[CBC]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[CFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[CTR]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[CommonJS]: https://en.wikipedia.org/wiki/CommonJS
[DES]: https://en.wikipedia.org/wiki/Data_Encryption_Standard
[ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[Fortuna]: https://en.wikipedia.org/wiki/Fortuna_(PRNG)
[GCM]: https://en.wikipedia.org/wiki/GCM_mode
[HMAC]: https://en.wikipedia.org/wiki/HMAC
[JavaScript]: https://en.wikipedia.org/wiki/JavaScript
[Karma]: https://karma-runner.github.io/
[Libera.Chat]: https://libera.chat/
[MD5]: https://en.wikipedia.org/wiki/MD5
[NPM]: https://www.npmjs.com/
[Node.js]: https://nodejs.org/
[OFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
[PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request
[PKCS#12]: https://en.wikipedia.org/wiki/PKCS_%E2%99%AF12
[PKCS#5]: https://en.wikipedia.org/wiki/PKCS
[PKCS#7]: https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax
[PayPal]: https://www.paypal.com/
[RC2]: https://en.wikipedia.org/wiki/RC2
[SHA-1]: https://en.wikipedia.org/wiki/SHA-1
[SHA-256]: https://en.wikipedia.org/wiki/SHA-256
[SHA-384]: https://en.wikipedia.org/wiki/SHA-384
[SHA-512]: https://en.wikipedia.org/wiki/SHA-512
[Subresource Integrity]: https://www.w3.org/TR/SRI/
[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
[UMD]: https://github.com/umdjs/umd
[X.509]: https://en.wikipedia.org/wiki/X.509
[freenode]: https://freenode.net/
[unpkg]: https://unpkg.com/
[webpack]: https://webpack.github.io/
[TweetNaCl.js]: https://github.com/dchest/tweetnacl-js