source: frontend/node_modules/node-forge/README.md

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

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