UNPKG

60.2 kBMarkdownView Raw
1# Forge
2
3[![npm package](https://nodei.co/npm/node-forge.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/node-forge/)
4
5[![Build status](https://img.shields.io/travis/digitalbazaar/forge.svg?branch=master)](https://travis-ci.org/digitalbazaar/forge)
6
7A native implementation of [TLS][] (and various other cryptographic tools) in
8[JavaScript][].
9
10Introduction
11------------
12
13The Forge software is a fully native implementation of the [TLS][] protocol
14in JavaScript, a set of cryptography utilities, and a set of tools for
15developing Web Apps that utilize many network resources.
16
17Performance
18------------
19
20Forge is fast. Benchmarks against other popular JavaScript cryptography
21libraries can be found here:
22
23* http://dominictarr.github.io/crypto-bench/
24* http://cryptojs.altervista.org/test/simulate-threading-speed_test.html
25
26Documentation
27-------------
28
29* [Introduction](#introduction)
30* [Performance](#performance)
31* [Installation](#installation)
32* [Testing](#testing)
33* [Contributing](#contributing)
34
35### API
36
37* [Options](#options)
38
39### Transports
40
41* [TLS](#tls)
42* [HTTP](#http)
43* [SSH](#ssh)
44* [XHR](#xhr)
45* [Sockets](#socket)
46
47### Ciphers
48
49* [CIPHER](#cipher)
50* [AES](#aes)
51* [DES](#des)
52* [RC2](#rc2)
53
54### PKI
55
56* [ED25519](#ed25519)
57* [RSA](#rsa)
58* [RSA-KEM](#rsakem)
59* [X.509](#x509)
60* [PKCS#5](#pkcs5)
61* [PKCS#7](#pkcs7)
62* [PKCS#8](#pkcs8)
63* [PKCS#10](#pkcs10)
64* [PKCS#12](#pkcs12)
65* [ASN.1](#asn)
66
67### Message Digests
68
69* [SHA1](#sha1)
70* [SHA256](#sha256)
71* [SHA384](#sha384)
72* [SHA512](#sha512)
73* [MD5](#md5)
74* [HMAC](#hmac)
75
76### Utilities
77
78* [Prime](#prime)
79* [PRNG](#prng)
80* [Tasks](#task)
81* [Utilities](#util)
82* [Logging](#log)
83* [Debugging](#debug)
84* [Flash Networking Support](#flash)
85
86### Other
87
88* [Security Considerations](#security-considerations)
89* [Library Background](#library-background)
90* [Contact](#contact)
91* [Donations](#donations)
92
93---------------------------------------
94
95Installation
96------------
97
98**Note**: Please see the [Security Considerations](#security-considerations)
99section before using packaging systems and pre-built files.
100
101Forge uses a [CommonJS][] module structure with a build process for browser
102bundles. The older [0.6.x][] branch with standalone files is available but will
103not be regularly updated.
104
105### Node.js
106
107If you want to use forge with [Node.js][], it is available through `npm`:
108
109https://npmjs.org/package/node-forge
110
111Installation:
112
113 npm install node-forge
114
115You can then use forge as a regular module:
116
117```js
118var forge = require('node-forge');
119```
120
121The npm package includes pre-built `forge.min.js`, `forge.all.min.js`, and
122`prime.worker.min.js` using the [UMD][] format.
123
124### Bundle / Bower
125
126Each release is published in a separate repository as pre-built and minimized
127basic forge bundles using the [UMD][] format.
128
129https://github.com/digitalbazaar/forge-dist
130
131This bundle can be used in many environments. In particular it can be installed
132with [Bower][]:
133
134 bower install forge
135
136### jsDelivr CDN
137
138To use it via [jsDelivr](https://www.jsdelivr.com/package/npm/node-forge) include this in your html:
139
140```html
141<script src="https://cdn.jsdelivr.net/npm/node-forge@0.7.0/dist/forge.min.js"></script>
142```
143
144### unpkg CDN
145
146To use it via [unpkg](https://unpkg.com/#/) include this in your html:
147
148```html
149<script src="https://unpkg.com/node-forge@0.7.0/dist/forge.min.js"></script>
150```
151
152### Development Requirements
153
154The core JavaScript has the following requirements to build and test:
155
156* Building a browser bundle:
157 * Node.js
158 * npm
159* Testing
160 * Node.js
161 * npm
162 * Chrome, Firefox, Safari (optional)
163
164Some special networking features can optionally use a Flash component. See the
165[Flash README](./flash/README.md) for details.
166
167### Building for a web browser
168
169To create single file bundles for use with browsers run the following:
170
171 npm install
172 npm run build
173
174This will create single non-minimized and minimized files that can be
175included in the browser:
176
177 dist/forge.js
178 dist/forge.min.js
179
180A bundle that adds some utilities and networking support is also available:
181
182 dist/forge.all.js
183 dist/forge.all.min.js
184
185Include the file via:
186
187```html
188<script src="YOUR_SCRIPT_PATH/forge.js"></script>
189```
190or
191```html
192<script src="YOUR_SCRIPT_PATH/forge.min.js"></script>
193```
194
195The above bundles will synchronously create a global 'forge' object.
196
197**Note**: These bundles will not include any WebWorker scripts (eg:
198`dist/prime.worker.js`), so these will need to be accessible from the browser
199if any WebWorkers are used.
200
201### Building a custom browser bundle
202
203The build process uses [webpack][] and the [config](./webpack.config.js) file
204can be modified to generate a file or files that only contain the parts of
205forge you need.
206
207[Browserify][] override support is also present in `package.json`.
208
209Testing
210-------
211
212### Prepare to run tests
213
214 npm install
215
216### Running automated tests with Node.js
217
218Forge natively runs in a [Node.js][] environment:
219
220 npm test
221
222### Running automated tests with Headless Chrome
223
224Automated testing is done via [Karma][]. By default it will run the tests with
225Headless Chrome.
226
227 npm run test-karma
228
229Is 'mocha' reporter output too verbose? Other reporters are available. Try
230'dots', 'progress', or 'tap'.
231
232 npm run test-karma -- --reporters progress
233
234By default [webpack][] is used. [Browserify][] can also be used.
235
236 BUNDLER=browserify npm run test-karma
237
238### Running automated tests with one or more browsers
239
240You can also specify one or more browsers to use.
241
242 npm run test-karma -- --browsers Chrome,Firefox,Safari,ChromeHeadless
243
244The reporter option and `BUNDLER` environment variable can also be used.
245
246### Running manual tests in a browser
247
248Testing in a browser uses [webpack][] to combine forge and all tests and then
249loading the result in a browser. A simple web server is provided that will
250output the HTTP or HTTPS URLs to load. It also will start a simple Flash Policy
251Server. Unit tests and older legacy tests are provided. Custom ports can be
252used by running `node tests/server.js` manually.
253
254To run the unit tests in a browser a special forge build is required:
255
256 npm run test-build
257
258To run legacy browser based tests the main forge build is required:
259
260 npm run build
261
262The tests are run with a custom server that prints out the URLs to use:
263
264 npm run test-server
265
266### Running other tests
267
268There are some other random tests and benchmarks available in the tests
269directory.
270
271### Coverage testing
272
273To perform coverage testing of the unit tests, run the following. The results
274will be put in the `coverage/` directory. Note that coverage testing can slow
275down some tests considerably.
276
277 npm install
278 npm run coverage
279
280Contributing
281------------
282
283Any contributions (eg: PRs) that are accepted will be brought under the same
284license used by the rest of the Forge project. This license allows Forge to
285be used under the terms of either the BSD License or the GNU General Public
286License (GPL) Version 2.
287
288See: [LICENSE](https://github.com/digitalbazaar/forge/blob/cbebca3780658703d925b61b2caffb1d263a6c1d/LICENSE)
289
290If a contribution contains 3rd party source code with its own license, it
291may retain it, so long as that license is compatible with the Forge license.
292
293API
294---
295
296<a name="options" />
297
298### Options
299
300If at any time you wish to disable the use of native code, where available,
301for particular forge features like its secure random number generator, you
302may set the ```forge.options.usePureJavaScript``` flag to ```true```. It is
303not recommended that you set this flag as native code is typically more
304performant and may have stronger security properties. It may be useful to
305set this flag to test certain features that you plan to run in environments
306that are different from your testing environment.
307
308To disable native code when including forge in the browser:
309
310```js
311// run this *after* including the forge script
312forge.options.usePureJavaScript = true;
313```
314
315To disable native code when using Node.js:
316
317```js
318var forge = require('node-forge');
319forge.options.usePureJavaScript = true;
320```
321
322Transports
323----------
324
325<a name="tls" />
326
327### TLS
328
329Provides a native javascript client and server-side [TLS][] implementation.
330
331__Examples__
332
333```js
334// create TLS client
335var client = forge.tls.createConnection({
336 server: false,
337 caStore: /* Array of PEM-formatted certs or a CA store object */,
338 sessionCache: {},
339 // supported cipher suites in order of preference
340 cipherSuites: [
341 forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
342 forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
343 virtualHost: 'example.com',
344 verify: function(connection, verified, depth, certs) {
345 if(depth === 0) {
346 var cn = certs[0].subject.getField('CN').value;
347 if(cn !== 'example.com') {
348 verified = {
349 alert: forge.tls.Alert.Description.bad_certificate,
350 message: 'Certificate common name does not match hostname.'
351 };
352 }
353 }
354 return verified;
355 },
356 connected: function(connection) {
357 console.log('connected');
358 // send message to server
359 connection.prepare(forge.util.encodeUtf8('Hi server!'));
360 /* NOTE: experimental, start heartbeat retransmission timer
361 myHeartbeatTimer = setInterval(function() {
362 connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
363 }, 5*60*1000);*/
364 },
365 /* provide a client-side cert if you want
366 getCertificate: function(connection, hint) {
367 return myClientCertificate;
368 },
369 /* the private key for the client-side cert if provided */
370 getPrivateKey: function(connection, cert) {
371 return myClientPrivateKey;
372 },
373 tlsDataReady: function(connection) {
374 // TLS data (encrypted) is ready to be sent to the server
375 sendToServerSomehow(connection.tlsData.getBytes());
376 // if you were communicating with the server below, you'd do:
377 // server.process(connection.tlsData.getBytes());
378 },
379 dataReady: function(connection) {
380 // clear data from the server is ready
381 console.log('the server sent: ' +
382 forge.util.decodeUtf8(connection.data.getBytes()));
383 // close connection
384 connection.close();
385 },
386 /* NOTE: experimental
387 heartbeatReceived: function(connection, payload) {
388 // restart retransmission timer, look at payload
389 clearInterval(myHeartbeatTimer);
390 myHeartbeatTimer = setInterval(function() {
391 connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
392 }, 5*60*1000);
393 payload.getBytes();
394 },*/
395 closed: function(connection) {
396 console.log('disconnected');
397 },
398 error: function(connection, error) {
399 console.log('uh oh', error);
400 }
401});
402
403// start the handshake process
404client.handshake();
405
406// when encrypted TLS data is received from the server, process it
407client.process(encryptedBytesFromServer);
408
409// create TLS server
410var server = forge.tls.createConnection({
411 server: true,
412 caStore: /* Array of PEM-formatted certs or a CA store object */,
413 sessionCache: {},
414 // supported cipher suites in order of preference
415 cipherSuites: [
416 forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
417 forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
418 // require a client-side certificate if you want
419 verifyClient: true,
420 verify: function(connection, verified, depth, certs) {
421 if(depth === 0) {
422 var cn = certs[0].subject.getField('CN').value;
423 if(cn !== 'the-client') {
424 verified = {
425 alert: forge.tls.Alert.Description.bad_certificate,
426 message: 'Certificate common name does not match expected client.'
427 };
428 }
429 }
430 return verified;
431 },
432 connected: function(connection) {
433 console.log('connected');
434 // send message to client
435 connection.prepare(forge.util.encodeUtf8('Hi client!'));
436 /* NOTE: experimental, start heartbeat retransmission timer
437 myHeartbeatTimer = setInterval(function() {
438 connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
439 }, 5*60*1000);*/
440 },
441 getCertificate: function(connection, hint) {
442 return myServerCertificate;
443 },
444 getPrivateKey: function(connection, cert) {
445 return myServerPrivateKey;
446 },
447 tlsDataReady: function(connection) {
448 // TLS data (encrypted) is ready to be sent to the client
449 sendToClientSomehow(connection.tlsData.getBytes());
450 // if you were communicating with the client above you'd do:
451 // client.process(connection.tlsData.getBytes());
452 },
453 dataReady: function(connection) {
454 // clear data from the client is ready
455 console.log('the client sent: ' +
456 forge.util.decodeUtf8(connection.data.getBytes()));
457 // close connection
458 connection.close();
459 },
460 /* NOTE: experimental
461 heartbeatReceived: function(connection, payload) {
462 // restart retransmission timer, look at payload
463 clearInterval(myHeartbeatTimer);
464 myHeartbeatTimer = setInterval(function() {
465 connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
466 }, 5*60*1000);
467 payload.getBytes();
468 },*/
469 closed: function(connection) {
470 console.log('disconnected');
471 },
472 error: function(connection, error) {
473 console.log('uh oh', error);
474 }
475});
476
477// when encrypted TLS data is received from the client, process it
478server.process(encryptedBytesFromClient);
479```
480
481Connect to a TLS server using node's net.Socket:
482
483```js
484var socket = new net.Socket();
485
486var client = forge.tls.createConnection({
487 server: false,
488 verify: function(connection, verified, depth, certs) {
489 // skip verification for testing
490 console.log('[tls] server certificate verified');
491 return true;
492 },
493 connected: function(connection) {
494 console.log('[tls] connected');
495 // prepare some data to send (note that the string is interpreted as
496 // 'binary' encoded, which works for HTTP which only uses ASCII, use
497 // forge.util.encodeUtf8(str) otherwise
498 client.prepare('GET / HTTP/1.0\r\n\r\n');
499 },
500 tlsDataReady: function(connection) {
501 // encrypted data is ready to be sent to the server
502 var data = connection.tlsData.getBytes();
503 socket.write(data, 'binary'); // encoding should be 'binary'
504 },
505 dataReady: function(connection) {
506 // clear data from the server is ready
507 var data = connection.data.getBytes();
508 console.log('[tls] data received from the server: ' + data);
509 },
510 closed: function() {
511 console.log('[tls] disconnected');
512 },
513 error: function(connection, error) {
514 console.log('[tls] error', error);
515 }
516});
517
518socket.on('connect', function() {
519 console.log('[socket] connected');
520 client.handshake();
521});
522socket.on('data', function(data) {
523 client.process(data.toString('binary')); // encoding should be 'binary'
524});
525socket.on('end', function() {
526 console.log('[socket] disconnected');
527});
528
529// connect to google.com
530socket.connect(443, 'google.com');
531
532// or connect to gmail's imap server (but don't send the HTTP header above)
533//socket.connect(993, 'imap.gmail.com');
534```
535
536<a name="http" />
537
538### HTTP
539
540Provides a native [JavaScript][] mini-implementation of an http client that
541uses pooled sockets.
542
543__Examples__
544
545```js
546// create an HTTP GET request
547var request = forge.http.createRequest({method: 'GET', path: url.path});
548
549// send the request somewhere
550sendSomehow(request.toString());
551
552// receive response
553var buffer = forge.util.createBuffer();
554var response = forge.http.createResponse();
555var someAsyncDataHandler = function(bytes) {
556 if(!response.bodyReceived) {
557 buffer.putBytes(bytes);
558 if(!response.headerReceived) {
559 if(response.readHeader(buffer)) {
560 console.log('HTTP response header: ' + response.toString());
561 }
562 }
563 if(response.headerReceived && !response.bodyReceived) {
564 if(response.readBody(buffer)) {
565 console.log('HTTP response body: ' + response.body);
566 }
567 }
568 }
569};
570```
571
572<a name="ssh" />
573
574### SSH
575
576Provides some SSH utility functions.
577
578__Examples__
579
580```js
581// encodes (and optionally encrypts) a private RSA key as a Putty PPK file
582forge.ssh.privateKeyToPutty(privateKey, passphrase, comment);
583
584// encodes a public RSA key as an OpenSSH file
585forge.ssh.publicKeyToOpenSSH(key, comment);
586
587// encodes a private RSA key as an OpenSSH file
588forge.ssh.privateKeyToOpenSSH(privateKey, passphrase);
589
590// gets the SSH public key fingerprint in a byte buffer
591forge.ssh.getPublicKeyFingerprint(key);
592
593// gets a hex-encoded, colon-delimited SSH public key fingerprint
594forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
595```
596
597<a name="xhr" />
598
599### XHR
600
601Provides an XmlHttpRequest implementation using forge.http as a backend.
602
603__Examples__
604
605```js
606// TODO
607```
608
609<a name="socket" />
610
611### Sockets
612
613Provides an interface to create and use raw sockets provided via Flash.
614
615__Examples__
616
617```js
618// TODO
619```
620
621Ciphers
622-------
623
624<a name="cipher" />
625
626### CIPHER
627
628Provides a basic API for block encryption and decryption. There is built-in
629support for the ciphers: [AES][], [3DES][], and [DES][], and for the modes
630of operation: [ECB][], [CBC][], [CFB][], [OFB][], [CTR][], and [GCM][].
631
632These algorithms are currently supported:
633
634* AES-ECB
635* AES-CBC
636* AES-CFB
637* AES-OFB
638* AES-CTR
639* AES-GCM
640* 3DES-ECB
641* 3DES-CBC
642* DES-ECB
643* DES-CBC
644
645When using an [AES][] algorithm, the key size will determine whether
646AES-128, AES-192, or AES-256 is used (all are supported). When a [DES][]
647algorithm is used, the key size will determine whether [3DES][] or regular
648[DES][] is used. Use a [3DES][] algorithm to enforce Triple-DES.
649
650__Examples__
651
652```js
653// generate a random key and IV
654// Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256
655var key = forge.random.getBytesSync(16);
656var iv = forge.random.getBytesSync(16);
657
658/* alternatively, generate a password-based 16-byte key
659var salt = forge.random.getBytesSync(128);
660var key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
661*/
662
663// encrypt some bytes using CBC mode
664// (other modes include: ECB, CFB, OFB, CTR, and GCM)
665// Note: CBC and ECB modes use PKCS#7 padding as default
666var cipher = forge.cipher.createCipher('AES-CBC', key);
667cipher.start({iv: iv});
668cipher.update(forge.util.createBuffer(someBytes));
669cipher.finish();
670var encrypted = cipher.output;
671// outputs encrypted hex
672console.log(encrypted.toHex());
673
674// decrypt some bytes using CBC mode
675// (other modes include: CFB, OFB, CTR, and GCM)
676var decipher = forge.cipher.createDecipher('AES-CBC', key);
677decipher.start({iv: iv});
678decipher.update(encrypted);
679var result = decipher.finish(); // check 'result' for true/false
680// outputs decrypted hex
681console.log(decipher.output.toHex());
682
683// decrypt bytes using CBC mode and streaming
684// Performance can suffer for large multi-MB inputs due to buffer
685// manipulations. Stream processing in chunks can offer significant
686// improvement. CPU intensive update() calls could also be performed with
687// setImmediate/setTimeout to avoid blocking the main browser UI thread (not
688// shown here). Optimal block size depends on the JavaScript VM and other
689// factors. Encryption can use a simple technique for increased performance.
690var encryptedBytes = encrypted.bytes();
691var decipher = forge.cipher.createDecipher('AES-CBC', key);
692decipher.start({iv: iv});
693var length = encryptedBytes.length;
694var chunkSize = 1024 * 64;
695var index = 0;
696var decrypted = '';
697do {
698 decrypted += decipher.output.getBytes();
699 var buf = forge.util.createBuffer(encryptedBytes.substr(index, chunkSize));
700 decipher.update(buf);
701 index += chunkSize;
702} while(index < length);
703var result = decipher.finish();
704assert(result);
705decrypted += decipher.output.getBytes();
706console.log(forge.util.bytesToHex(decrypted));
707
708// encrypt some bytes using GCM mode
709var cipher = forge.cipher.createCipher('AES-GCM', key);
710cipher.start({
711 iv: iv, // should be a 12-byte binary-encoded string or byte buffer
712 additionalData: 'binary-encoded string', // optional
713 tagLength: 128 // optional, defaults to 128 bits
714});
715cipher.update(forge.util.createBuffer(someBytes));
716cipher.finish();
717var encrypted = cipher.output;
718var tag = cipher.mode.tag;
719// outputs encrypted hex
720console.log(encrypted.toHex());
721// outputs authentication tag
722console.log(tag.toHex());
723
724// decrypt some bytes using GCM mode
725var decipher = forge.cipher.createDecipher('AES-GCM', key);
726decipher.start({
727 iv: iv,
728 additionalData: 'binary-encoded string', // optional
729 tagLength: 128, // optional, defaults to 128 bits
730 tag: tag // authentication tag from encryption
731});
732decipher.update(encrypted);
733var pass = decipher.finish();
734// pass is false if there was a failure (eg: authentication tag didn't match)
735if(pass) {
736 // outputs decrypted hex
737 console.log(decipher.output.toHex());
738}
739```
740
741Using 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/)):
742
743```js
744var forge = require('node-forge');
745var fs = require('fs');
746
747// openssl enc -des3 -in input.txt -out input.enc
748function encrypt(password) {
749 var input = fs.readFileSync('input.txt', {encoding: 'binary'});
750
751 // 3DES key and IV sizes
752 var keySize = 24;
753 var ivSize = 8;
754
755 // get derived bytes
756 // Notes:
757 // 1. If using an alternative hash (eg: "-md sha1") pass
758 // "forge.md.sha1.create()" as the final parameter.
759 // 2. If using "-nosalt", set salt to null.
760 var salt = forge.random.getBytesSync(8);
761 // var md = forge.md.sha1.create(); // "-md sha1"
762 var derivedBytes = forge.pbe.opensslDeriveBytes(
763 password, salt, keySize + ivSize/*, md*/);
764 var buffer = forge.util.createBuffer(derivedBytes);
765 var key = buffer.getBytes(keySize);
766 var iv = buffer.getBytes(ivSize);
767
768 var cipher = forge.cipher.createCipher('3DES-CBC', key);
769 cipher.start({iv: iv});
770 cipher.update(forge.util.createBuffer(input, 'binary'));
771 cipher.finish();
772
773 var output = forge.util.createBuffer();
774
775 // if using a salt, prepend this to the output:
776 if(salt !== null) {
777 output.putBytes('Salted__'); // (add to match openssl tool output)
778 output.putBytes(salt);
779 }
780 output.putBuffer(cipher.output);
781
782 fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'});
783}
784
785// openssl enc -d -des3 -in input.enc -out input.dec.txt
786function decrypt(password) {
787 var input = fs.readFileSync('input.enc', {encoding: 'binary'});
788
789 // parse salt from input
790 input = forge.util.createBuffer(input, 'binary');
791 // skip "Salted__" (if known to be present)
792 input.getBytes('Salted__'.length);
793 // read 8-byte salt
794 var salt = input.getBytes(8);
795
796 // Note: if using "-nosalt", skip above parsing and use
797 // var salt = null;
798
799 // 3DES key and IV sizes
800 var keySize = 24;
801 var ivSize = 8;
802
803 var derivedBytes = forge.pbe.opensslDeriveBytes(
804 password, salt, keySize + ivSize);
805 var buffer = forge.util.createBuffer(derivedBytes);
806 var key = buffer.getBytes(keySize);
807 var iv = buffer.getBytes(ivSize);
808
809 var decipher = forge.cipher.createDecipher('3DES-CBC', key);
810 decipher.start({iv: iv});
811 decipher.update(input);
812 var result = decipher.finish(); // check 'result' for true/false
813
814 fs.writeFileSync(
815 'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'});
816}
817```
818
819<a name="aes" />
820
821### AES
822
823Provides [AES][] encryption and decryption in [CBC][], [CFB][], [OFB][],
824[CTR][], and [GCM][] modes. See [CIPHER](#cipher) for examples.
825
826<a name="des" />
827
828### DES
829
830Provides [3DES][] and [DES][] encryption and decryption in [ECB][] and
831[CBC][] modes. See [CIPHER](#cipher) for examples.
832
833<a name="rc2" />
834
835### RC2
836
837__Examples__
838
839```js
840// generate a random key and IV
841var key = forge.random.getBytesSync(16);
842var iv = forge.random.getBytesSync(8);
843
844// encrypt some bytes
845var cipher = forge.rc2.createEncryptionCipher(key);
846cipher.start(iv);
847cipher.update(forge.util.createBuffer(someBytes));
848cipher.finish();
849var encrypted = cipher.output;
850// outputs encrypted hex
851console.log(encrypted.toHex());
852
853// decrypt some bytes
854var cipher = forge.rc2.createDecryptionCipher(key);
855cipher.start(iv);
856cipher.update(encrypted);
857cipher.finish();
858// outputs decrypted hex
859console.log(cipher.output.toHex());
860```
861
862PKI
863---
864
865Provides [X.509][] certificate support, ED25519 key generation and
866signing/verifying, and RSA public and private key encoding, decoding,
867encryption/decryption, and signing/verifying.
868
869<a name="ed25519" />
870
871### ED25519
872
873Special thanks to [TweetNaCl.js][] for providing the bulk of the implementation.
874
875__Examples__
876
877```js
878var ed25519 = forge.pki.ed25519;
879
880// generate a random ED25519 keypair
881var keypair = ed25519.generateKeyPair();
882// `keypair.publicKey` is a node.js Buffer or Uint8Array
883// `keypair.privateKey` is a node.js Buffer or Uint8Array
884
885// generate a random ED25519 keypair based on a random 32-byte seed
886var seed = forge.random.getBytesSync(32);
887var keypair = ed25519.generateKeyPair({seed: seed});
888
889// generate a random ED25519 keypair based on a "password" 32-byte seed
890var password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
891var seed = new forge.util.ByteBuffer(password, 'utf8');
892var keypair = ed25519.generateKeyPair({seed: seed});
893
894// sign a UTF-8 message
895var signature = ED25519.sign({
896 message: 'test',
897 // also accepts `binary` if you want to pass a binary string
898 encoding: 'utf8',
899 // node.js Buffer, Uint8Array, forge ByteBuffer, binary string
900 privateKey: privateKey
901});
902// `signature` is a node.js Buffer or Uint8Array
903
904// sign a message passed as a buffer
905var signature = ED25519.sign({
906 // also accepts a forge ByteBuffer or Uint8Array
907 message: Buffer.from('test', 'utf8'),
908 privateKey: privateKey
909});
910
911// sign a message digest (shorter "message" == better performance)
912var md = forge.md.sha256.create();
913md.update('test', 'utf8');
914var signature = ED25519.sign({
915 md: md,
916 privateKey: privateKey
917});
918
919// verify a signature on a UTF-8 message
920var verified = ED25519.verify({
921 message: 'test',
922 encoding: 'utf8',
923 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
924 signature: signature,
925 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
926 publicKey: publicKey
927});
928// `verified` is true/false
929
930// sign a message passed as a buffer
931var verified = ED25519.verify({
932 // also accepts a forge ByteBuffer or Uint8Array
933 message: Buffer.from('test', 'utf8'),
934 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
935 signature: signature,
936 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
937 publicKey: publicKey
938});
939
940// verify a signature on a message digest
941var md = forge.md.sha256.create();
942md.update('test', 'utf8');
943var verified = ED25519.verify({
944 md: md,
945 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
946 signature: signature,
947 // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
948 publicKey: publicKey
949});
950```
951
952<a name="rsa" />
953
954### RSA
955
956__Examples__
957
958```js
959var rsa = forge.pki.rsa;
960
961// generate an RSA key pair synchronously
962// *NOT RECOMMENDED*: Can be significantly slower than async and may block
963// JavaScript execution. Will use native Node.js 10.12.0+ API if possible.
964var keypair = rsa.generateKeyPair({bits: 2048, e: 0x10001});
965
966// generate an RSA key pair asynchronously (uses web workers if available)
967// use workers: -1 to run a fast core estimator to optimize # of workers
968// *RECOMMENDED*: Can be significantly faster than sync. Will use native
969// Node.js 10.12.0+ or WebCrypto API if possible.
970rsa.generateKeyPair({bits: 2048, workers: 2}, function(err, keypair) {
971 // keypair.privateKey, keypair.publicKey
972});
973
974// generate an RSA key pair in steps that attempt to run for a specified period
975// of time on the main JS thread
976var state = rsa.createKeyPairGenerationState(2048, 0x10001);
977var step = function() {
978 // run for 100 ms
979 if(!rsa.stepKeyPairGenerationState(state, 100)) {
980 setTimeout(step, 1);
981 }
982 else {
983 // done, turn off progress indicator, use state.keys
984 }
985};
986// turn on progress indicator, schedule generation to run
987setTimeout(step);
988
989// sign data with a private key and output DigestInfo DER-encoded bytes
990// (defaults to RSASSA PKCS#1 v1.5)
991var md = forge.md.sha1.create();
992md.update('sign this', 'utf8');
993var signature = privateKey.sign(md);
994
995// verify data with a public key
996// (defaults to RSASSA PKCS#1 v1.5)
997var verified = publicKey.verify(md.digest().bytes(), signature);
998
999// sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based
1000// masking function MGF1, and a 20 byte salt
1001var md = forge.md.sha1.create();
1002md.update('sign this', 'utf8');
1003var pss = forge.pss.create({
1004 md: forge.md.sha1.create(),
1005 mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
1006 saltLength: 20
1007 // optionally pass 'prng' with a custom PRNG implementation
1008 // optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt
1009});
1010var signature = privateKey.sign(md, pss);
1011
1012// verify RSASSA-PSS signature
1013var pss = forge.pss.create({
1014 md: forge.md.sha1.create(),
1015 mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
1016 saltLength: 20
1017 // optionally pass 'prng' with a custom PRNG implementation
1018});
1019var md = forge.md.sha1.create();
1020md.update('sign this', 'utf8');
1021publicKey.verify(md.digest().getBytes(), signature, pss);
1022
1023// encrypt data with a public key (defaults to RSAES PKCS#1 v1.5)
1024var encrypted = publicKey.encrypt(bytes);
1025
1026// decrypt data with a private key (defaults to RSAES PKCS#1 v1.5)
1027var decrypted = privateKey.decrypt(encrypted);
1028
1029// encrypt data with a public key using RSAES PKCS#1 v1.5
1030var encrypted = publicKey.encrypt(bytes, 'RSAES-PKCS1-V1_5');
1031
1032// decrypt data with a private key using RSAES PKCS#1 v1.5
1033var decrypted = privateKey.decrypt(encrypted, 'RSAES-PKCS1-V1_5');
1034
1035// encrypt data with a public key using RSAES-OAEP
1036var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP');
1037
1038// decrypt data with a private key using RSAES-OAEP
1039var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP');
1040
1041// encrypt data with a public key using RSAES-OAEP/SHA-256
1042var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
1043 md: forge.md.sha256.create()
1044});
1045
1046// decrypt data with a private key using RSAES-OAEP/SHA-256
1047var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
1048 md: forge.md.sha256.create()
1049});
1050
1051// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
1052// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
1053var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
1054 md: forge.md.sha256.create(),
1055 mgf1: {
1056 md: forge.md.sha1.create()
1057 }
1058});
1059
1060// decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1
1061// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
1062var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
1063 md: forge.md.sha256.create(),
1064 mgf1: {
1065 md: forge.md.sha1.create()
1066 }
1067});
1068
1069```
1070
1071<a name="rsakem" />
1072
1073### RSA-KEM
1074
1075__Examples__
1076
1077```js
1078// generate an RSA key pair asynchronously (uses web workers if available)
1079// use workers: -1 to run a fast core estimator to optimize # of workers
1080forge.rsa.generateKeyPair({bits: 2048, workers: -1}, function(err, keypair) {
1081 // keypair.privateKey, keypair.publicKey
1082});
1083
1084// generate and encapsulate a 16-byte secret key
1085var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
1086var kem = forge.kem.rsa.create(kdf1);
1087var result = kem.encrypt(keypair.publicKey, 16);
1088// result has 'encapsulation' and 'key'
1089
1090// encrypt some bytes
1091var iv = forge.random.getBytesSync(12);
1092var someBytes = 'hello world!';
1093var cipher = forge.cipher.createCipher('AES-GCM', result.key);
1094cipher.start({iv: iv});
1095cipher.update(forge.util.createBuffer(someBytes));
1096cipher.finish();
1097var encrypted = cipher.output.getBytes();
1098var tag = cipher.mode.tag.getBytes();
1099
1100// send 'encrypted', 'iv', 'tag', and result.encapsulation to recipient
1101
1102// decrypt encapsulated 16-byte secret key
1103var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
1104var kem = forge.kem.rsa.create(kdf1);
1105var key = kem.decrypt(keypair.privateKey, result.encapsulation, 16);
1106
1107// decrypt some bytes
1108var decipher = forge.cipher.createDecipher('AES-GCM', key);
1109decipher.start({iv: iv, tag: tag});
1110decipher.update(forge.util.createBuffer(encrypted));
1111var pass = decipher.finish();
1112// pass is false if there was a failure (eg: authentication tag didn't match)
1113if(pass) {
1114 // outputs 'hello world!'
1115 console.log(decipher.output.getBytes());
1116}
1117
1118```
1119
1120<a name="x509" />
1121
1122### X.509
1123
1124__Examples__
1125
1126```js
1127var pki = forge.pki;
1128
1129// convert a PEM-formatted public key to a Forge public key
1130var publicKey = pki.publicKeyFromPem(pem);
1131
1132// convert a Forge public key to PEM-format
1133var pem = pki.publicKeyToPem(publicKey);
1134
1135// convert an ASN.1 SubjectPublicKeyInfo to a Forge public key
1136var publicKey = pki.publicKeyFromAsn1(subjectPublicKeyInfo);
1137
1138// convert a Forge public key to an ASN.1 SubjectPublicKeyInfo
1139var subjectPublicKeyInfo = pki.publicKeyToAsn1(publicKey);
1140
1141// gets a SHA-1 RSAPublicKey fingerprint a byte buffer
1142pki.getPublicKeyFingerprint(key);
1143
1144// gets a SHA-1 SubjectPublicKeyInfo fingerprint a byte buffer
1145pki.getPublicKeyFingerprint(key, {type: 'SubjectPublicKeyInfo'});
1146
1147// gets a hex-encoded, colon-delimited SHA-1 RSAPublicKey public key fingerprint
1148pki.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
1149
1150// gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprint
1151pki.getPublicKeyFingerprint(key, {
1152 type: 'SubjectPublicKeyInfo',
1153 encoding: 'hex',
1154 delimiter: ':'
1155});
1156
1157// gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprint
1158pki.getPublicKeyFingerprint(key, {
1159 md: forge.md.md5.create(),
1160 encoding: 'hex',
1161 delimiter: ':'
1162});
1163
1164// creates a CA store
1165var caStore = pki.createCaStore([/* PEM-encoded cert */, ...]);
1166
1167// add a certificate to the CA store
1168caStore.addCertificate(certObjectOrPemString);
1169
1170// gets the issuer (its certificate) for the given certificate
1171var issuerCert = caStore.getIssuer(subjectCert);
1172
1173// verifies a certificate chain against a CA store
1174pki.verifyCertificateChain(caStore, chain, customVerifyCallback);
1175
1176// signs a certificate using the given private key
1177cert.sign(privateKey);
1178
1179// signs a certificate using SHA-256 instead of SHA-1
1180cert.sign(privateKey, forge.md.sha256.create());
1181
1182// verifies an issued certificate using the certificates public key
1183var verified = issuer.verify(issued);
1184
1185// generate a keypair and create an X.509v3 certificate
1186var keys = pki.rsa.generateKeyPair(2048);
1187var cert = pki.createCertificate();
1188cert.publicKey = keys.publicKey;
1189// alternatively set public key from a csr
1190//cert.publicKey = csr.publicKey;
1191// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
1192// Conforming CAs should ensure serialNumber is:
1193// - no more than 20 octets
1194// - non-negative (prefix a '00' if your value starts with a '1' bit)
1195cert.serialNumber = '01';
1196cert.validity.notBefore = new Date();
1197cert.validity.notAfter = new Date();
1198cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
1199var attrs = [{
1200 name: 'commonName',
1201 value: 'example.org'
1202}, {
1203 name: 'countryName',
1204 value: 'US'
1205}, {
1206 shortName: 'ST',
1207 value: 'Virginia'
1208}, {
1209 name: 'localityName',
1210 value: 'Blacksburg'
1211}, {
1212 name: 'organizationName',
1213 value: 'Test'
1214}, {
1215 shortName: 'OU',
1216 value: 'Test'
1217}];
1218cert.setSubject(attrs);
1219// alternatively set subject from a csr
1220//cert.setSubject(csr.subject.attributes);
1221cert.setIssuer(attrs);
1222cert.setExtensions([{
1223 name: 'basicConstraints',
1224 cA: true
1225}, {
1226 name: 'keyUsage',
1227 keyCertSign: true,
1228 digitalSignature: true,
1229 nonRepudiation: true,
1230 keyEncipherment: true,
1231 dataEncipherment: true
1232}, {
1233 name: 'extKeyUsage',
1234 serverAuth: true,
1235 clientAuth: true,
1236 codeSigning: true,
1237 emailProtection: true,
1238 timeStamping: true
1239}, {
1240 name: 'nsCertType',
1241 client: true,
1242 server: true,
1243 email: true,
1244 objsign: true,
1245 sslCA: true,
1246 emailCA: true,
1247 objCA: true
1248}, {
1249 name: 'subjectAltName',
1250 altNames: [{
1251 type: 6, // URI
1252 value: 'http://example.org/webid#me'
1253 }, {
1254 type: 7, // IP
1255 ip: '127.0.0.1'
1256 }]
1257}, {
1258 name: 'subjectKeyIdentifier'
1259}]);
1260/* alternatively set extensions from a csr
1261var extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;
1262// optionally add more extensions
1263extensions.push.apply(extensions, [{
1264 name: 'basicConstraints',
1265 cA: true
1266}, {
1267 name: 'keyUsage',
1268 keyCertSign: true,
1269 digitalSignature: true,
1270 nonRepudiation: true,
1271 keyEncipherment: true,
1272 dataEncipherment: true
1273}]);
1274cert.setExtensions(extensions);
1275*/
1276// self-sign certificate
1277cert.sign(keys.privateKey);
1278
1279// convert a Forge certificate to PEM
1280var pem = pki.certificateToPem(cert);
1281
1282// convert a Forge certificate from PEM
1283var cert = pki.certificateFromPem(pem);
1284
1285// convert an ASN.1 X.509x3 object to a Forge certificate
1286var cert = pki.certificateFromAsn1(obj);
1287
1288// convert a Forge certificate to an ASN.1 X.509v3 object
1289var asn1Cert = pki.certificateToAsn1(cert);
1290```
1291
1292<a name="pkcs5" />
1293
1294### PKCS#5
1295
1296Provides the password-based key-derivation function from [PKCS#5][].
1297
1298__Examples__
1299
1300```js
1301// generate a password-based 16-byte key
1302// note an optional message digest can be passed as the final parameter
1303var salt = forge.random.getBytesSync(128);
1304var derivedKey = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
1305
1306// generate key asynchronously
1307// note an optional message digest can be passed before the callback
1308forge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey) {
1309 // do something w/derivedKey
1310});
1311```
1312
1313<a name="pkcs7" />
1314
1315### PKCS#7
1316
1317Provides cryptographically protected messages from [PKCS#7][].
1318
1319__Examples__
1320
1321```js
1322// convert a message from PEM
1323var p7 = forge.pkcs7.messageFromPem(pem);
1324// look at p7.recipients
1325
1326// find a recipient by the issuer of a certificate
1327var recipient = p7.findRecipient(cert);
1328
1329// decrypt
1330p7.decrypt(p7.recipients[0], privateKey);
1331
1332// create a p7 enveloped message
1333var p7 = forge.pkcs7.createEnvelopedData();
1334
1335// add a recipient
1336var cert = forge.pki.certificateFromPem(certPem);
1337p7.addRecipient(cert);
1338
1339// set content
1340p7.content = forge.util.createBuffer('Hello');
1341
1342// encrypt
1343p7.encrypt();
1344
1345// convert message to PEM
1346var pem = forge.pkcs7.messageToPem(p7);
1347
1348// create a degenerate PKCS#7 certificate container
1349// (CRLs not currently supported, only certificates)
1350var p7 = forge.pkcs7.createSignedData();
1351p7.addCertificate(certOrCertPem1);
1352p7.addCertificate(certOrCertPem2);
1353var pem = forge.pkcs7.messageToPem(p7);
1354
1355// create PKCS#7 signed data with authenticatedAttributes
1356// attributes include: PKCS#9 content-type, message-digest, and signing-time
1357var p7 = forge.pkcs7.createSignedData();
1358p7.content = forge.util.createBuffer('Some content to be signed.', 'utf8');
1359p7.addCertificate(certOrCertPem);
1360p7.addSigner({
1361 key: privateKeyAssociatedWithCert,
1362 certificate: certOrCertPem,
1363 digestAlgorithm: forge.pki.oids.sha256,
1364 authenticatedAttributes: [{
1365 type: forge.pki.oids.contentType,
1366 value: forge.pki.oids.data
1367 }, {
1368 type: forge.pki.oids.messageDigest
1369 // value will be auto-populated at signing time
1370 }, {
1371 type: forge.pki.oids.signingTime,
1372 // value can also be auto-populated at signing time
1373 value: new Date()
1374 }]
1375});
1376p7.sign();
1377var pem = forge.pkcs7.messageToPem(p7);
1378
1379// PKCS#7 Sign in detached mode.
1380// Includes the signature and certificate without the signed data.
1381p7.sign({detached: true});
1382
1383```
1384
1385<a name="pkcs8" />
1386
1387### PKCS#8
1388
1389__Examples__
1390
1391```js
1392var pki = forge.pki;
1393
1394// convert a PEM-formatted private key to a Forge private key
1395var privateKey = pki.privateKeyFromPem(pem);
1396
1397// convert a Forge private key to PEM-format
1398var pem = pki.privateKeyToPem(privateKey);
1399
1400// convert an ASN.1 PrivateKeyInfo or RSAPrivateKey to a Forge private key
1401var privateKey = pki.privateKeyFromAsn1(rsaPrivateKey);
1402
1403// convert a Forge private key to an ASN.1 RSAPrivateKey
1404var rsaPrivateKey = pki.privateKeyToAsn1(privateKey);
1405
1406// wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfo
1407var privateKeyInfo = pki.wrapRsaPrivateKey(rsaPrivateKey);
1408
1409// convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM
1410var pem = pki.privateKeyInfoToPem(privateKeyInfo);
1411
1412// encrypts a PrivateKeyInfo using a custom password and
1413// outputs an EncryptedPrivateKeyInfo
1414var encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo(
1415 privateKeyInfo, 'myCustomPasswordHere', {
1416 algorithm: 'aes256', // 'aes128', 'aes192', 'aes256', '3des'
1417 });
1418
1419// decrypts an ASN.1 EncryptedPrivateKeyInfo that was encrypted
1420// with a custom password
1421var privateKeyInfo = pki.decryptPrivateKeyInfo(
1422 encryptedPrivateKeyInfo, 'myCustomPasswordHere');
1423
1424// converts an EncryptedPrivateKeyInfo to PEM
1425var pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);
1426
1427// converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format
1428var encryptedPrivateKeyInfo = pki.encryptedPrivateKeyFromPem(pem);
1429
1430// wraps and encrypts a Forge private key and outputs it in PEM format
1431var pem = pki.encryptRsaPrivateKey(privateKey, 'password');
1432
1433// encrypts a Forge private key and outputs it in PEM format using OpenSSL's
1434// proprietary legacy format + encapsulated PEM headers (DEK-Info)
1435var pem = pki.encryptRsaPrivateKey(privateKey, 'password', {legacy: true});
1436
1437// decrypts a PEM-formatted, encrypted private key
1438var privateKey = pki.decryptRsaPrivateKey(pem, 'password');
1439
1440// sets an RSA public key from a private key
1441var publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e);
1442```
1443
1444<a name="pkcs10" />
1445
1446### PKCS#10
1447
1448Provides certification requests or certificate signing requests (CSR) from
1449[PKCS#10][].
1450
1451__Examples__
1452
1453```js
1454// generate a key pair
1455var keys = forge.pki.rsa.generateKeyPair(1024);
1456
1457// create a certification request (CSR)
1458var csr = forge.pki.createCertificationRequest();
1459csr.publicKey = keys.publicKey;
1460csr.setSubject([{
1461 name: 'commonName',
1462 value: 'example.org'
1463}, {
1464 name: 'countryName',
1465 value: 'US'
1466}, {
1467 shortName: 'ST',
1468 value: 'Virginia'
1469}, {
1470 name: 'localityName',
1471 value: 'Blacksburg'
1472}, {
1473 name: 'organizationName',
1474 value: 'Test'
1475}, {
1476 shortName: 'OU',
1477 value: 'Test'
1478}]);
1479// set (optional) attributes
1480csr.setAttributes([{
1481 name: 'challengePassword',
1482 value: 'password'
1483}, {
1484 name: 'unstructuredName',
1485 value: 'My Company, Inc.'
1486}, {
1487 name: 'extensionRequest',
1488 extensions: [{
1489 name: 'subjectAltName',
1490 altNames: [{
1491 // 2 is DNS type
1492 type: 2,
1493 value: 'test.domain.com'
1494 }, {
1495 type: 2,
1496 value: 'other.domain.com',
1497 }, {
1498 type: 2,
1499 value: 'www.domain.net'
1500 }]
1501 }]
1502}]);
1503
1504// sign certification request
1505csr.sign(keys.privateKey);
1506
1507// verify certification request
1508var verified = csr.verify();
1509
1510// convert certification request to PEM-format
1511var pem = forge.pki.certificationRequestToPem(csr);
1512
1513// convert a Forge certification request from PEM-format
1514var csr = forge.pki.certificationRequestFromPem(pem);
1515
1516// get an attribute
1517csr.getAttribute({name: 'challengePassword'});
1518
1519// get extensions array
1520csr.getAttribute({name: 'extensionRequest'}).extensions;
1521
1522```
1523
1524<a name="pkcs12" />
1525
1526### PKCS#12
1527
1528Provides the cryptographic archive file format from [PKCS#12][].
1529
1530**Note for Chrome/Firefox/iOS/similar users**: If you have trouble importing
1531a PKCS#12 container, try using the TripleDES algorithm. It can be passed
1532to `forge.pkcs12.toPkcs12Asn1` using the `{algorithm: '3des'}` option.
1533
1534__Examples__
1535
1536```js
1537// decode p12 from base64
1538var p12Der = forge.util.decode64(p12b64);
1539// get p12 as ASN.1 object
1540var p12Asn1 = forge.asn1.fromDer(p12Der);
1541// decrypt p12 using the password 'password'
1542var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');
1543// decrypt p12 using non-strict parsing mode (resolves some ASN.1 parse errors)
1544var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, 'password');
1545// decrypt p12 using literally no password (eg: Mac OS X/apple push)
1546var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1);
1547// decrypt p12 using an "empty" password (eg: OpenSSL with no password input)
1548var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, '');
1549// p12.safeContents is an array of safe contents, each of
1550// which contains an array of safeBags
1551
1552// get bags by friendlyName
1553var bags = p12.getBags({friendlyName: 'test'});
1554// bags are key'd by attribute type (here "friendlyName")
1555// and the key values are an array of matching objects
1556var cert = bags.friendlyName[0];
1557
1558// get bags by localKeyId
1559var bags = p12.getBags({localKeyId: buffer});
1560// bags are key'd by attribute type (here "localKeyId")
1561// and the key values are an array of matching objects
1562var cert = bags.localKeyId[0];
1563
1564// get bags by localKeyId (input in hex)
1565var bags = p12.getBags({localKeyIdHex: '7b59377ff142d0be4565e9ac3d396c01401cd879'});
1566// bags are key'd by attribute type (here "localKeyId", *not* "localKeyIdHex")
1567// and the key values are an array of matching objects
1568var cert = bags.localKeyId[0];
1569
1570// get bags by type
1571var bags = p12.getBags({bagType: forge.pki.oids.certBag});
1572// bags are key'd by bagType and each bagType key's value
1573// is an array of matches (in this case, certificate objects)
1574var cert = bags[forge.pki.oids.certBag][0];
1575
1576// get bags by friendlyName and filter on bag type
1577var bags = p12.getBags({
1578 friendlyName: 'test',
1579 bagType: forge.pki.oids.certBag
1580});
1581
1582// get key bags
1583var bags = p12.getBags({bagType: forge.pki.oids.keyBag});
1584// get key
1585var bag = bags[forge.pki.oids.keyBag][0];
1586var key = bag.key;
1587// if the key is in a format unrecognized by forge then
1588// bag.key will be `null`, use bag.asn1 to get the ASN.1
1589// representation of the key
1590if(bag.key === null) {
1591 var keyAsn1 = bag.asn1;
1592 // can now convert back to DER/PEM/etc for export
1593}
1594
1595// generate a p12 using AES (default)
1596var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
1597 privateKey, certificateChain, 'password');
1598
1599// generate a p12 that can be imported by Chrome/Firefox/iOS
1600// (requires the use of Triple DES instead of AES)
1601var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
1602 privateKey, certificateChain, 'password',
1603 {algorithm: '3des'});
1604
1605// base64-encode p12
1606var p12Der = forge.asn1.toDer(p12Asn1).getBytes();
1607var p12b64 = forge.util.encode64(p12Der);
1608
1609// create download link for p12
1610var a = document.createElement('a');
1611a.download = 'example.p12';
1612a.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12b64);
1613a.appendChild(document.createTextNode('Download'));
1614```
1615
1616<a name="asn" />
1617
1618### ASN.1
1619
1620Provides [ASN.1][] DER encoding and decoding.
1621
1622__Examples__
1623
1624```js
1625var asn1 = forge.asn1;
1626
1627// create a SubjectPublicKeyInfo
1628var subjectPublicKeyInfo =
1629 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1630 // AlgorithmIdentifier
1631 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1632 // algorithm
1633 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
1634 asn1.oidToDer(pki.oids['rsaEncryption']).getBytes()),
1635 // parameters (null)
1636 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')
1637 ]),
1638 // subjectPublicKey
1639 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, [
1640 // RSAPublicKey
1641 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1642 // modulus (n)
1643 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
1644 _bnToBytes(key.n)),
1645 // publicExponent (e)
1646 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
1647 _bnToBytes(key.e))
1648 ])
1649 ])
1650 ]);
1651
1652// serialize an ASN.1 object to DER format
1653var derBuffer = asn1.toDer(subjectPublicKeyInfo);
1654
1655// deserialize to an ASN.1 object from a byte buffer filled with DER data
1656var object = asn1.fromDer(derBuffer);
1657
1658// convert an OID dot-separated string to a byte buffer
1659var derOidBuffer = asn1.oidToDer('1.2.840.113549.1.1.5');
1660
1661// convert a byte buffer with a DER-encoded OID to a dot-separated string
1662console.log(asn1.derToOid(derOidBuffer));
1663// output: 1.2.840.113549.1.1.5
1664
1665// validates that an ASN.1 object matches a particular ASN.1 structure and
1666// captures data of interest from that structure for easy access
1667var publicKeyValidator = {
1668 name: 'SubjectPublicKeyInfo',
1669 tagClass: asn1.Class.UNIVERSAL,
1670 type: asn1.Type.SEQUENCE,
1671 constructed: true,
1672 captureAsn1: 'subjectPublicKeyInfo',
1673 value: [{
1674 name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',
1675 tagClass: asn1.Class.UNIVERSAL,
1676 type: asn1.Type.SEQUENCE,
1677 constructed: true,
1678 value: [{
1679 name: 'AlgorithmIdentifier.algorithm',
1680 tagClass: asn1.Class.UNIVERSAL,
1681 type: asn1.Type.OID,
1682 constructed: false,
1683 capture: 'publicKeyOid'
1684 }]
1685 }, {
1686 // subjectPublicKey
1687 name: 'SubjectPublicKeyInfo.subjectPublicKey',
1688 tagClass: asn1.Class.UNIVERSAL,
1689 type: asn1.Type.BITSTRING,
1690 constructed: false,
1691 value: [{
1692 // RSAPublicKey
1693 name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',
1694 tagClass: asn1.Class.UNIVERSAL,
1695 type: asn1.Type.SEQUENCE,
1696 constructed: true,
1697 optional: true,
1698 captureAsn1: 'rsaPublicKey'
1699 }]
1700 }]
1701};
1702
1703var capture = {};
1704var errors = [];
1705if(!asn1.validate(
1706 publicKeyValidator, subjectPublicKeyInfo, validator, capture, errors)) {
1707 throw 'ASN.1 object is not a SubjectPublicKeyInfo.';
1708}
1709// capture.subjectPublicKeyInfo contains the full ASN.1 object
1710// capture.rsaPublicKey contains the full ASN.1 object for the RSA public key
1711// capture.publicKeyOid only contains the value for the OID
1712var oid = asn1.derToOid(capture.publicKeyOid);
1713if(oid !== pki.oids['rsaEncryption']) {
1714 throw 'Unsupported OID.';
1715}
1716
1717// pretty print an ASN.1 object to a string for debugging purposes
1718asn1.prettyPrint(object);
1719```
1720
1721Message Digests
1722----------------
1723
1724<a name="sha1" />
1725
1726### SHA1
1727
1728Provides [SHA-1][] message digests.
1729
1730__Examples__
1731
1732```js
1733var md = forge.md.sha1.create();
1734md.update('The quick brown fox jumps over the lazy dog');
1735console.log(md.digest().toHex());
1736// output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
1737```
1738
1739<a name="sha256" />
1740
1741### SHA256
1742
1743Provides [SHA-256][] message digests.
1744
1745__Examples__
1746
1747```js
1748var md = forge.md.sha256.create();
1749md.update('The quick brown fox jumps over the lazy dog');
1750console.log(md.digest().toHex());
1751// output: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
1752```
1753
1754<a name="sha384" />
1755
1756### SHA384
1757
1758Provides [SHA-384][] message digests.
1759
1760__Examples__
1761
1762```js
1763var md = forge.md.sha384.create();
1764md.update('The quick brown fox jumps over the lazy dog');
1765console.log(md.digest().toHex());
1766// output: ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1
1767```
1768
1769<a name="sha512" />
1770
1771### SHA512
1772
1773Provides [SHA-512][] message digests.
1774
1775__Examples__
1776
1777```js
1778// SHA-512
1779var md = forge.md.sha512.create();
1780md.update('The quick brown fox jumps over the lazy dog');
1781console.log(md.digest().toHex());
1782// output: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6
1783
1784// SHA-512/224
1785var md = forge.md.sha512.sha224.create();
1786md.update('The quick brown fox jumps over the lazy dog');
1787console.log(md.digest().toHex());
1788// output: 944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37
1789
1790// SHA-512/256
1791var md = forge.md.sha512.sha256.create();
1792md.update('The quick brown fox jumps over the lazy dog');
1793console.log(md.digest().toHex());
1794// output: dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d
1795```
1796
1797<a name="md5" />
1798
1799### MD5
1800
1801Provides [MD5][] message digests.
1802
1803__Examples__
1804
1805```js
1806var md = forge.md.md5.create();
1807md.update('The quick brown fox jumps over the lazy dog');
1808console.log(md.digest().toHex());
1809// output: 9e107d9d372bb6826bd81d3542a419d6
1810```
1811
1812<a name="hmac" />
1813
1814### HMAC
1815
1816Provides [HMAC][] w/any supported message digest algorithm.
1817
1818__Examples__
1819
1820```js
1821var hmac = forge.hmac.create();
1822hmac.start('sha1', 'Jefe');
1823hmac.update('what do ya want for nothing?');
1824console.log(hmac.digest().toHex());
1825// output: effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
1826```
1827
1828Utilities
1829---------
1830
1831<a name="prime" />
1832
1833### Prime
1834
1835Provides an API for generating large, random, probable primes.
1836
1837__Examples__
1838
1839```js
1840// generate a random prime on the main JS thread
1841var bits = 1024;
1842forge.prime.generateProbablePrime(bits, function(err, num) {
1843 console.log('random prime', num.toString(16));
1844});
1845
1846// generate a random prime using Web Workers (if available, otherwise
1847// falls back to the main thread)
1848var bits = 1024;
1849var options = {
1850 algorithm: {
1851 name: 'PRIMEINC',
1852 workers: -1 // auto-optimize # of workers
1853 }
1854};
1855forge.prime.generateProbablePrime(bits, options, function(err, num) {
1856 console.log('random prime', num.toString(16));
1857});
1858```
1859
1860<a name="prng" />
1861
1862### PRNG
1863
1864Provides a [Fortuna][]-based cryptographically-secure pseudo-random number
1865generator, to be used with a cryptographic function backend, e.g. [AES][]. An
1866implementation using [AES][] as a backend is provided. An API for collecting
1867entropy is given, though if window.crypto.getRandomValues is available, it will
1868be used automatically.
1869
1870__Examples__
1871
1872```js
1873// get some random bytes synchronously
1874var bytes = forge.random.getBytesSync(32);
1875console.log(forge.util.bytesToHex(bytes));
1876
1877// get some random bytes asynchronously
1878forge.random.getBytes(32, function(err, bytes) {
1879 console.log(forge.util.bytesToHex(bytes));
1880});
1881
1882// collect some entropy if you'd like
1883forge.random.collect(someRandomBytes);
1884jQuery().mousemove(function(e) {
1885 forge.random.collectInt(e.clientX, 16);
1886 forge.random.collectInt(e.clientY, 16);
1887});
1888
1889// specify a seed file for use with the synchronous API if you'd like
1890forge.random.seedFileSync = function(needed) {
1891 // get 'needed' number of random bytes from somewhere
1892 return fetchedRandomBytes;
1893};
1894
1895// specify a seed file for use with the asynchronous API if you'd like
1896forge.random.seedFile = function(needed, callback) {
1897 // get the 'needed' number of random bytes from somewhere
1898 callback(null, fetchedRandomBytes);
1899});
1900
1901// register the main thread to send entropy or a Web Worker to receive
1902// entropy on demand from the main thread
1903forge.random.registerWorker(self);
1904
1905// generate a new instance of a PRNG with no collected entropy
1906var myPrng = forge.random.createInstance();
1907```
1908
1909<a name="task" />
1910
1911### Tasks
1912
1913Provides queuing and synchronizing tasks in a web application.
1914
1915__Examples__
1916
1917```js
1918// TODO
1919```
1920
1921<a name="util" />
1922
1923### Utilities
1924
1925Provides utility functions, including byte buffer support, base64,
1926bytes to/from hex, zlib inflate/deflate, etc.
1927
1928__Examples__
1929
1930```js
1931// encode/decode base64
1932var encoded = forge.util.encode64(str);
1933var str = forge.util.decode64(encoded);
1934
1935// encode/decode UTF-8
1936var encoded = forge.util.encodeUtf8(str);
1937var str = forge.util.decodeUtf8(encoded);
1938
1939// bytes to/from hex
1940var bytes = forge.util.hexToBytes(hex);
1941var hex = forge.util.bytesToHex(bytes);
1942
1943// create an empty byte buffer
1944var buffer = forge.util.createBuffer();
1945// create a byte buffer from raw binary bytes
1946var buffer = forge.util.createBuffer(input, 'raw');
1947// create a byte buffer from utf8 bytes
1948var buffer = forge.util.createBuffer(input, 'utf8');
1949
1950// get the length of the buffer in bytes
1951buffer.length();
1952// put bytes into the buffer
1953buffer.putBytes(bytes);
1954// put a 32-bit integer into the buffer
1955buffer.putInt32(10);
1956// buffer to hex
1957buffer.toHex();
1958// get a copy of the bytes in the buffer
1959bytes.bytes(/* count */);
1960// empty this buffer and get its contents
1961bytes.getBytes(/* count */);
1962
1963// convert a forge buffer into a Node.js Buffer
1964// make sure you specify the encoding as 'binary'
1965var forgeBuffer = forge.util.createBuffer();
1966var nodeBuffer = Buffer.from(forgeBuffer.getBytes(), 'binary');
1967
1968// convert a Node.js Buffer into a forge buffer
1969// make sure you specify the encoding as 'binary'
1970var nodeBuffer = Buffer.from('CAFE', 'hex');
1971var forgeBuffer = forge.util.createBuffer(nodeBuffer.toString('binary'));
1972
1973// parse a URL
1974var parsed = forge.util.parseUrl('http://example.com/foo?bar=baz');
1975// parsed.scheme, parsed.host, parsed.port, parsed.path, parsed.fullHost
1976```
1977
1978<a name="log" />
1979
1980### Logging
1981
1982Provides logging to a javascript console using various categories and
1983levels of verbosity.
1984
1985__Examples__
1986
1987```js
1988// TODO
1989```
1990
1991<a name="debug" />
1992
1993### Debugging
1994
1995Provides storage of debugging information normally inaccessible in
1996closures for viewing/investigation.
1997
1998__Examples__
1999
2000```js
2001// TODO
2002```
2003
2004<a name="flash" />
2005
2006### Flash Networking Support
2007
2008The [flash README](./flash/README.md) provides details on rebuilding the
2009optional Flash component used for networking. It also provides details on
2010Policy Server support.
2011
2012Security Considerations
2013-----------------------
2014
2015When using this code please keep the following in mind:
2016
2017- Cryptography is hard. Please review and test this code before depending on it
2018 for critical functionality.
2019- The nature of JavaScript is that execution of this code depends on trusting a
2020 very large set of JavaScript tools and systems. Consider runtime variations,
2021 runtime characteristics, runtime optimization, code optimization, code
2022 minimization, code obfuscation, bundling tools, possible bugs, the Forge code
2023 itself, and so on.
2024- If using pre-built bundles from [Bower][] or similar be aware someone else
2025 ran the tools to create those files.
2026- Use a secure transport channel such as [TLS][] to load scripts and consider
2027 using additional security mechanisms such as [Subresource Integrity][] script
2028 attributes.
2029- Use "native" functionality where possible. This can be critical when dealing
2030 with performance and random number generation. Note that the JavaScript
2031 random number algorithms should perform well if given suitable entropy.
2032- Understand possible attacks against cryptographic systems. For instance side
2033 channel and timing attacks may be possible due to the difficulty in
2034 implementing constant time algorithms in pure JavaScript.
2035- Certain features in this library are less susceptible to attacks depending on
2036 usage. This primarily includes features that deal with data format
2037 manipulation or those that are not involved in communication.
2038
2039Library Background
2040------------------
2041
2042* https://digitalbazaar.com/2010/07/20/javascript-tls-1/
2043* https://digitalbazaar.com/2010/07/20/javascript-tls-2/
2044
2045Contact
2046-------
2047
2048* Code: https://github.com/digitalbazaar/forge
2049* Bugs: https://github.com/digitalbazaar/forge/issues
2050* Email: support@digitalbazaar.com
2051* IRC: [#forgejs][] on [freenode][]
2052
2053Donations
2054---------
2055
2056Financial support is welcome and helps contribute to futher development:
2057
2058* For [PayPal][] please send to paypal@digitalbazaar.com.
2059* Something else? Please contact support@digitalbazaar.com.
2060
2061[#forgejs]: https://webchat.freenode.net/?channels=#forgejs
2062[0.6.x]: https://github.com/digitalbazaar/forge/tree/0.6.x
2063[3DES]: https://en.wikipedia.org/wiki/Triple_DES
2064[AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
2065[ASN.1]: https://en.wikipedia.org/wiki/ASN.1
2066[Bower]: https://bower.io/
2067[Browserify]: http://browserify.org/
2068[CBC]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2069[CFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2070[CTR]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2071[CommonJS]: https://en.wikipedia.org/wiki/CommonJS
2072[DES]: https://en.wikipedia.org/wiki/Data_Encryption_Standard
2073[ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2074[Fortuna]: https://en.wikipedia.org/wiki/Fortuna_(PRNG)
2075[GCM]: https://en.wikipedia.org/wiki/GCM_mode
2076[HMAC]: https://en.wikipedia.org/wiki/HMAC
2077[JavaScript]: https://en.wikipedia.org/wiki/JavaScript
2078[Karma]: https://karma-runner.github.io/
2079[MD5]: https://en.wikipedia.org/wiki/MD5
2080[Node.js]: https://nodejs.org/
2081[OFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2082[PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request
2083[PKCS#12]: https://en.wikipedia.org/wiki/PKCS_%E2%99%AF12
2084[PKCS#5]: https://en.wikipedia.org/wiki/PKCS
2085[PKCS#7]: https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax
2086[PayPal]: https://www.paypal.com/
2087[RC2]: https://en.wikipedia.org/wiki/RC2
2088[SHA-1]: https://en.wikipedia.org/wiki/SHA-1
2089[SHA-256]: https://en.wikipedia.org/wiki/SHA-256
2090[SHA-384]: https://en.wikipedia.org/wiki/SHA-384
2091[SHA-512]: https://en.wikipedia.org/wiki/SHA-512
2092[Subresource Integrity]: https://www.w3.org/TR/SRI/
2093[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
2094[UMD]: https://github.com/umdjs/umd
2095[X.509]: https://en.wikipedia.org/wiki/X.509
2096[freenode]: https://freenode.net/
2097[unpkg]: https://unpkg.com/
2098[webpack]: https://webpack.github.io/
2099[TweetNaCl.js]: https://github.com/dchest/tweetnacl-js