node-forge 0.7.1 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +163 -6
- package/dist/forge.all.min.js +1 -10
- package/dist/forge.all.min.js.map +1 -1
- package/dist/forge.min.js +1 -9
- package/dist/forge.min.js.map +1 -1
- package/dist/prime.worker.min.js +1 -1
- package/lib/asn1.js +5 -5
- package/lib/baseN.js +186 -0
- package/lib/ed25519.js +996 -0
- package/lib/form.js +1 -1
- package/lib/index.js +1 -0
- package/lib/oids.js +2 -0
- package/lib/pkcs7.js +5 -3
- package/lib/prng.js +41 -22
- package/lib/util.js +32 -13
- package/lib/x509.js +12 -0
- package/package.json +25 -20
- package/flash/package.json +0 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
Forge ChangeLog
|
|
2
2
|
===============
|
|
3
3
|
|
|
4
|
+
## 0.7.5 - 2018-03-30
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
- Remove use of `const`.
|
|
8
|
+
|
|
9
|
+
## 0.7.4 - 2018-03-07
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- Potential regex denial of service in form.js.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Support for ED25519.
|
|
16
|
+
- Support for baseN/base58.
|
|
17
|
+
|
|
18
|
+
## 0.7.3 - 2018-03-05
|
|
19
|
+
|
|
20
|
+
- Re-publish with npm 5.6.0 due to file timestamp issues.
|
|
21
|
+
|
|
22
|
+
## 0.7.2 - 2018-02-27
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Support verification of SHA-384 certificates.
|
|
26
|
+
- `1.2.840.10040.4.3'`/`dsa-with-sha1` OID.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- Support importing PKCS#7 data with no certificates. RFC 2315 sec 9.1 states
|
|
30
|
+
certificates are optional.
|
|
31
|
+
- `asn1.equals` loop bug.
|
|
32
|
+
- Fortuna implementation bugs.
|
|
33
|
+
|
|
34
|
+
## 0.7.1 - 2017-03-27
|
|
35
|
+
|
|
4
36
|
### Fixed
|
|
5
37
|
|
|
6
38
|
- Fix digestLength for hashes based on SHA-512.
|
package/README.md
CHANGED
|
@@ -53,6 +53,7 @@ Documentation
|
|
|
53
53
|
|
|
54
54
|
### PKI
|
|
55
55
|
|
|
56
|
+
* [ED25519](#ed25519)
|
|
56
57
|
* [RSA](#rsa)
|
|
57
58
|
* [RSA-KEM](#rsakem)
|
|
58
59
|
* [X.509](#x509)
|
|
@@ -132,11 +133,21 @@ with [Bower][]:
|
|
|
132
133
|
|
|
133
134
|
bower install forge
|
|
134
135
|
|
|
135
|
-
###
|
|
136
|
+
### jsDelivr CDN
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
To use it via [jsDelivr](https://www.jsdelivr.com/package/npm/node-forge) include this in your html:
|
|
138
139
|
|
|
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
|
+
```
|
|
140
151
|
|
|
141
152
|
### Development Requirements
|
|
142
153
|
|
|
@@ -285,6 +296,7 @@ API
|
|
|
285
296
|
---
|
|
286
297
|
|
|
287
298
|
<a name="options" />
|
|
299
|
+
|
|
288
300
|
### Options
|
|
289
301
|
|
|
290
302
|
If at any time you wish to disable the use of native code, where available,
|
|
@@ -313,6 +325,7 @@ Transports
|
|
|
313
325
|
----------
|
|
314
326
|
|
|
315
327
|
<a name="tls" />
|
|
328
|
+
|
|
316
329
|
### TLS
|
|
317
330
|
|
|
318
331
|
Provides a native javascript client and server-side [TLS][] implementation.
|
|
@@ -523,6 +536,7 @@ socket.connect(443, 'google.com');
|
|
|
523
536
|
```
|
|
524
537
|
|
|
525
538
|
<a name="http" />
|
|
539
|
+
|
|
526
540
|
### HTTP
|
|
527
541
|
|
|
528
542
|
Provides a native [JavaScript][] mini-implementation of an http client that
|
|
@@ -558,6 +572,7 @@ var someAsyncDataHandler = function(bytes) {
|
|
|
558
572
|
```
|
|
559
573
|
|
|
560
574
|
<a name="ssh" />
|
|
575
|
+
|
|
561
576
|
### SSH
|
|
562
577
|
|
|
563
578
|
Provides some SSH utility functions.
|
|
@@ -582,6 +597,7 @@ forge.ssh.getPublicKeyFingerprint(key, {encoding: 'hex', delimiter: ':'});
|
|
|
582
597
|
```
|
|
583
598
|
|
|
584
599
|
<a name="xhr" />
|
|
600
|
+
|
|
585
601
|
### XHR
|
|
586
602
|
|
|
587
603
|
Provides an XmlHttpRequest implementation using forge.http as a backend.
|
|
@@ -593,6 +609,7 @@ __Examples__
|
|
|
593
609
|
```
|
|
594
610
|
|
|
595
611
|
<a name="socket" />
|
|
612
|
+
|
|
596
613
|
### Sockets
|
|
597
614
|
|
|
598
615
|
Provides an interface to create and use raw sockets provided via Flash.
|
|
@@ -607,6 +624,7 @@ Ciphers
|
|
|
607
624
|
-------
|
|
608
625
|
|
|
609
626
|
<a name="cipher" />
|
|
627
|
+
|
|
610
628
|
### CIPHER
|
|
611
629
|
|
|
612
630
|
Provides a basic API for block encryption and decryption. There is built-in
|
|
@@ -660,10 +678,35 @@ console.log(encrypted.toHex());
|
|
|
660
678
|
var decipher = forge.cipher.createDecipher('AES-CBC', key);
|
|
661
679
|
decipher.start({iv: iv});
|
|
662
680
|
decipher.update(encrypted);
|
|
663
|
-
decipher.finish();
|
|
681
|
+
var result = decipher.finish(); // check 'result' for true/false
|
|
664
682
|
// outputs decrypted hex
|
|
665
683
|
console.log(decipher.output.toHex());
|
|
666
684
|
|
|
685
|
+
// decrypt bytes using CBC mode and streaming
|
|
686
|
+
// Performance can suffer for large multi-MB inputs due to buffer
|
|
687
|
+
// manipulations. Stream processing in chunks can offer significant
|
|
688
|
+
// improvement. CPU intensive update() calls could also be performed with
|
|
689
|
+
// setImmediate/setTimeout to avoid blocking the main browser UI thread (not
|
|
690
|
+
// shown here). Optimal block size depends on the JavaScript VM and other
|
|
691
|
+
// factors. Encryption can use a simple technique for increased performance.
|
|
692
|
+
var encryptedBytes = encrypted.bytes();
|
|
693
|
+
var decipher = forge.cipher.createDecipher('AES-CBC', key);
|
|
694
|
+
decipher.start({iv: iv});
|
|
695
|
+
var length = encryptedBytes.length;
|
|
696
|
+
var chunkSize = 1024 * 64;
|
|
697
|
+
var index = 0;
|
|
698
|
+
var decrypted = '';
|
|
699
|
+
do {
|
|
700
|
+
decrypted += decipher.output.getBytes();
|
|
701
|
+
var buf = forge.util.createBuffer(encryptedBytes.substr(index, chunkSize));
|
|
702
|
+
decipher.update(buf);
|
|
703
|
+
index += chunkSize;
|
|
704
|
+
} while(index < length);
|
|
705
|
+
var result = decipher.finish();
|
|
706
|
+
assert(result);
|
|
707
|
+
decrypted += decipher.output.getBytes();
|
|
708
|
+
console.log(forge.util.bytesToHex(decrypted));
|
|
709
|
+
|
|
667
710
|
// encrypt some bytes using GCM mode
|
|
668
711
|
var cipher = forge.cipher.createCipher('AES-GCM', key);
|
|
669
712
|
cipher.start({
|
|
@@ -776,18 +819,21 @@ function decrypt(password) {
|
|
|
776
819
|
```
|
|
777
820
|
|
|
778
821
|
<a name="aes" />
|
|
822
|
+
|
|
779
823
|
### AES
|
|
780
824
|
|
|
781
825
|
Provides [AES][] encryption and decryption in [CBC][], [CFB][], [OFB][],
|
|
782
826
|
[CTR][], and [GCM][] modes. See [CIPHER](#cipher) for examples.
|
|
783
827
|
|
|
784
828
|
<a name="des" />
|
|
829
|
+
|
|
785
830
|
### DES
|
|
786
831
|
|
|
787
832
|
Provides [3DES][] and [DES][] encryption and decryption in [ECB][] and
|
|
788
833
|
[CBC][] modes. See [CIPHER](#cipher) for examples.
|
|
789
834
|
|
|
790
835
|
<a name="rc2" />
|
|
836
|
+
|
|
791
837
|
### RC2
|
|
792
838
|
|
|
793
839
|
__Examples__
|
|
@@ -818,10 +864,95 @@ console.log(cipher.output.toHex());
|
|
|
818
864
|
PKI
|
|
819
865
|
---
|
|
820
866
|
|
|
821
|
-
Provides [X.509][] certificate
|
|
822
|
-
|
|
867
|
+
Provides [X.509][] certificate support, ED25519 key generation and
|
|
868
|
+
signing/verifying, and RSA public and private key encoding, decoding,
|
|
869
|
+
encryption/decryption, and signing/verifying.
|
|
870
|
+
|
|
871
|
+
<a name="ed25519" />
|
|
872
|
+
|
|
873
|
+
### ED25519
|
|
874
|
+
|
|
875
|
+
Special thanks to [TweetNaCl.js][] for providing the bulk of the implementation.
|
|
876
|
+
|
|
877
|
+
__Examples__
|
|
878
|
+
|
|
879
|
+
```js
|
|
880
|
+
var ed25519 = forge.pki.ed25519;
|
|
881
|
+
|
|
882
|
+
// generate a random ED25519 keypair
|
|
883
|
+
var keypair = ed25519.generateKeyPair();
|
|
884
|
+
// `keypair.publicKey` is a node.js Buffer or Uint8Array
|
|
885
|
+
// `keypair.privateKey` is a node.js Buffer or Uint8Array
|
|
886
|
+
|
|
887
|
+
// generate a random ED25519 keypair based on a random 32-byte seed
|
|
888
|
+
var seed = forge.random.getBytesSync(32);
|
|
889
|
+
var keypair = ed25519.generateKeyPair({seed: seed});
|
|
890
|
+
|
|
891
|
+
// generate a random ED25519 keypair based on a "password" 32-byte seed
|
|
892
|
+
var password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
|
|
893
|
+
var seed = new forge.util.ByteBuffer(password, 'utf8');
|
|
894
|
+
var keypair = ed25519.generateKeyPair({seed: seed});
|
|
895
|
+
|
|
896
|
+
// sign a UTF-8 message
|
|
897
|
+
var signature = ED25519.sign({
|
|
898
|
+
message: 'test',
|
|
899
|
+
// also accepts `binary` if you want to pass a binary string
|
|
900
|
+
encoding: 'utf8',
|
|
901
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, binary string
|
|
902
|
+
privateKey: privateKey
|
|
903
|
+
});
|
|
904
|
+
// `signature` is a node.js Buffer or Uint8Array
|
|
905
|
+
|
|
906
|
+
// sign a message passed as a buffer
|
|
907
|
+
var signature = ED25519.sign({
|
|
908
|
+
// also accepts a forge ByteBuffer or Uint8Array
|
|
909
|
+
message: new Buffer('test', 'utf8'),
|
|
910
|
+
privateKey: privateKey
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
// sign a message digest (shorter "message" == better performance)
|
|
914
|
+
var md = forge.md.sha256.create();
|
|
915
|
+
md.update('test', 'utf8');
|
|
916
|
+
var signature = ED25519.sign({
|
|
917
|
+
md: md,
|
|
918
|
+
privateKey: privateKey
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
// verify a signature on a UTF-8 message
|
|
922
|
+
var verified = ED25519.verify({
|
|
923
|
+
message: 'test',
|
|
924
|
+
encoding: 'utf8',
|
|
925
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
926
|
+
signature: signature,
|
|
927
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
928
|
+
publicKey: publicKey
|
|
929
|
+
});
|
|
930
|
+
// `verified` is true/false
|
|
931
|
+
|
|
932
|
+
// sign a message passed as a buffer
|
|
933
|
+
var verified = ED25519.verify({
|
|
934
|
+
// also accepts a forge ByteBuffer or Uint8Array
|
|
935
|
+
message: new Buffer('test', 'utf8'),
|
|
936
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
937
|
+
signature: signature,
|
|
938
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
939
|
+
publicKey: publicKey
|
|
940
|
+
});
|
|
941
|
+
|
|
942
|
+
// verify a signature on a message digest
|
|
943
|
+
var md = forge.md.sha256.create();
|
|
944
|
+
md.update('test', 'utf8');
|
|
945
|
+
var verified = ED25519.verify({
|
|
946
|
+
md: md,
|
|
947
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
948
|
+
signature: signature,
|
|
949
|
+
// node.js Buffer, Uint8Array, forge ByteBuffer, or binary string
|
|
950
|
+
publicKey: publicKey
|
|
951
|
+
});
|
|
952
|
+
```
|
|
823
953
|
|
|
824
954
|
<a name="rsa" />
|
|
955
|
+
|
|
825
956
|
### RSA
|
|
826
957
|
|
|
827
958
|
__Examples__
|
|
@@ -940,6 +1071,7 @@ var decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
|
|
|
940
1071
|
```
|
|
941
1072
|
|
|
942
1073
|
<a name="rsakem" />
|
|
1074
|
+
|
|
943
1075
|
### RSA-KEM
|
|
944
1076
|
|
|
945
1077
|
__Examples__
|
|
@@ -988,6 +1120,7 @@ if(pass) {
|
|
|
988
1120
|
```
|
|
989
1121
|
|
|
990
1122
|
<a name="x509" />
|
|
1123
|
+
|
|
991
1124
|
### X.509
|
|
992
1125
|
|
|
993
1126
|
__Examples__
|
|
@@ -1057,6 +1190,10 @@ var cert = pki.createCertificate();
|
|
|
1057
1190
|
cert.publicKey = keys.publicKey;
|
|
1058
1191
|
// alternatively set public key from a csr
|
|
1059
1192
|
//cert.publicKey = csr.publicKey;
|
|
1193
|
+
// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
|
|
1194
|
+
// Conforming CAs should ensure serialNumber is:
|
|
1195
|
+
// - no more than 20 octets
|
|
1196
|
+
// - non-negative (prefix a '00' if your value starts with a '1' bit)
|
|
1060
1197
|
cert.serialNumber = '01';
|
|
1061
1198
|
cert.validity.notBefore = new Date();
|
|
1062
1199
|
cert.validity.notAfter = new Date();
|
|
@@ -1155,6 +1292,7 @@ var asn1Cert = pki.certificateToAsn1(cert);
|
|
|
1155
1292
|
```
|
|
1156
1293
|
|
|
1157
1294
|
<a name="pkcs5" />
|
|
1295
|
+
|
|
1158
1296
|
### PKCS#5
|
|
1159
1297
|
|
|
1160
1298
|
Provides the password-based key-derivation function from [PKCS#5][].
|
|
@@ -1175,6 +1313,7 @@ forge.pkcs5.pbkdf2('password', salt, numIterations, 16, function(err, derivedKey
|
|
|
1175
1313
|
```
|
|
1176
1314
|
|
|
1177
1315
|
<a name="pkcs7" />
|
|
1316
|
+
|
|
1178
1317
|
### PKCS#7
|
|
1179
1318
|
|
|
1180
1319
|
Provides cryptographically protected messages from [PKCS#7][].
|
|
@@ -1242,6 +1381,7 @@ var pem = forge.pkcs7.messageToPem(p7);
|
|
|
1242
1381
|
```
|
|
1243
1382
|
|
|
1244
1383
|
<a name="pkcs8" />
|
|
1384
|
+
|
|
1245
1385
|
### PKCS#8
|
|
1246
1386
|
|
|
1247
1387
|
__Examples__
|
|
@@ -1298,6 +1438,7 @@ var publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e);
|
|
|
1298
1438
|
```
|
|
1299
1439
|
|
|
1300
1440
|
<a name="pkcs10" />
|
|
1441
|
+
|
|
1301
1442
|
### PKCS#10
|
|
1302
1443
|
|
|
1303
1444
|
Provides certification requests or certificate signing requests (CSR) from
|
|
@@ -1377,6 +1518,7 @@ csr.getAttribute({name: 'extensionRequest'}).extensions;
|
|
|
1377
1518
|
```
|
|
1378
1519
|
|
|
1379
1520
|
<a name="pkcs12" />
|
|
1521
|
+
|
|
1380
1522
|
### PKCS#12
|
|
1381
1523
|
|
|
1382
1524
|
Provides the cryptographic archive file format from [PKCS#12][].
|
|
@@ -1468,6 +1610,7 @@ a.appendChild(document.createTextNode('Download'));
|
|
|
1468
1610
|
```
|
|
1469
1611
|
|
|
1470
1612
|
<a name="asn" />
|
|
1613
|
+
|
|
1471
1614
|
### ASN.1
|
|
1472
1615
|
|
|
1473
1616
|
Provides [ASN.1][] DER encoding and decoding.
|
|
@@ -1575,6 +1718,7 @@ Message Digests
|
|
|
1575
1718
|
----------------
|
|
1576
1719
|
|
|
1577
1720
|
<a name="sha1" />
|
|
1721
|
+
|
|
1578
1722
|
### SHA1
|
|
1579
1723
|
|
|
1580
1724
|
Provides [SHA-1][] message digests.
|
|
@@ -1589,6 +1733,7 @@ console.log(md.digest().toHex());
|
|
|
1589
1733
|
```
|
|
1590
1734
|
|
|
1591
1735
|
<a name="sha256" />
|
|
1736
|
+
|
|
1592
1737
|
### SHA256
|
|
1593
1738
|
|
|
1594
1739
|
Provides [SHA-256][] message digests.
|
|
@@ -1603,6 +1748,7 @@ console.log(md.digest().toHex());
|
|
|
1603
1748
|
```
|
|
1604
1749
|
|
|
1605
1750
|
<a name="sha384" />
|
|
1751
|
+
|
|
1606
1752
|
### SHA384
|
|
1607
1753
|
|
|
1608
1754
|
Provides [SHA-384][] message digests.
|
|
@@ -1617,6 +1763,7 @@ console.log(md.digest().toHex());
|
|
|
1617
1763
|
```
|
|
1618
1764
|
|
|
1619
1765
|
<a name="sha512" />
|
|
1766
|
+
|
|
1620
1767
|
### SHA512
|
|
1621
1768
|
|
|
1622
1769
|
Provides [SHA-512][] message digests.
|
|
@@ -1644,6 +1791,7 @@ console.log(md.digest().toHex());
|
|
|
1644
1791
|
```
|
|
1645
1792
|
|
|
1646
1793
|
<a name="md5" />
|
|
1794
|
+
|
|
1647
1795
|
### MD5
|
|
1648
1796
|
|
|
1649
1797
|
Provides [MD5][] message digests.
|
|
@@ -1658,6 +1806,7 @@ console.log(md.digest().toHex());
|
|
|
1658
1806
|
```
|
|
1659
1807
|
|
|
1660
1808
|
<a name="hmac" />
|
|
1809
|
+
|
|
1661
1810
|
### HMAC
|
|
1662
1811
|
|
|
1663
1812
|
Provides [HMAC][] w/any supported message digest algorithm.
|
|
@@ -1676,6 +1825,7 @@ Utilities
|
|
|
1676
1825
|
---------
|
|
1677
1826
|
|
|
1678
1827
|
<a name="prime" />
|
|
1828
|
+
|
|
1679
1829
|
### Prime
|
|
1680
1830
|
|
|
1681
1831
|
Provides an API for generating large, random, probable primes.
|
|
@@ -1704,6 +1854,7 @@ forge.prime.generateProbablePrime(bits, options, function(err, num) {
|
|
|
1704
1854
|
```
|
|
1705
1855
|
|
|
1706
1856
|
<a name="prng" />
|
|
1857
|
+
|
|
1707
1858
|
### PRNG
|
|
1708
1859
|
|
|
1709
1860
|
Provides a [Fortuna][]-based cryptographically-secure pseudo-random number
|
|
@@ -1752,6 +1903,7 @@ var myPrng = forge.random.createInstance();
|
|
|
1752
1903
|
```
|
|
1753
1904
|
|
|
1754
1905
|
<a name="task" />
|
|
1906
|
+
|
|
1755
1907
|
### Tasks
|
|
1756
1908
|
|
|
1757
1909
|
Provides queuing and synchronizing tasks in a web application.
|
|
@@ -1763,6 +1915,7 @@ __Examples__
|
|
|
1763
1915
|
```
|
|
1764
1916
|
|
|
1765
1917
|
<a name="util" />
|
|
1918
|
+
|
|
1766
1919
|
### Utilities
|
|
1767
1920
|
|
|
1768
1921
|
Provides utility functions, including byte buffer support, base64,
|
|
@@ -1819,6 +1972,7 @@ var parsed = forge.util.parseUrl('http://example.com/foo?bar=baz');
|
|
|
1819
1972
|
```
|
|
1820
1973
|
|
|
1821
1974
|
<a name="log" />
|
|
1975
|
+
|
|
1822
1976
|
### Logging
|
|
1823
1977
|
|
|
1824
1978
|
Provides logging to a javascript console using various categories and
|
|
@@ -1831,6 +1985,7 @@ __Examples__
|
|
|
1831
1985
|
```
|
|
1832
1986
|
|
|
1833
1987
|
<a name="debug" />
|
|
1988
|
+
|
|
1834
1989
|
### Debugging
|
|
1835
1990
|
|
|
1836
1991
|
Provides storage of debugging information normally inaccessible in
|
|
@@ -1843,6 +1998,7 @@ __Examples__
|
|
|
1843
1998
|
```
|
|
1844
1999
|
|
|
1845
2000
|
<a name="flash" />
|
|
2001
|
+
|
|
1846
2002
|
### Flash Networking Support
|
|
1847
2003
|
|
|
1848
2004
|
The [flash README](./flash/README.md) provides details on rebuilding the
|
|
@@ -1936,3 +2092,4 @@ Financial support is welcome and helps contribute to futher development:
|
|
|
1936
2092
|
[freenode]: https://freenode.net/
|
|
1937
2093
|
[unpkg]: https://unpkg.com/
|
|
1938
2094
|
[webpack]: https://webpack.github.io/
|
|
2095
|
+
[TweetNaCl]: https://github.com/dchest/tweetnacl-js
|