forge
Forge
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:
var forge = require('node-forge');
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:
<script src="https://cdn.jsdelivr.net/npm/node-forge@1.0.0/dist/forge.min.js"></script>
unpkg CDN
To use it via unpkg include this in your html:
<script src="https://unpkg.com/node-forge@1.0.0/dist/forge.min.js"></script>
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:
<script src="YOUR_SCRIPT_PATH/forge.js"></script>
or
<script src="YOUR_SCRIPT_PATH/forge.min.js"></script>
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:
// run this *after* including the forge script forge.options.usePureJavaScript = true;
To disable native code when using Node.js:
var forge = require('node-forge'); forge.options.usePureJavaScript = true;
Transports
TLS
Provides a native javascript client and server-side TLS implementation.
Examples
// create TLS client var client = forge.tls.createConnection({ server: false, caStore: /* Array of PEM-formatted certs or a CA store object */, sessionCache: {}, // supported cipher suites in order of preference cipherSuites: [ forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA, forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA], virtualHost: 'example.com', verify: function(connection, verified, depth, certs) { if(depth === 0) { var cn = certs[0].subject.getField('CN').value; if(cn !== 'example.com') { verified = { alert: forge.tls.Alert.Description.bad_certificate, message: 'Certificate common name does not match hostname.' }; } } return verified; }, connected: function(connection) { console.log('connected'); // send message to server connection.prepare(forge.util.encodeUtf8('Hi server!')); /* NOTE: experimental, start heartbeat retransmission timer myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000);*/ }, /* provide a client-side cert if you want getCertificate: function(connection, hint) { return myClientCertificate; }, /* the private key for the client-side cert if provided */ getPrivateKey: function(connection, cert) { return myClientPrivateKey; }, tlsDataReady: function(connection) { // TLS data (encrypted) is ready to be sent to the server sendToServerSomehow(connection.tlsData.getBytes()); // if you were communicating with the server below, you'd do: // server.process(connection.tlsData.getBytes()); }, dataReady: function(connection) { // clear data from the server is ready console.log('the server sent: ' + forge.util.decodeUtf8(connection.data.getBytes())); // close connection connection.close(); }, /* NOTE: experimental heartbeatReceived: function(connection, payload) { // restart retransmission timer, look at payload clearInterval(myHeartbeatTimer); myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000); payload.getBytes(); },*/ closed: function(connection) { console.log('disconnected'); }, error: function(connection, error) { console.log('uh oh', error); } }); // start the handshake process client.handshake(); // when encrypted TLS data is received from the server, process it client.process(encryptedBytesFromServer); // create TLS server var server = forge.tls.createConnection({ server: true, caStore: /* Array of PEM-formatted certs or a CA store object */, sessionCache: {}, // supported cipher suites in order of preference cipherSuites: [ forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA, forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA], // require a client-side certificate if you want verifyClient: true, verify: function(connection, verified, depth, certs) { if(depth === 0) { var cn = certs[0].subject.getField('CN').value; if(cn !== 'the-client') { verified = { alert: forge.tls.Alert.Description.bad_certificate, message: 'Certificate common name does not match expected client.' }; } } return verified; }, connected: function(connection) { console.log('connected'); // send message to client connection.prepare(forge.util.encodeUtf8('Hi client!')); /* NOTE: experimental, start heartbeat retransmission timer myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000);*/ }, getCertificate:...