UNPKG

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