Projekt

Obecné

Profil

Stáhnout (58.7 KB) Statistiky
| Větev: | Revize:
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

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

    
10
Introduction
11
------------
12

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

    
17
Performance
18
------------
19

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

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

    
26
Documentation
27
-------------
28

    
29
* [Introduction](#introduction)
30
* [Performance](#performance)
31
* [Installation](#installation)
32
* [Testing](#testing)
33
* [Contributing](#contributing)
34

    
35
### API
36

    
37
* [Options](#options)
38

    
39
### Transports
40

    
41
* [TLS](#tls)
42
* [HTTP](#http)
43
* [SSH](#ssh)
44
* [XHR](#xhr)
45
* [Sockets](#socket)
46

    
47
### Ciphers
48

    
49
* [CIPHER](#cipher)
50
* [AES](#aes)
51
* [DES](#des)
52
* [RC2](#rc2)
53

    
54
### PKI
55

    
56
* [ED25519](#ed25519)
57
* [RSA](#rsa)
58
* [RSA-KEM](#rsakem)
59
* [X.509](#x509)
60
* [PKCS#5](#pkcs5)
61
* [PKCS#7](#pkcs7)
62
* [PKCS#8](#pkcs8)
63
* [PKCS#10](#pkcs10)
64
* [PKCS#12](#pkcs12)
65
* [ASN.1](#asn)
66

    
67
### Message Digests
68

    
69
* [SHA1](#sha1)
70
* [SHA256](#sha256)
71
* [SHA384](#sha384)
72
* [SHA512](#sha512)
73
* [MD5](#md5)
74
* [HMAC](#hmac)
75

    
76
### Utilities
77

    
78
* [Prime](#prime)
79
* [PRNG](#prng)
80
* [Tasks](#task)
81
* [Utilities](#util)
82
* [Logging](#log)
83
* [Debugging](#debug)
84
* [Flash Networking Support](#flash)
85

    
86
### Other
87

    
88
* [Security Considerations](#security-considerations)
89
* [Library Background](#library-background)
90
* [Contact](#contact)
91
* [Donations](#donations)
92

    
93
---------------------------------------
94

    
95
Installation
96
------------
97

    
98
**Note**: Please see the [Security Considerations](#security-considerations)
99
section before using packaging systems and pre-built files.
100

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

    
105
### Node.js
106

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

    
109
https://npmjs.org/package/node-forge
110

    
111
Installation:
112

    
113
    npm install node-forge
114

    
115
You can then use forge as a regular module:
116

    
117
```js
118
var forge = require('node-forge');
119
```
120

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

    
124
### Bundle / Bower
125

    
126
Each release is published in a separate repository as pre-built and minimized
127
basic forge bundles using the [UMD][] format.
128

    
129
https://github.com/digitalbazaar/forge-dist
130

    
131
This bundle can be used in many environments. In particular it can be installed
132
with [Bower][]:
133

    
134
    bower install forge
135

    
136
### jsDelivr CDN
137

    
138
To use it via [jsDelivr](https://www.jsdelivr.com/package/npm/node-forge) include this in your html:
139

    
140
```html
141
<script src="https://cdn.jsdelivr.net/npm/node-forge@0.7.0/dist/forge.min.js"></script>
142
```
143

    
144
### unpkg CDN
145

    
146
To use it via [unpkg](https://unpkg.com/#/) include this in your html:
147

    
148
```html
149
<script src="https://unpkg.com/node-forge@0.7.0/dist/forge.min.js"></script>
150
```
151

    
152
### Development Requirements
153

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

    
156
* Building a browser bundle:
157
  * Node.js
158
  * npm
159
* Testing
160
  * Node.js
161
  * npm
162
  * Chrome, Firefox, Safari (optional)
163

    
164
Some special networking features can optionally use a Flash component.  See the
165
[Flash README](./flash/README.md) for details.
166

    
167
### Building for a web browser
168

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

    
171
    npm install
172
    npm run build
173

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

    
177
    dist/forge.js
178
    dist/forge.min.js
179

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

    
182
    dist/forge.all.js
183
    dist/forge.all.min.js
184

    
185
Include the file via:
186

    
187
```html
188
<script src="YOUR_SCRIPT_PATH/forge.js"></script>
189
```
190
or
191
```html
192
<script src="YOUR_SCRIPT_PATH/forge.min.js"></script>
193
```
194

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

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

    
201
### Building a custom browser bundle
202

    
203
The build process uses [webpack][] and the [config](./webpack.config.js) file
204
can be modified to generate a file or files that only contain the parts of
205
forge you need.
206

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

    
209
Testing
210
-------
211

    
212
### Prepare to run tests
213

    
214
    npm install
215

    
216
### Running automated tests with Node.js
217

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

    
220
    npm test
221

    
222
### Running automated tests with Headless Chrome
223

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

    
227
    npm run test-karma
228

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

    
232
    npm run test-karma -- --reporters progress
233

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

    
236
    BUNDLER=browserify npm run test-karma
237

    
238
### Running automated tests with one or more browsers
239

    
240
You can also specify one or more browsers to use.
241

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

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

    
246
### Running manual tests in a browser
247

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

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

    
256
    npm run test-build
257

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

    
260
    npm run build
261

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

    
264
    npm run test-server
265

    
266
### Running other tests
267

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

    
271
### Coverage testing
272

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

    
277
    npm install
278
    npm run coverage
279

    
280
Contributing
281
------------
282

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

    
288
See: [LICENSE](https://github.com/digitalbazaar/forge/blob/cbebca3780658703d925b61b2caffb1d263a6c1d/LICENSE)
289

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

    
293
API
294
---
295

    
296
<a name="options" />
297

    
298
### Options
299

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

    
308
To disable native code when including forge in the browser:
309

    
310
```js
311
// run this *after* including the forge script
312
forge.options.usePureJavaScript = true;
313
```
314

    
315
To disable native code when using Node.js:
316

    
317
```js
318
var forge = require('node-forge');
319
forge.options.usePureJavaScript = true;
320
```
321

    
322
Transports
323
----------
324

    
325
<a name="tls" />
326

    
327
### TLS
328

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

    
331
__Examples__
332

    
333
```js
334
// create TLS client
335
var client = forge.tls.createConnection({
336
  server: false,
337
  caStore: /* Array of PEM-formatted certs or a CA store object */,
338
  sessionCache: {},
339
  // supported cipher suites in order of preference
340
  cipherSuites: [
341
    forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
342
    forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
343
  virtualHost: 'example.com',
344
  verify: function(connection, verified, depth, certs) {
345
    if(depth === 0) {
346
      var cn = certs[0].subject.getField('CN').value;
347
      if(cn !== 'example.com') {
348
        verified = {
349
          alert: forge.tls.Alert.Description.bad_certificate,
350
          message: 'Certificate common name does not match hostname.'
351
        };
352
      }
353
    }
354
    return verified;
355
  },
356
  connected: function(connection) {
357
    console.log('connected');
358
    // send message to server
359
    connection.prepare(forge.util.encodeUtf8('Hi server!'));
360
    /* NOTE: experimental, start heartbeat retransmission timer
361
    myHeartbeatTimer = setInterval(function() {
362
      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
363
    }, 5*60*1000);*/
364
  },
365
  /* provide a client-side cert if you want
366
  getCertificate: function(connection, hint) {
367
    return myClientCertificate;
368
  },
369
  /* the private key for the client-side cert if provided */
370
  getPrivateKey: function(connection, cert) {
371
    return myClientPrivateKey;
372
  },
373
  tlsDataReady: function(connection) {
374
    // TLS data (encrypted) is ready to be sent to the server
375
    sendToServerSomehow(connection.tlsData.getBytes());
376
    // if you were communicating with the server below, you'd do:
377
    // server.process(connection.tlsData.getBytes());
378
  },
379
  dataReady: function(connection) {
380
    // clear data from the server is ready
381
    console.log('the server sent: ' +
382
      forge.util.decodeUtf8(connection.data.getBytes()));
383
    // close connection
384
    connection.close();
385
  },
386
  /* NOTE: experimental
387
  heartbeatReceived: function(connection, payload) {
388
    // restart retransmission timer, look at payload
389
    clearInterval(myHeartbeatTimer);
390
    myHeartbeatTimer = setInterval(function() {
391
      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
392
    }, 5*60*1000);
393
    payload.getBytes();
394
  },*/
395
  closed: function(connection) {
396
    console.log('disconnected');
397
  },
398
  error: function(connection, error) {
399
    console.log('uh oh', error);
400
  }
401
});
402

    
403
// start the handshake process
404
client.handshake();
405

    
406
// when encrypted TLS data is received from the server, process it
407
client.process(encryptedBytesFromServer);
408

    
409
// create TLS server
410
var server = forge.tls.createConnection({
411
  server: true,
412
  caStore: /* Array of PEM-formatted certs or a CA store object */,
413
  sessionCache: {},
414
  // supported cipher suites in order of preference
415
  cipherSuites: [
416
    forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
417
    forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],
418
  // require a client-side certificate if you want
419
  verifyClient: true,
420
  verify: function(connection, verified, depth, certs) {
421
    if(depth === 0) {
422
      var cn = certs[0].subject.getField('CN').value;
423
      if(cn !== 'the-client') {
424
        verified = {
425
          alert: forge.tls.Alert.Description.bad_certificate,
426
          message: 'Certificate common name does not match expected client.'
427
        };
428
      }
429
    }
430
    return verified;
431
  },
432
  connected: function(connection) {
433
    console.log('connected');
434
    // send message to client
435
    connection.prepare(forge.util.encodeUtf8('Hi client!'));
436
    /* NOTE: experimental, start heartbeat retransmission timer
437
    myHeartbeatTimer = setInterval(function() {
438
      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
439
    }, 5*60*1000);*/
440
  },
441
  getCertificate: function(connection, hint) {
442
    return myServerCertificate;
443
  },
444
  getPrivateKey: function(connection, cert) {
445
    return myServerPrivateKey;
446
  },
447
  tlsDataReady: function(connection) {
448
    // TLS data (encrypted) is ready to be sent to the client
449
    sendToClientSomehow(connection.tlsData.getBytes());
450
    // if you were communicating with the client above you'd do:
451
    // client.process(connection.tlsData.getBytes());
452
  },
453
  dataReady: function(connection) {
454
    // clear data from the client is ready
455
    console.log('the client sent: ' +
456
      forge.util.decodeUtf8(connection.data.getBytes()));
457
    // close connection
458
    connection.close();
459
  },
460
  /* NOTE: experimental
461
  heartbeatReceived: function(connection, payload) {
462
    // restart retransmission timer, look at payload
463
    clearInterval(myHeartbeatTimer);
464
    myHeartbeatTimer = setInterval(function() {
465
      connection.prepareHeartbeatRequest(forge.util.createBuffer('1234'));
466
    }, 5*60*1000);
467
    payload.getBytes();
468
  },*/
469
  closed: function(connection) {
470
    console.log('disconnected');
471
  },
472
  error: function(connection, error) {
473
    console.log('uh oh', error);
474
  }
475
});
476

    
477
// when encrypted TLS data is received from the client, process it
478
server.process(encryptedBytesFromClient);
479
```
480

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

    
483
```js
484
var socket = new net.Socket();
485

    
486
var client = forge.tls.createConnection({
487
  server: false,
488
  verify: function(connection, verified, depth, certs) {
489
    // skip verification for testing
490
    console.log('[tls] server certificate verified');
491
    return true;
492
  },
493
  connected: function(connection) {
494
    console.log('[tls] connected');
495
    // prepare some data to send (note that the string is interpreted as
496
    // 'binary' encoded, which works for HTTP which only uses ASCII, use
497
    // forge.util.encodeUtf8(str) otherwise
498
    client.prepare('GET / HTTP/1.0\r\n\r\n');
499
  },
500
  tlsDataReady: function(connection) {
501
    // encrypted data is ready to be sent to the server
502
    var data = connection.tlsData.getBytes();
503
    socket.write(data, 'binary'); // encoding should be 'binary'
504
  },
505
  dataReady: function(connection) {
506
    // clear data from the server is ready
507
    var data = connection.data.getBytes();
508
    console.log('[tls] data received from the server: ' + data);
509
  },
510
  closed: function() {
511
    console.log('[tls] disconnected');
512
  },
513
  error: function(connection, error) {
514
    console.log('[tls] error', error);
515
  }
516
});
517

    
518
socket.on('connect', function() {
519
  console.log('[socket] connected');
520
  client.handshake();
521
});
522
socket.on('data', function(data) {
523
  client.process(data.toString('binary')); // encoding should be 'binary'
524
});
525
socket.on('end', function() {
526
  console.log('[socket] disconnected');
527
});
528

    
529
// connect to google.com
530
socket.connect(443, 'google.com');
531

    
532
// or connect to gmail's imap server (but don't send the HTTP header above)
533
//socket.connect(993, 'imap.gmail.com');
534
```
535

    
536
<a name="http" />
537

    
538
### HTTP
539

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

    
543
__Examples__
544

    
545
```js
546
// create an HTTP GET request
547
var request = forge.http.createRequest({method: 'GET', path: url.path});
548

    
549
// send the request somewhere
550
sendSomehow(request.toString());
551

    
552
// receive response
553
var buffer = forge.util.createBuffer();
554
var response = forge.http.createResponse();
555
var someAsyncDataHandler = function(bytes) {
556
  if(!response.bodyReceived) {
557
    buffer.putBytes(bytes);
558
    if(!response.headerReceived) {
559
      if(response.readHeader(buffer)) {
560
        console.log('HTTP response header: ' + response.toString());
561
      }
562
    }
563
    if(response.headerReceived && !response.bodyReceived) {
564
      if(response.readBody(buffer)) {
565
        console.log('HTTP response body: ' + response.body);
566
      }
567
    }
568
  }
569
};
570
```
571

    
572
<a name="ssh" />
573

    
574
### SSH
575

    
576
Provides some SSH utility functions.
577

    
578
__Examples__
579

    
580
```js
581
// encodes (and optionally encrypts) a private RSA key as a Putty PPK file
582
forge.ssh.privateKeyToPutty(privateKey, passphrase, comment);
583

    
584
// encodes a public RSA key as an OpenSSH file
585
forge.ssh.publicKeyToOpenSSH(key, comment);
586

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

    
590
// gets the SSH public key fingerprint in a byte buffer
591
forge.ssh.getPublicKeyFingerprint(key);
592

    
593
// gets a hex-encoded, colon-delimited SSH public key fingerprint
594
forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
595
```
596

    
597
<a name="xhr" />
598

    
599
### XHR
600

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

    
603
__Examples__
604

    
605
```js
606
// TODO
607
```
608

    
609
<a name="socket" />
610

    
611
### Sockets
612

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

    
615
__Examples__
616

    
617
```js
618
// TODO
619
```
620

    
621
Ciphers
622
-------
623

    
624
<a name="cipher" />
625

    
626
### CIPHER
627

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

    
632
These algorithms are currently supported:
633

    
634
* AES-ECB
635
* AES-CBC
636
* AES-CFB
637
* AES-OFB
638
* AES-CTR
639
* AES-GCM
640
* 3DES-ECB
641
* 3DES-CBC
642
* DES-ECB
643
* DES-CBC
644

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

    
650
__Examples__
651

    
652
```js
653
// generate a random key and IV
654
// Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256
655
var key = forge.random.getBytesSync(16);
656
var iv = forge.random.getBytesSync(16);
657

    
658
/* alternatively, generate a password-based 16-byte key
659
var salt = forge.random.getBytesSync(128);
660
var key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
661
*/
662

    
663
// encrypt some bytes using CBC mode
664
// (other modes include: ECB, CFB, OFB, CTR, and GCM)
665
// Note: CBC and ECB modes use PKCS#7 padding as default
666
var cipher = forge.cipher.createCipher('AES-CBC', key);
667
cipher.start({iv: iv});
668
cipher.update(forge.util.createBuffer(someBytes));
669
cipher.finish();
670
var encrypted = cipher.output;
671
// outputs encrypted hex
672
console.log(encrypted.toHex());
673

    
674
// decrypt some bytes using CBC mode
675
// (other modes include: CFB, OFB, CTR, and GCM)
676
var decipher = forge.cipher.createDecipher('AES-CBC', key);
677
decipher.start({iv: iv});
678
decipher.update(encrypted);
679
var result = decipher.finish(); // check 'result' for true/false
680
// outputs decrypted hex
681
console.log(decipher.output.toHex());
682

    
683
// decrypt bytes using CBC mode and streaming
684
// Performance can suffer for large multi-MB inputs due to buffer
685
// manipulations. Stream processing in chunks can offer significant
686
// improvement. CPU intensive update() calls could also be performed with
687
// setImmediate/setTimeout to avoid blocking the main browser UI thread (not
688
// shown here). Optimal block size depends on the JavaScript VM and other
689
// factors. Encryption can use a simple technique for increased performance.
690
var encryptedBytes = encrypted.bytes();
691
var decipher = forge.cipher.createDecipher('AES-CBC', key);
692
decipher.start({iv: iv});
693
var length = encryptedBytes.length;
694
var chunkSize = 1024 * 64;
695
var index = 0;
696
var decrypted = '';
697
do {
698
  decrypted += decipher.output.getBytes();
699
  var buf = forge.util.createBuffer(encryptedBytes.substr(index, chunkSize));
700
  decipher.update(buf);
701
  index += chunkSize;
702
} while(index < length);
703
var result = decipher.finish();
704
assert(result);
705
decrypted += decipher.output.getBytes();
706
console.log(forge.util.bytesToHex(decrypted));
707

    
708
// encrypt some bytes using GCM mode
709
var cipher = forge.cipher.createCipher('AES-GCM', key);
710
cipher.start({
711
  iv: iv, // should be a 12-byte binary-encoded string or byte buffer
712
  additionalData: 'binary-encoded string', // optional
713
  tagLength: 128 // optional, defaults to 128 bits
714
});
715
cipher.update(forge.util.createBuffer(someBytes));
716
cipher.finish();
717
var encrypted = cipher.output;
718
var tag = cipher.mode.tag;
719
// outputs encrypted hex
720
console.log(encrypted.toHex());
721
// outputs authentication tag
722
console.log(tag.toHex());
723

    
724
// decrypt some bytes using GCM mode
725
var decipher = forge.cipher.createDecipher('AES-GCM', key);
726
decipher.start({
727
  iv: iv,
728
  additionalData: 'binary-encoded string', // optional
729
  tagLength: 128, // optional, defaults to 128 bits
730
  tag: tag // authentication tag from encryption
731
});
732
decipher.update(encrypted);
733
var pass = decipher.finish();
734
// pass is false if there was a failure (eg: authentication tag didn't match)
735
if(pass) {
736
  // outputs decrypted hex
737
  console.log(decipher.output.toHex());
738
}
739
```
740

    
741
Using forge in Node.js to match openssl's "enc" command line tool (**Note**: OpenSSL "enc" uses a non-standard file format with a custom key derivation function and a fixed iteration count of 1, which some consider less secure than alternatives such as [OpenPGP](https://tools.ietf.org/html/rfc4880)/[GnuPG](https://www.gnupg.org/)):
742

    
743
```js
744
var forge = require('node-forge');
745
var fs = require('fs');
746

    
747
// openssl enc -des3 -in input.txt -out input.enc
748
function encrypt(password) {
749
  var input = fs.readFileSync('input.txt', {encoding: 'binary'});
750

    
751
  // 3DES key and IV sizes
752
  var keySize = 24;
753
  var ivSize = 8;
754

    
755
  // get derived bytes
756
  // Notes:
757
  // 1. If using an alternative hash (eg: "-md sha1") pass
758
  //   "forge.md.sha1.create()" as the final parameter.
759
  // 2. If using "-nosalt", set salt to null.
760
  var salt = forge.random.getBytesSync(8);
761
  // var md = forge.md.sha1.create(); // "-md sha1"
762
  var derivedBytes = forge.pbe.opensslDeriveBytes(
763
    password, salt, keySize + ivSize/*, md*/);
764
  var buffer = forge.util.createBuffer(derivedBytes);
765
  var key = buffer.getBytes(keySize);
766
  var iv = buffer.getBytes(ivSize);
767

    
768
  var cipher = forge.cipher.createCipher('3DES-CBC', key);
769
  cipher.start({iv: iv});
770
  cipher.update(forge.util.createBuffer(input, 'binary'));
771
  cipher.finish();
772

    
773
  var output = forge.util.createBuffer();
774

    
775
  // if using a salt, prepend this to the output:
776
  if(salt !== null) {
777
    output.putBytes('Salted__'); // (add to match openssl tool output)
778
    output.putBytes(salt);
779
  }
780
  output.putBuffer(cipher.output);
781

    
782
  fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'});
783
}
784

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

    
789
  // parse salt from input
790
  input = forge.util.createBuffer(input, 'binary');
791
  // skip "Salted__" (if known to be present)
792
  input.getBytes('Salted__'.length);
793
  // read 8-byte salt
794
  var salt = input.getBytes(8);
795

    
796
  // Note: if using "-nosalt", skip above parsing and use
797
  // var salt = null;
798

    
799
  // 3DES key and IV sizes
800
  var keySize = 24;
801
  var ivSize = 8;
802

    
803
  var derivedBytes = forge.pbe.opensslDeriveBytes(
804
    password, salt, keySize + ivSize);
805
  var buffer = forge.util.createBuffer(derivedBytes);
806
  var key = buffer.getBytes(keySize);
807
  var iv = buffer.getBytes(ivSize);
808

    
809
  var decipher = forge.cipher.createDecipher('3DES-CBC', key);
810
  decipher.start({iv: iv});
811
  decipher.update(input);
812
  var result = decipher.finish(); // check 'result' for true/false
813

    
814
  fs.writeFileSync(
815
    'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'});
816
}
817
```
818

    
819
<a name="aes" />
820

    
821
### AES
822

    
823
Provides [AES][] encryption and decryption in [CBC][], [CFB][], [OFB][],
824
[CTR][], and [GCM][] modes. See [CIPHER](#cipher) for examples.
825

    
826
<a name="des" />
827

    
828
### DES
829

    
830
Provides [3DES][] and [DES][] encryption and decryption in [ECB][] and
831
[CBC][] modes. See [CIPHER](#cipher) for examples.
832

    
833
<a name="rc2" />
834

    
835
### RC2
836

    
837
__Examples__
838

    
839
```js
840
// generate a random key and IV
841
var key = forge.random.getBytesSync(16);
842
var iv = forge.random.getBytesSync(8);
843

    
844
// encrypt some bytes
845
var cipher = forge.rc2.createEncryptionCipher(key);
846
cipher.start(iv);
847
cipher.update(forge.util.createBuffer(someBytes));
848
cipher.finish();
849
var encrypted = cipher.output;
850
// outputs encrypted hex
851
console.log(encrypted.toHex());
852

    
853
// decrypt some bytes
854
var cipher = forge.rc2.createDecryptionCipher(key);
855
cipher.start(iv);
856
cipher.update(encrypted);
857
cipher.finish();
858
// outputs decrypted hex
859
console.log(cipher.output.toHex());
860
```
861

    
862
PKI
863
---
864

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

    
869
<a name="ed25519" />
870

    
871
### ED25519
872

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

    
875
__Examples__
876

    
877
```js
878
var ed25519 = forge.pki.ed25519;
879

    
880
// generate a random ED25519 keypair
881
var keypair = ed25519.generateKeyPair();
882
// `keypair.publicKey` is a node.js Buffer or Uint8Array
883
// `keypair.privateKey` is a node.js Buffer or Uint8Array
884

    
885
// generate a random ED25519 keypair based on a random 32-byte seed
886
var seed = forge.random.getBytesSync(32);
887
var keypair = ed25519.generateKeyPair({seed: seed});
888

    
889
// generate a random ED25519 keypair based on a "password" 32-byte seed
890
var password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
891
var seed = new forge.util.ByteBuffer(password, 'utf8');
892
var keypair = ed25519.generateKeyPair({seed: seed});
893

    
894
// sign a UTF-8 message
895
var signature = ED25519.sign({
896
  message: 'test',
897
  // also accepts `binary` if you want to pass a binary string
898
  encoding: 'utf8',
899
  // node.js Buffer, Uint8Array, forge ByteBuffer, binary string
900
  privateKey: privateKey
901
});
902
// `signature` is a node.js Buffer or Uint8Array
903

    
904
// sign a message passed as a buffer
905
var signature = ED25519.sign({
906
  // also accepts a forge ByteBuffer or Uint8Array
907
  message: Buffer.from('test', 'utf8'),
908
  privateKey: privateKey
909
});
910

    
911
// sign a message digest (shorter "message" == better performance)
912
var md = forge.md.sha256.create();
913
md.update('test', 'utf8');
914
var signature = ED25519.sign({
915
  md: md,
916
  privateKey: privateKey
917
});
918

    
919
// verify a signature on a UTF-8 message
920
var verified = ED25519.verify({
921
  message: 'test',
922
  encoding: 'utf8',
923
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
924
  signature: signature,
925
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
926
  publicKey: publicKey
927
});
928
// `verified` is true/false
929

    
930
// sign a message passed as a buffer
931
var verified = ED25519.verify({
932
  // also accepts a forge ByteBuffer or Uint8Array
933
  message: Buffer.from('test', 'utf8'),
934
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
935
  signature: signature,
936
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
937
  publicKey: publicKey
938
});
939

    
940
// verify a signature on a message digest
941
var md = forge.md.sha256.create();
942
md.update('test', 'utf8');
943
var verified = ED25519.verify({
944
  md: md,
945
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
946
  signature: signature,
947
  // node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
948
  publicKey: publicKey
949
});
950
```
951

    
952
<a name="rsa" />
953

    
954
### RSA
955

    
956
__Examples__
957

    
958
```js
959
var rsa = forge.pki.rsa;
960

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

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

    
974
// generate an RSA key pair in steps that attempt to run for a specified period
975
// of time on the main JS thread
976
var state = rsa.createKeyPairGenerationState(2048, 0x10001);
977
var step = function() {
978
  // run for 100 ms
979
  if(!rsa.stepKeyPairGenerationState(state, 100)) {
980
    setTimeout(step, 1);
981
  }
982
  else {
983
    // done, turn off progress indicator, use state.keys
984
  }
985
};
986
// turn on progress indicator, schedule generation to run
987
setTimeout(step);
988

    
989
// sign data with a private key and output DigestInfo DER-encoded bytes
990
// (defaults to RSASSA PKCS#1 v1.5)
991
var md = forge.md.sha1.create();
992
md.update('sign this', 'utf8');
993
var signature = privateKey.sign(md);
994

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

    
999
// sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based
1000
// masking function MGF1, and a 20 byte salt
1001
var md = forge.md.sha1.create();
1002
md.update('sign this', 'utf8');
1003
var pss = forge.pss.create({
1004
  md: forge.md.sha1.create(),
1005
  mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
1006
  saltLength: 20
1007
  // optionally pass 'prng' with a custom PRNG implementation
1008
  // optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt
1009
});
1010
var signature = privateKey.sign(md, pss);
1011

    
1012
// verify RSASSA-PSS signature
1013
var pss = forge.pss.create({
1014
  md: forge.md.sha1.create(),
1015
  mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
1016
  saltLength: 20
1017
  // optionally pass 'prng' with a custom PRNG implementation
1018
});
1019
var md = forge.md.sha1.create();
1020
md.update('sign this', 'utf8');
1021
publicKey.verify(md.digest().getBytes(), signature, pss);
1022

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

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

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

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

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

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

    
1041
// encrypt data with a public key using RSAES-OAEP/SHA-256
1042
var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
1043
  md: forge.md.sha256.create()
1044
});
1045

    
1046
// decrypt data with a private key using RSAES-OAEP/SHA-256
1047
var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
1048
  md: forge.md.sha256.create()
1049
});
1050

    
1051
// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
1052
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
1053
var encrypted = publicKey.encrypt(bytes, 'RSA-OAEP', {
1054
  md: forge.md.sha256.create(),
1055
  mgf1: {
1056
    md: forge.md.sha1.create()
1057
  }
1058
});
1059

    
1060
// decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1
1061
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
1062
var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
1063
  md: forge.md.sha256.create(),
1064
  mgf1: {
1065
    md: forge.md.sha1.create()
1066
  }
1067
});
1068

    
1069
```
1070

    
1071
<a name="rsakem" />
1072

    
1073
### RSA-KEM
1074

    
1075
__Examples__
1076

    
1077
```js
1078
// generate an RSA key pair asynchronously (uses web workers if available)
1079
// use workers: -1 to run a fast core estimator to optimize # of workers
1080
forge.rsa.generateKeyPair({bits: 2048, workers: -1}, function(err, keypair) {
1081
  // keypair.privateKey, keypair.publicKey
1082
});
1083

    
1084
// generate and encapsulate a 16-byte secret key
1085
var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
1086
var kem = forge.kem.rsa.create(kdf1);
1087
var result = kem.encrypt(keypair.publicKey, 16);
1088
// result has 'encapsulation' and 'key'
1089

    
1090
// encrypt some bytes
1091
var iv = forge.random.getBytesSync(12);
1092
var someBytes = 'hello world!';
1093
var cipher = forge.cipher.createCipher('AES-GCM', result.key);
1094
cipher.start({iv: iv});
1095
cipher.update(forge.util.createBuffer(someBytes));
1096
cipher.finish();
1097
var encrypted = cipher.output.getBytes();
1098
var tag = cipher.mode.tag.getBytes();
1099

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

    
1102
// decrypt encapsulated 16-byte secret key
1103
var kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
1104
var kem = forge.kem.rsa.create(kdf1);
1105
var key = kem.decrypt(keypair.privateKey, result.encapsulation, 16);
1106

    
1107
// decrypt some bytes
1108
var decipher = forge.cipher.createDecipher('AES-GCM', key);
1109
decipher.start({iv: iv, tag: tag});
1110
decipher.update(forge.util.createBuffer(encrypted));
1111
var pass = decipher.finish();
1112
// pass is false if there was a failure (eg: authentication tag didn't match)
1113
if(pass) {
1114
  // outputs 'hello world!'
1115
  console.log(decipher.output.getBytes());
1116
}
1117

    
1118
```
1119

    
1120
<a name="x509" />
1121

    
1122
### X.509
1123

    
1124
__Examples__
1125

    
1126
```js
1127
var pki = forge.pki;
1128

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

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

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

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

    
1141
// gets a SHA-1 RSAPublicKey fingerprint a byte buffer
1142
pki.getPublicKeyFingerprint(key);
1143

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

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

    
1150
// gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprint
1151
pki.getPublicKeyFingerprint(key, {
1152
  type: 'SubjectPublicKeyInfo',
1153
  encoding: 'hex',
1154
  delimiter: ':'
1155
});
1156

    
1157
// gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprint
1158
pki.getPublicKeyFingerprint(key, {
1159
  md: forge.md.md5.create(),
1160
  encoding: 'hex',
1161
  delimiter: ':'
1162
});
1163

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

    
1167
// add a certificate to the CA store
1168
caStore.addCertificate(certObjectOrPemString);
1169

    
1170
// gets the issuer (its certificate) for the given certificate
1171
var issuerCert = caStore.getIssuer(subjectCert);
1172

    
1173
// verifies a certificate chain against a CA store
1174
pki.verifyCertificateChain(caStore, chain, customVerifyCallback);
1175

    
1176
// signs a certificate using the given private key
1177
cert.sign(privateKey);
1178

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

    
1182
// verifies an issued certificate using the certificates public key
1183
var verified = issuer.verify(issued);
1184

    
1185
// generate a keypair and create an X.509v3 certificate
1186
var keys = pki.rsa.generateKeyPair(2048);
1187
var cert = pki.createCertificate();
1188
cert.publicKey = keys.publicKey;
1189
// alternatively set public key from a csr
1190
//cert.publicKey = csr.publicKey;
1191
// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
1192
// Conforming CAs should ensure serialNumber is:
1193
// - no more than 20 octets
1194
// - non-negative (prefix a '00' if your value starts with a '1' bit)
1195
cert.serialNumber = '01';
1196
cert.validity.notBefore = new Date();
1197
cert.validity.notAfter = new Date();
1198
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
1199
var attrs = [{
1200
  name: 'commonName',
1201
  value: 'example.org'
1202
}, {
1203
  name: 'countryName',
1204
  value: 'US'
1205
}, {
1206
  shortName: 'ST',
1207
  value: 'Virginia'
1208
}, {
1209
  name: 'localityName',
1210
  value: 'Blacksburg'
1211
}, {
1212
  name: 'organizationName',
1213
  value: 'Test'
1214
}, {
1215
  shortName: 'OU',
1216
  value: 'Test'
1217
}];
1218
cert.setSubject(attrs);
1219
// alternatively set subject from a csr
1220
//cert.setSubject(csr.subject.attributes);
1221
cert.setIssuer(attrs);
1222
cert.setExtensions([{
1223
  name: 'basicConstraints',
1224
  cA: true
1225
}, {
1226
  name: 'keyUsage',
1227
  keyCertSign: true,
1228
  digitalSignature: true,
1229
  nonRepudiation: true,
1230
  keyEncipherment: true,
1231
  dataEncipherment: true
1232
}, {
1233
  name: 'extKeyUsage',
1234
  serverAuth: true,
1235
  clientAuth: true,
1236
  codeSigning: true,
1237
  emailProtection: true,
1238
  timeStamping: true
1239
}, {
1240
  name: 'nsCertType',
1241
  client: true,
1242
  server: true,
1243
  email: true,
1244
  objsign: true,
1245
  sslCA: true,
1246
  emailCA: true,
1247
  objCA: true
1248
}, {
1249
  name: 'subjectAltName',
1250
  altNames: [{
1251
    type: 6, // URI
1252
    value: 'http://example.org/webid#me'
1253
  }, {
1254
    type: 7, // IP
1255
    ip: '127.0.0.1'
1256
  }]
1257
}, {
1258
  name: 'subjectKeyIdentifier'
1259
}]);
1260
/* alternatively set extensions from a csr
1261
var extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;
1262
// optionally add more extensions
1263
extensions.push.apply(extensions, [{
1264
  name: 'basicConstraints',
1265
  cA: true
1266
}, {
1267
  name: 'keyUsage',
1268
  keyCertSign: true,
1269
  digitalSignature: true,
1270
  nonRepudiation: true,
1271
  keyEncipherment: true,
1272
  dataEncipherment: true
1273
}]);
1274
cert.setExtensions(extensions);
1275
*/
1276
// self-sign certificate
1277
cert.sign(keys.privateKey);
1278

    
1279
// convert a Forge certificate to PEM
1280
var pem = pki.certificateToPem(cert);
1281

    
1282
// convert a Forge certificate from PEM
1283
var cert = pki.certificateFromPem(pem);
1284

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

    
1288
// convert a Forge certificate to an ASN.1 X.509v3 object
1289
var asn1Cert = pki.certificateToAsn1(cert);
1290
```
1291

    
1292
<a name="pkcs5" />
1293

    
1294
### PKCS#5
1295

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

    
1298
__Examples__
1299

    
1300
```js
1301
// generate a password-based 16-byte key
1302
// note an optional message digest can be passed as the final parameter
1303
var salt = forge.random.getBytesSync(128);
1304
var derivedKey = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
1305

    
1306
// generate key asynchronously
1307
// note an optional message digest can be passed before the callback
1308
forge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey) {
1309
  // do something w/derivedKey
1310
});
1311
```
1312

    
1313
<a name="pkcs7" />
1314

    
1315
### PKCS#7
1316

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

    
1319
__Examples__
1320

    
1321
```js
1322
// convert a message from PEM
1323
var p7 = forge.pkcs7.messageFromPem(pem);
1324
// look at p7.recipients
1325

    
1326
// find a recipient by the issuer of a certificate
1327
var recipient = p7.findRecipient(cert);
1328

    
1329
// decrypt
1330
p7.decrypt(p7.recipients[0], privateKey);
1331

    
1332
// create a p7 enveloped message
1333
var p7 = forge.pkcs7.createEnvelopedData();
1334

    
1335
// add a recipient
1336
var cert = forge.pki.certificateFromPem(certPem);
1337
p7.addRecipient(cert);
1338

    
1339
// set content
1340
p7.content = forge.util.createBuffer('Hello');
1341

    
1342
// encrypt
1343
p7.encrypt();
1344

    
1345
// convert message to PEM
1346
var pem = forge.pkcs7.messageToPem(p7);
1347

    
1348
// create a degenerate PKCS#7 certificate container
1349
// (CRLs not currently supported, only certificates)
1350
var p7 = forge.pkcs7.createSignedData();
1351
p7.addCertificate(certOrCertPem1);
1352
p7.addCertificate(certOrCertPem2);
1353
var pem = forge.pkcs7.messageToPem(p7);
1354

    
1355
// create PKCS#7 signed data with authenticatedAttributes
1356
// attributes include: PKCS#9 content-type, message-digest, and signing-time
1357
var p7 = forge.pkcs7.createSignedData();
1358
p7.content = forge.util.createBuffer('Some content to be signed.', 'utf8');
1359
p7.addCertificate(certOrCertPem);
1360
p7.addSigner({
1361
  key: privateKeyAssociatedWithCert,
1362
  certificate: certOrCertPem,
1363
  digestAlgorithm: forge.pki.oids.sha256,
1364
  authenticatedAttributes: [{
1365
    type: forge.pki.oids.contentType,
1366
    value: forge.pki.oids.data
1367
  }, {
1368
    type: forge.pki.oids.messageDigest
1369
    // value will be auto-populated at signing time
1370
  }, {
1371
    type: forge.pki.oids.signingTime,
1372
    // value can also be auto-populated at signing time
1373
    value: new Date()
1374
  }]
1375
});
1376
p7.sign();
1377
var pem = forge.pkcs7.messageToPem(p7);
1378

    
1379
// PKCS#7 Sign in detached mode.
1380
// Includes the signature and certificate without the signed data.
1381
p7.sign({detached: true});
1382

    
1383
```
1384

    
1385
<a name="pkcs8" />
1386

    
1387
### PKCS#8
1388

    
1389
__Examples__
1390

    
1391
```js
1392
var pki = forge.pki;
1393

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

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

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

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

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

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

    
1412
// encrypts a PrivateKeyInfo using a custom password and
1413
// outputs an EncryptedPrivateKeyInfo
1414
var encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo(
1415
  privateKeyInfo, 'myCustomPasswordHere', {
1416
    algorithm: 'aes256', // 'aes128', 'aes192', 'aes256', '3des'
1417
  });
1418

    
1419
// decrypts an ASN.1 EncryptedPrivateKeyInfo that was encrypted
1420
// with a custom password
1421
var privateKeyInfo = pki.decryptPrivateKeyInfo(
1422
  encryptedPrivateKeyInfo, 'myCustomPasswordHere');
1423

    
1424
// converts an EncryptedPrivateKeyInfo to PEM
1425
var pem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);
1426

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

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

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

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

    
1440
// sets an RSA public key from a private key
1441
var publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e);
1442
```
1443

    
1444
<a name="pkcs10" />
1445

    
1446
### PKCS#10
1447

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

    
1451
__Examples__
1452

    
1453
```js
1454
// generate a key pair
1455
var keys = forge.pki.rsa.generateKeyPair(1024);
1456

    
1457
// create a certification request (CSR)
1458
var csr = forge.pki.createCertificationRequest();
1459
csr.publicKey = keys.publicKey;
1460
csr.setSubject([{
1461
  name: 'commonName',
1462
  value: 'example.org'
1463
}, {
1464
  name: 'countryName',
1465
  value: 'US'
1466
}, {
1467
  shortName: 'ST',
1468
  value: 'Virginia'
1469
}, {
1470
  name: 'localityName',
1471
  value: 'Blacksburg'
1472
}, {
1473
  name: 'organizationName',
1474
  value: 'Test'
1475
}, {
1476
  shortName: 'OU',
1477
  value: 'Test'
1478
}]);
1479
// set (optional) attributes
1480
csr.setAttributes([{
1481
  name: 'challengePassword',
1482
  value: 'password'
1483
}, {
1484
  name: 'unstructuredName',
1485
  value: 'My Company, Inc.'
1486
}, {
1487
  name: 'extensionRequest',
1488
  extensions: [{
1489
    name: 'subjectAltName',
1490
    altNames: [{
1491
      // 2 is DNS type
1492
      type: 2,
1493
      value: 'test.domain.com'
1494
    }, {
1495
      type: 2,
1496
      value: 'other.domain.com',
1497
    }, {
1498
      type: 2,
1499
      value: 'www.domain.net'
1500
    }]
1501
  }]
1502
}]);
1503

    
1504
// sign certification request
1505
csr.sign(keys.privateKey);
1506

    
1507
// verify certification request
1508
var verified = csr.verify();
1509

    
1510
// convert certification request to PEM-format
1511
var pem = forge.pki.certificationRequestToPem(csr);
1512

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

    
1516
// get an attribute
1517
csr.getAttribute({name: 'challengePassword'});
1518

    
1519
// get extensions array
1520
csr.getAttribute({name: 'extensionRequest'}).extensions;
1521

    
1522
```
1523

    
1524
<a name="pkcs12" />
1525

    
1526
### PKCS#12
1527

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

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

    
1534
__Examples__
1535

    
1536
```js
1537
// decode p12 from base64
1538
var p12Der = forge.util.decode64(p12b64);
1539
// get p12 as ASN.1 object
1540
var p12Asn1 = forge.asn1.fromDer(p12Der);
1541
// decrypt p12 using the password 'password'
1542
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');
1543
// decrypt p12 using non-strict parsing mode (resolves some ASN.1 parse errors)
1544
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, 'password');
1545
// decrypt p12 using literally no password (eg: Mac OS X/apple push)
1546
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1);
1547
// decrypt p12 using an "empty" password (eg: OpenSSL with no password input)
1548
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, '');
1549
// p12.safeContents is an array of safe contents, each of
1550
// which contains an array of safeBags
1551

    
1552
// get bags by friendlyName
1553
var bags = p12.getBags({friendlyName: 'test'});
1554
// bags are key'd by attribute type (here "friendlyName")
1555
// and the key values are an array of matching objects
1556
var cert = bags.friendlyName[0];
1557

    
1558
// get bags by localKeyId
1559
var bags = p12.getBags({localKeyId: buffer});
1560
// bags are key'd by attribute type (here "localKeyId")
1561
// and the key values are an array of matching objects
1562
var cert = bags.localKeyId[0];
1563

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

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

    
1576
// get bags by friendlyName and filter on bag type
1577
var bags = p12.getBags({
1578
  friendlyName: 'test',
1579
  bagType: forge.pki.oids.certBag
1580
});
1581

    
1582
// get key bags
1583
var bags = p12.getBags({bagType: forge.pki.oids.keyBag});
1584
// get key
1585
var bag = bags[forge.pki.oids.keyBag][0];
1586
var key = bag.key;
1587
// if the key is in a format unrecognized by forge then
1588
// bag.key will be `null`, use bag.asn1 to get the ASN.1
1589
// representation of the key
1590
if(bag.key === null) {
1591
  var keyAsn1 = bag.asn1;
1592
  // can now convert back to DER/PEM/etc for export
1593
}
1594

    
1595
// generate a p12 using AES (default)
1596
var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
1597
  privateKey, certificateChain, 'password');
1598

    
1599
// generate a p12 that can be imported by Chrome/Firefox/iOS
1600
// (requires the use of Triple DES instead of AES)
1601
var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
1602
  privateKey, certificateChain, 'password',
1603
  {algorithm: '3des'});
1604

    
1605
// base64-encode p12
1606
var p12Der = forge.asn1.toDer(p12Asn1).getBytes();
1607
var p12b64 = forge.util.encode64(p12Der);
1608

    
1609
// create download link for p12
1610
var a = document.createElement('a');
1611
a.download = 'example.p12';
1612
a.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12b64);
1613
a.appendChild(document.createTextNode('Download'));
1614
```
1615

    
1616
<a name="asn" />
1617

    
1618
### ASN.1
1619

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

    
1622
__Examples__
1623

    
1624
```js
1625
var asn1 = forge.asn1;
1626

    
1627
// create a SubjectPublicKeyInfo
1628
var subjectPublicKeyInfo =
1629
  asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1630
    // AlgorithmIdentifier
1631
    asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1632
      // algorithm
1633
      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
1634
        asn1.oidToDer(pki.oids['rsaEncryption']).getBytes()),
1635
      // parameters (null)
1636
      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')
1637
    ]),
1638
    // subjectPublicKey
1639
    asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, [
1640
      // RSAPublicKey
1641
      asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1642
        // modulus (n)
1643
        asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
1644
          _bnToBytes(key.n)),
1645
        // publicExponent (e)
1646
        asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
1647
          _bnToBytes(key.e))
1648
      ])
1649
    ])
1650
  ]);
1651

    
1652
// serialize an ASN.1 object to DER format
1653
var derBuffer = asn1.toDer(subjectPublicKeyInfo);
1654

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

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

    
1661
// convert a byte buffer with a DER-encoded OID to a dot-separated string
1662
console.log(asn1.derToOid(derOidBuffer));
1663
// output: 1.2.840.113549.1.1.5
1664

    
1665
// validates that an ASN.1 object matches a particular ASN.1 structure and
1666
// captures data of interest from that structure for easy access
1667
var publicKeyValidator = {
1668
  name: 'SubjectPublicKeyInfo',
1669
  tagClass: asn1.Class.UNIVERSAL,
1670
  type: asn1.Type.SEQUENCE,
1671
  constructed: true,
1672
  captureAsn1: 'subjectPublicKeyInfo',
1673
  value: [{
1674
    name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',
1675
    tagClass: asn1.Class.UNIVERSAL,
1676
    type: asn1.Type.SEQUENCE,
1677
    constructed: true,
1678
    value: [{
1679
      name: 'AlgorithmIdentifier.algorithm',
1680
      tagClass: asn1.Class.UNIVERSAL,
1681
      type: asn1.Type.OID,
1682
      constructed: false,
1683
      capture: 'publicKeyOid'
1684
    }]
1685
  }, {
1686
    // subjectPublicKey
1687
    name: 'SubjectPublicKeyInfo.subjectPublicKey',
1688
    tagClass: asn1.Class.UNIVERSAL,
1689
    type: asn1.Type.BITSTRING,
1690
    constructed: false,
1691
    value: [{
1692
      // RSAPublicKey
1693
      name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',
1694
      tagClass: asn1.Class.UNIVERSAL,
1695
      type: asn1.Type.SEQUENCE,
1696
      constructed: true,
1697
      optional: true,
1698
      captureAsn1: 'rsaPublicKey'
1699
    }]
1700
  }]
1701
};
1702

    
1703
var capture = {};
1704
var errors = [];
1705
if(!asn1.validate(
1706
  publicKeyValidator, subjectPublicKeyInfo, validator, capture, errors)) {
1707
  throw 'ASN.1 object is not a SubjectPublicKeyInfo.';
1708
}
1709
// capture.subjectPublicKeyInfo contains the full ASN.1 object
1710
// capture.rsaPublicKey contains the full ASN.1 object for the RSA public key
1711
// capture.publicKeyOid only contains the value for the OID
1712
var oid = asn1.derToOid(capture.publicKeyOid);
1713
if(oid !== pki.oids['rsaEncryption']) {
1714
  throw 'Unsupported OID.';
1715
}
1716

    
1717
// pretty print an ASN.1 object to a string for debugging purposes
1718
asn1.prettyPrint(object);
1719
```
1720

    
1721
Message Digests
1722
----------------
1723

    
1724
<a name="sha1" />
1725

    
1726
### SHA1
1727

    
1728
Provides [SHA-1][] message digests.
1729

    
1730
__Examples__
1731

    
1732
```js
1733
var md = forge.md.sha1.create();
1734
md.update('The quick brown fox jumps over the lazy dog');
1735
console.log(md.digest().toHex());
1736
// output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
1737
```
1738

    
1739
<a name="sha256" />
1740

    
1741
### SHA256
1742

    
1743
Provides [SHA-256][] message digests.
1744

    
1745
__Examples__
1746

    
1747
```js
1748
var md = forge.md.sha256.create();
1749
md.update('The quick brown fox jumps over the lazy dog');
1750
console.log(md.digest().toHex());
1751
// output: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
1752
```
1753

    
1754
<a name="sha384" />
1755

    
1756
### SHA384
1757

    
1758
Provides [SHA-384][] message digests.
1759

    
1760
__Examples__
1761

    
1762
```js
1763
var md = forge.md.sha384.create();
1764
md.update('The quick brown fox jumps over the lazy dog');
1765
console.log(md.digest().toHex());
1766
// output: ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1
1767
```
1768

    
1769
<a name="sha512" />
1770

    
1771
### SHA512
1772

    
1773
Provides [SHA-512][] message digests.
1774

    
1775
__Examples__
1776

    
1777
```js
1778
// SHA-512
1779
var md = forge.md.sha512.create();
1780
md.update('The quick brown fox jumps over the lazy dog');
1781
console.log(md.digest().toHex());
1782
// output: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6
1783

    
1784
// SHA-512/224
1785
var md = forge.md.sha512.sha224.create();
1786
md.update('The quick brown fox jumps over the lazy dog');
1787
console.log(md.digest().toHex());
1788
// output: 944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37
1789

    
1790
// SHA-512/256
1791
var md = forge.md.sha512.sha256.create();
1792
md.update('The quick brown fox jumps over the lazy dog');
1793
console.log(md.digest().toHex());
1794
// output: dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d
1795
```
1796

    
1797
<a name="md5" />
1798

    
1799
### MD5
1800

    
1801
Provides [MD5][] message digests.
1802

    
1803
__Examples__
1804

    
1805
```js
1806
var md = forge.md.md5.create();
1807
md.update('The quick brown fox jumps over the lazy dog');
1808
console.log(md.digest().toHex());
1809
// output: 9e107d9d372bb6826bd81d3542a419d6
1810
```
1811

    
1812
<a name="hmac" />
1813

    
1814
### HMAC
1815

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

    
1818
__Examples__
1819

    
1820
```js
1821
var hmac = forge.hmac.create();
1822
hmac.start('sha1', 'Jefe');
1823
hmac.update('what do ya want for nothing?');
1824
console.log(hmac.digest().toHex());
1825
// output: effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
1826
```
1827

    
1828
Utilities
1829
---------
1830

    
1831
<a name="prime" />
1832

    
1833
### Prime
1834

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

    
1837
__Examples__
1838

    
1839
```js
1840
// generate a random prime on the main JS thread
1841
var bits = 1024;
1842
forge.prime.generateProbablePrime(bits, function(err, num) {
1843
  console.log('random prime', num.toString(16));
1844
});
1845

    
1846
// generate a random prime using Web Workers (if available, otherwise
1847
// falls back to the main thread)
1848
var bits = 1024;
1849
var options = {
1850
  algorithm: {
1851
    name: 'PRIMEINC',
1852
    workers: -1 // auto-optimize # of workers
1853
  }
1854
};
1855
forge.prime.generateProbablePrime(bits, options, function(err, num) {
1856
  console.log('random prime', num.toString(16));
1857
});
1858
```
1859

    
1860
<a name="prng" />
1861

    
1862
### PRNG
1863

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

    
1870
__Examples__
1871

    
1872
```js
1873
// get some random bytes synchronously
1874
var bytes = forge.random.getBytesSync(32);
1875
console.log(forge.util.bytesToHex(bytes));
1876

    
1877
// get some random bytes asynchronously
1878
forge.random.getBytes(32, function(err, bytes) {
1879
  console.log(forge.util.bytesToHex(bytes));
1880
});
1881

    
1882
// collect some entropy if you'd like
1883
forge.random.collect(someRandomBytes);
1884
jQuery().mousemove(function(e) {
1885
  forge.random.collectInt(e.clientX, 16);
1886
  forge.random.collectInt(e.clientY, 16);
1887
});
1888

    
1889
// specify a seed file for use with the synchronous API if you'd like
1890
forge.random.seedFileSync = function(needed) {
1891
  // get 'needed' number of random bytes from somewhere
1892
  return fetchedRandomBytes;
1893
};
1894

    
1895
// specify a seed file for use with the asynchronous API if you'd like
1896
forge.random.seedFile = function(needed, callback) {
1897
  // get the 'needed' number of random bytes from somewhere
1898
  callback(null, fetchedRandomBytes);
1899
});
1900

    
1901
// register the main thread to send entropy or a Web Worker to receive
1902
// entropy on demand from the main thread
1903
forge.random.registerWorker(self);
1904

    
1905
// generate a new instance of a PRNG with no collected entropy
1906
var myPrng = forge.random.createInstance();
1907
```
1908

    
1909
<a name="task" />
1910

    
1911
### Tasks
1912

    
1913
Provides queuing and synchronizing tasks in a web application.
1914

    
1915
__Examples__
1916

    
1917
```js
1918
// TODO
1919
```
1920

    
1921
<a name="util" />
1922

    
1923
### Utilities
1924

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

    
1928
__Examples__
1929

    
1930
```js
1931
// encode/decode base64
1932
var encoded = forge.util.encode64(str);
1933
var str = forge.util.decode64(encoded);
1934

    
1935
// encode/decode UTF-8
1936
var encoded = forge.util.encodeUtf8(str);
1937
var str = forge.util.decodeUtf8(encoded);
1938

    
1939
// bytes to/from hex
1940
var bytes = forge.util.hexToBytes(hex);
1941
var hex = forge.util.bytesToHex(bytes);
1942

    
1943
// create an empty byte buffer
1944
var buffer = forge.util.createBuffer();
1945
// create a byte buffer from raw binary bytes
1946
var buffer = forge.util.createBuffer(input, 'raw');
1947
// create a byte buffer from utf8 bytes
1948
var buffer = forge.util.createBuffer(input, 'utf8');
1949

    
1950
// get the length of the buffer in bytes
1951
buffer.length();
1952
// put bytes into the buffer
1953
buffer.putBytes(bytes);
1954
// put a 32-bit integer into the buffer
1955
buffer.putInt32(10);
1956
// buffer to hex
1957
buffer.toHex();
1958
// get a copy of the bytes in the buffer
1959
bytes.bytes(/* count */);
1960
// empty this buffer and get its contents
1961
bytes.getBytes(/* count */);
1962

    
1963
// convert a forge buffer into a Node.js Buffer
1964
// make sure you specify the encoding as 'binary'
1965
var forgeBuffer = forge.util.createBuffer();
1966
var nodeBuffer = Buffer.from(forgeBuffer.getBytes(), 'binary');
1967

    
1968
// convert a Node.js Buffer into a forge buffer
1969
// make sure you specify the encoding as 'binary'
1970
var nodeBuffer = Buffer.from('CAFE', 'hex');
1971
var forgeBuffer = forge.util.createBuffer(nodeBuffer.toString('binary'));
1972

    
1973
// parse a URL
1974
var parsed = forge.util.parseUrl('http://example.com/foo?bar=baz');
1975
// parsed.scheme, parsed.host, parsed.port, parsed.path, parsed.fullHost
1976
```
1977

    
1978
<a name="log" />
1979

    
1980
### Logging
1981

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

    
1985
__Examples__
1986

    
1987
```js
1988
// TODO
1989
```
1990

    
1991
<a name="debug" />
1992

    
1993
### Debugging
1994

    
1995
Provides storage of debugging information normally inaccessible in
1996
closures for viewing/investigation.
1997

    
1998
__Examples__
1999

    
2000
```js
2001
// TODO
2002
```
2003

    
2004
<a name="flash" />
2005

    
2006
### Flash Networking Support
2007

    
2008
The [flash README](./flash/README.md) provides details on rebuilding the
2009
optional Flash component used for networking. It also provides details on
2010
Policy Server support.
2011

    
2012
Security Considerations
2013
-----------------------
2014

    
2015
When using this code please keep the following in mind:
2016

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

    
2039
Library Background
2040
------------------
2041

    
2042
* https://digitalbazaar.com/2010/07/20/javascript-tls-1/
2043
* https://digitalbazaar.com/2010/07/20/javascript-tls-2/
2044

    
2045
Contact
2046
-------
2047

    
2048
* Code: https://github.com/digitalbazaar/forge
2049
* Bugs: https://github.com/digitalbazaar/forge/issues
2050
* Email: support@digitalbazaar.com
2051
* IRC: [#forgejs][] on [freenode][]
2052

    
2053
Donations
2054
---------
2055

    
2056
Financial support is welcome and helps contribute to futher development:
2057

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

    
2061
[#forgejs]: https://webchat.freenode.net/?channels=#forgejs
2062
[0.6.x]: https://github.com/digitalbazaar/forge/tree/0.6.x
2063
[3DES]: https://en.wikipedia.org/wiki/Triple_DES
2064
[AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
2065
[ASN.1]: https://en.wikipedia.org/wiki/ASN.1
2066
[Bower]: https://bower.io/
2067
[Browserify]: http://browserify.org/
2068
[CBC]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2069
[CFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2070
[CTR]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2071
[CommonJS]: https://en.wikipedia.org/wiki/CommonJS
2072
[DES]: https://en.wikipedia.org/wiki/Data_Encryption_Standard
2073
[ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2074
[Fortuna]: https://en.wikipedia.org/wiki/Fortuna_(PRNG)
2075
[GCM]: https://en.wikipedia.org/wiki/GCM_mode
2076
[HMAC]: https://en.wikipedia.org/wiki/HMAC
2077
[JavaScript]: https://en.wikipedia.org/wiki/JavaScript
2078
[Karma]: https://karma-runner.github.io/
2079
[MD5]: https://en.wikipedia.org/wiki/MD5
2080
[Node.js]: https://nodejs.org/
2081
[OFB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
2082
[PKCS#10]: https://en.wikipedia.org/wiki/Certificate_signing_request
2083
[PKCS#12]: https://en.wikipedia.org/wiki/PKCS_%E2%99%AF12
2084
[PKCS#5]: https://en.wikipedia.org/wiki/PKCS
2085
[PKCS#7]: https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax
2086
[PayPal]: https://www.paypal.com/
2087
[RC2]: https://en.wikipedia.org/wiki/RC2
2088
[SHA-1]: https://en.wikipedia.org/wiki/SHA-1
2089
[SHA-256]: https://en.wikipedia.org/wiki/SHA-256
2090
[SHA-384]: https://en.wikipedia.org/wiki/SHA-384
2091
[SHA-512]: https://en.wikipedia.org/wiki/SHA-512
2092
[Subresource Integrity]: https://www.w3.org/TR/SRI/
2093
[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security
2094
[UMD]: https://github.com/umdjs/umd
2095
[X.509]: https://en.wikipedia.org/wiki/X.509
2096
[freenode]: https://freenode.net/
2097
[unpkg]: https://unpkg.com/
2098
[webpack]: https://webpack.github.io/
2099
[TweetNaCl.js]: https://github.com/dchest/tweetnacl-js
(3-3/4)