node-forge 0.8.3 → 0.9.1

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.
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Copyright (c) 2019 Digital Bazaar, Inc.
3
+ */
4
+
5
+ var forge = require('./forge');
6
+ require('./asn1');
7
+ var asn1 = forge.asn1;
8
+
9
+ exports.privateKeyValidator = {
10
+ // PrivateKeyInfo
11
+ name: 'PrivateKeyInfo',
12
+ tagClass: asn1.Class.UNIVERSAL,
13
+ type: asn1.Type.SEQUENCE,
14
+ constructed: true,
15
+ value: [{
16
+ // Version (INTEGER)
17
+ name: 'PrivateKeyInfo.version',
18
+ tagClass: asn1.Class.UNIVERSAL,
19
+ type: asn1.Type.INTEGER,
20
+ constructed: false,
21
+ capture: 'privateKeyVersion'
22
+ }, {
23
+ // privateKeyAlgorithm
24
+ name: 'PrivateKeyInfo.privateKeyAlgorithm',
25
+ tagClass: asn1.Class.UNIVERSAL,
26
+ type: asn1.Type.SEQUENCE,
27
+ constructed: true,
28
+ value: [{
29
+ name: 'AlgorithmIdentifier.algorithm',
30
+ tagClass: asn1.Class.UNIVERSAL,
31
+ type: asn1.Type.OID,
32
+ constructed: false,
33
+ capture: 'privateKeyOid'
34
+ }]
35
+ }, {
36
+ // PrivateKey
37
+ name: 'PrivateKeyInfo',
38
+ tagClass: asn1.Class.UNIVERSAL,
39
+ type: asn1.Type.OCTETSTRING,
40
+ constructed: false,
41
+ capture: 'privateKey'
42
+ }]
43
+ };
44
+
45
+ exports.publicKeyValidator = {
46
+ name: 'SubjectPublicKeyInfo',
47
+ tagClass: asn1.Class.UNIVERSAL,
48
+ type: asn1.Type.SEQUENCE,
49
+ constructed: true,
50
+ captureAsn1: 'subjectPublicKeyInfo',
51
+ value: [{
52
+ name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',
53
+ tagClass: asn1.Class.UNIVERSAL,
54
+ type: asn1.Type.SEQUENCE,
55
+ constructed: true,
56
+ value: [{
57
+ name: 'AlgorithmIdentifier.algorithm',
58
+ tagClass: asn1.Class.UNIVERSAL,
59
+ type: asn1.Type.OID,
60
+ constructed: false,
61
+ capture: 'publicKeyOid'
62
+ }]
63
+ },
64
+ // capture group for ed25519PublicKey
65
+ {
66
+ tagClass: asn1.Class.UNIVERSAL,
67
+ type: asn1.Type.BITSTRING,
68
+ constructed: false,
69
+ composed: true,
70
+ captureBitStringValue: 'ed25519PublicKey'
71
+ }
72
+ // FIXME: this is capture group for rsaPublicKey, use it in this API or
73
+ // discard?
74
+ /* {
75
+ // subjectPublicKey
76
+ name: 'SubjectPublicKeyInfo.subjectPublicKey',
77
+ tagClass: asn1.Class.UNIVERSAL,
78
+ type: asn1.Type.BITSTRING,
79
+ constructed: false,
80
+ value: [{
81
+ // RSAPublicKey
82
+ name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',
83
+ tagClass: asn1.Class.UNIVERSAL,
84
+ type: asn1.Type.SEQUENCE,
85
+ constructed: true,
86
+ optional: true,
87
+ captureAsn1: 'rsaPublicKey'
88
+ }]
89
+ } */
90
+ ]
91
+ };
package/lib/asn1.js CHANGED
@@ -619,7 +619,7 @@ function _fromDer(bytes, remaining, depth, options) {
619
619
  }
620
620
 
621
621
  // add BIT STRING contents if available
622
- var asn1Options = bitStringContents === undefined ? null : {
622
+ var asn1Options = bitStringContents === undefined ? null : {
623
623
  bitStringContents: bitStringContents
624
624
  };
625
625
 
@@ -119,7 +119,7 @@ modes.cbc.prototype.start = function(options) {
119
119
  throw new Error('Invalid IV parameter.');
120
120
  } else {
121
121
  // save IV as "previous" block
122
- this._iv = transformIV(options.iv);
122
+ this._iv = transformIV(options.iv, this.blockSize);
123
123
  this._prev = this._iv.slice(0);
124
124
  }
125
125
  };
@@ -215,7 +215,7 @@ modes.cfb.prototype.start = function(options) {
215
215
  throw new Error('Invalid IV parameter.');
216
216
  }
217
217
  // use IV as first input
218
- this._iv = transformIV(options.iv);
218
+ this._iv = transformIV(options.iv, this.blockSize);
219
219
  this._inBlock = this._iv.slice(0);
220
220
  this._partialBytes = 0;
221
221
  };
@@ -359,7 +359,7 @@ modes.ofb.prototype.start = function(options) {
359
359
  throw new Error('Invalid IV parameter.');
360
360
  }
361
361
  // use IV as first input
362
- this._iv = transformIV(options.iv);
362
+ this._iv = transformIV(options.iv, this.blockSize);
363
363
  this._inBlock = this._iv.slice(0);
364
364
  this._partialBytes = 0;
365
365
  };
@@ -444,7 +444,7 @@ modes.ctr.prototype.start = function(options) {
444
444
  throw new Error('Invalid IV parameter.');
445
445
  }
446
446
  // use IV as first input
447
- this._iv = transformIV(options.iv);
447
+ this._iv = transformIV(options.iv, this.blockSize);
448
448
  this._inBlock = this._iv.slice(0);
449
449
  this._partialBytes = 0;
450
450
  };
@@ -954,7 +954,7 @@ modes.gcm.prototype.generateSubHashTable = function(mid, bits) {
954
954
 
955
955
  /** Utility functions */
956
956
 
957
- function transformIV(iv) {
957
+ function transformIV(iv, blockSize) {
958
958
  if(typeof iv === 'string') {
959
959
  // convert iv string into byte buffer
960
960
  iv = forge.util.createBuffer(iv);
@@ -968,9 +968,21 @@ function transformIV(iv) {
968
968
  iv.putByte(tmp[i]);
969
969
  }
970
970
  }
971
+
972
+ if(iv.length() < blockSize) {
973
+ throw new Error(
974
+ 'Invalid IV length; got ' + iv.length() +
975
+ ' bytes and expected ' + blockSize + ' bytes.');
976
+ }
977
+
971
978
  if(!forge.util.isArray(iv)) {
972
979
  // convert iv byte buffer into 32-bit integer array
973
- iv = [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()];
980
+ var ints = [];
981
+ var blocks = blockSize / 4;
982
+ for(var i = 0; i < blocks; ++i) {
983
+ ints.push(iv.getInt32());
984
+ }
985
+ iv = ints;
974
986
  }
975
987
 
976
988
  return iv;
package/lib/ed25519.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * JavaScript implementation of Ed25519.
3
3
  *
4
- * Copyright (c) 2017-2018 Digital Bazaar, Inc.
4
+ * Copyright (c) 2017-2019 Digital Bazaar, Inc.
5
5
  *
6
6
  * This implementation is based on the most excellent TweetNaCl which is
7
7
  * in the public domain. Many thanks to its contributors:
@@ -13,6 +13,9 @@ require('./jsbn');
13
13
  require('./random');
14
14
  require('./sha512');
15
15
  require('./util');
16
+ var asn1Validator = require('./asn1-validator');
17
+ var publicKeyValidator = asn1Validator.publicKeyValidator;
18
+ var privateKeyValidator = asn1Validator.privateKeyValidator;
16
19
 
17
20
  if(typeof BigInteger === 'undefined') {
18
21
  var BigInteger = forge.jsbn.BigInteger;
@@ -64,6 +67,75 @@ ed25519.generateKeyPair = function(options) {
64
67
  return {publicKey: pk, privateKey: sk};
65
68
  };
66
69
 
70
+ /**
71
+ * Converts a private key from a RFC8410 ASN.1 encoding.
72
+ *
73
+ * @param obj - The asn1 representation of a private key.
74
+ *
75
+ * @returns {Object} keyInfo - The key information.
76
+ * @returns {Buffer|Uint8Array} keyInfo.privateKeyBytes - 32 private key bytes.
77
+ */
78
+ ed25519.privateKeyFromAsn1 = function(obj) {
79
+ var capture = {};
80
+ var errors = [];
81
+ var valid = forge.asn1.validate(obj, privateKeyValidator, capture, errors);
82
+ if(!valid) {
83
+ var error = new Error('Invalid Key.');
84
+ error.errors = errors;
85
+ throw error;
86
+ }
87
+ var oid = forge.asn1.derToOid(capture.privateKeyOid);
88
+ var ed25519Oid = forge.oids.EdDSA25519;
89
+ if(oid !== ed25519Oid) {
90
+ throw new Error('Invalid OID "' + oid + '"; OID must be "' +
91
+ ed25519Oid + '".');
92
+ }
93
+ var privateKey = capture.privateKey;
94
+ // manually extract the private key bytes from nested octet string, see FIXME:
95
+ // https://github.com/digitalbazaar/forge/blob/master/lib/asn1.js#L542
96
+ var privateKeyBytes = messageToNativeBuffer({
97
+ message: forge.asn1.fromDer(privateKey).value,
98
+ encoding: 'binary'
99
+ });
100
+ // TODO: RFC8410 specifies a format for encoding the public key bytes along
101
+ // with the private key bytes. `publicKeyBytes` can be returned in the
102
+ // future. https://tools.ietf.org/html/rfc8410#section-10.3
103
+ return {privateKeyBytes: privateKeyBytes};
104
+ };
105
+
106
+ /**
107
+ * Converts a public key from a RFC8410 ASN.1 encoding.
108
+ *
109
+ * @param obj - The asn1 representation of a public key.
110
+ *
111
+ * @return {Buffer|Uint8Array} - 32 public key bytes.
112
+ */
113
+ ed25519.publicKeyFromAsn1 = function(obj) {
114
+ // get SubjectPublicKeyInfo
115
+ var capture = {};
116
+ var errors = [];
117
+ var valid = forge.asn1.validate(obj, publicKeyValidator, capture, errors);
118
+ if(!valid) {
119
+ var error = new Error('Invalid Key.');
120
+ error.errors = errors;
121
+ throw error;
122
+ }
123
+ var oid = forge.asn1.derToOid(capture.publicKeyOid);
124
+ var ed25519Oid = forge.oids.EdDSA25519;
125
+ if(oid !== ed25519Oid) {
126
+ throw new Error('Invalid OID "' + oid + '"; OID must be "' +
127
+ ed25519Oid + '".');
128
+ }
129
+ var publicKeyBytes = capture.ed25519PublicKey;
130
+ if(publicKeyBytes.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) {
131
+ throw new Error('Key length is invalid.');
132
+ }
133
+ return messageToNativeBuffer({
134
+ message: publicKeyBytes,
135
+ encoding: 'binary'
136
+ });
137
+ };
138
+
67
139
  ed25519.publicKeyFromPrivateKey = function(options) {
68
140
  options = options || {};
69
141
  var privateKey = messageToNativeBuffer({
@@ -89,9 +161,13 @@ ed25519.sign = function(options) {
89
161
  message: options.privateKey,
90
162
  encoding: 'binary'
91
163
  });
92
- if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
164
+ if(privateKey.length === ed25519.constants.SEED_BYTE_LENGTH) {
165
+ var keyPair = ed25519.generateKeyPair({seed: privateKey});
166
+ privateKey = keyPair.privateKey;
167
+ } else if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
93
168
  throw new TypeError(
94
169
  '"options.privateKey" must have a byte length of ' +
170
+ ed25519.constants.SEED_BYTE_LENGTH + ' or ' +
95
171
  ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
96
172
  }
97
173
 
@@ -147,7 +223,7 @@ ed25519.verify = function(options) {
147
223
 
148
224
  function messageToNativeBuffer(options) {
149
225
  var message = options.message;
150
- if(message instanceof Uint8Array) {
226
+ if(message instanceof Uint8Array || message instanceof NativeBuffer) {
151
227
  return message;
152
228
  }
153
229
 
@@ -168,7 +244,7 @@ function messageToNativeBuffer(options) {
168
244
 
169
245
  if(typeof message === 'string') {
170
246
  if(typeof Buffer !== 'undefined') {
171
- return new Buffer(message, encoding);
247
+ return Buffer.from(message, encoding);
172
248
  }
173
249
  message = new ByteBuffer(message, encoding);
174
250
  } else if(!(message instanceof ByteBuffer)) {
@@ -217,7 +293,7 @@ function sha512(msg, msgLen) {
217
293
  md.update(buffer.getBytes(msgLen), 'binary');
218
294
  var hash = md.digest().getBytes();
219
295
  if(typeof Buffer !== 'undefined') {
220
- return new Buffer(hash, 'binary');
296
+ return Buffer.from(hash, 'binary');
221
297
  }
222
298
  var out = new NativeBuffer(ed25519.constants.HASH_BYTE_LENGTH);
223
299
  for(var i = 0; i < 64; ++i) {
package/lib/oids.js CHANGED
@@ -34,6 +34,8 @@ _IN('1.2.840.113549.1.1.10', 'RSASSA-PSS');
34
34
  _IN('1.2.840.113549.1.1.11', 'sha256WithRSAEncryption');
35
35
  _IN('1.2.840.113549.1.1.12', 'sha384WithRSAEncryption');
36
36
  _IN('1.2.840.113549.1.1.13', 'sha512WithRSAEncryption');
37
+ // Edwards-curve Digital Signature Algorithm (EdDSA) Ed25519
38
+ _IN('1.3.101.112', 'EdDSA25519');
37
39
 
38
40
  _IN('1.2.840.10040.4.3', 'dsa-with-sha1');
39
41
 
@@ -106,9 +108,14 @@ _IN('2.5.4.5', 'serialName');
106
108
  _IN('2.5.4.6', 'countryName');
107
109
  _IN('2.5.4.7', 'localityName');
108
110
  _IN('2.5.4.8', 'stateOrProvinceName');
111
+ _IN('2.5.4.9', 'streetAddress');
109
112
  _IN('2.5.4.10', 'organizationName');
110
113
  _IN('2.5.4.11', 'organizationalUnitName');
111
114
  _IN('2.5.4.13', 'description');
115
+ _IN('2.5.4.15', 'businessCategory');
116
+ _IN('2.5.4.17', 'postalCode');
117
+ _IN('1.3.6.1.4.1.311.60.2.1.2', 'jurisdictionOfIncorporationStateOrProvinceName');
118
+ _IN('1.3.6.1.4.1.311.60.2.1.3', 'jurisdictionOfIncorporationCountryName');
112
119
 
113
120
  // X.509 extension OIDs
114
121
  _IN('2.16.840.1.113730.1.1', 'nsCertType');
package/lib/pbkdf2.js CHANGED
@@ -51,8 +51,8 @@ module.exports = forge.pbkdf2 = pkcs5.pbkdf2 = function(
51
51
  // default prf to SHA-1
52
52
  md = 'sha1';
53
53
  }
54
- p = new Buffer(p, 'binary');
55
- s = new Buffer(s, 'binary');
54
+ p = Buffer.from(p, 'binary');
55
+ s = Buffer.from(s, 'binary');
56
56
  if(!callback) {
57
57
  if(crypto.pbkdf2Sync.length === 4) {
58
58
  return crypto.pbkdf2Sync(p, s, c, dkLen).toString('binary');
package/lib/util.js CHANGED
@@ -279,7 +279,7 @@ util.ByteStringBuffer.prototype.fillWithByte = function(b, n) {
279
279
  /**
280
280
  * Puts bytes in this buffer.
281
281
  *
282
- * @param bytes the bytes (as a UTF-8 encoded string) to put.
282
+ * @param bytes the bytes (as a binary encoded string) to put.
283
283
  *
284
284
  * @return this buffer.
285
285
  */
@@ -567,11 +567,13 @@ util.ByteStringBuffer.prototype.getSignedInt = function(n) {
567
567
  };
568
568
 
569
569
  /**
570
- * Reads bytes out into a UTF-8 string and clears them from the buffer.
570
+ * Reads bytes out as a binary encoded string and clears them from the
571
+ * buffer. Note that the resulting string is binary encoded (in node.js this
572
+ * encoding is referred to as `binary`, it is *not* `utf8`).
571
573
  *
572
574
  * @param count the number of bytes to read, undefined or null for all.
573
575
  *
574
- * @return a UTF-8 string of bytes.
576
+ * @return a binary encoded string of bytes.
575
577
  */
576
578
  util.ByteStringBuffer.prototype.getBytes = function(count) {
577
579
  var rval;
@@ -591,12 +593,12 @@ util.ByteStringBuffer.prototype.getBytes = function(count) {
591
593
  };
592
594
 
593
595
  /**
594
- * Gets a UTF-8 encoded string of the bytes from this buffer without modifying
595
- * the read pointer.
596
+ * Gets a binary encoded string of the bytes from this buffer without
597
+ * modifying the read pointer.
596
598
  *
597
599
  * @param count the number of bytes to get, omit to get all.
598
600
  *
599
- * @return a string full of UTF-8 encoded characters.
601
+ * @return a string full of binary encoded characters.
600
602
  */
601
603
  util.ByteStringBuffer.prototype.bytes = function(count) {
602
604
  return (typeof(count) === 'undefined' ?
@@ -1228,11 +1230,12 @@ util.DataBuffer.prototype.getSignedInt = function(n) {
1228
1230
  };
1229
1231
 
1230
1232
  /**
1231
- * Reads bytes out into a UTF-8 string and clears them from the buffer.
1233
+ * Reads bytes out as a binary encoded string and clears them from the
1234
+ * buffer.
1232
1235
  *
1233
1236
  * @param count the number of bytes to read, undefined or null for all.
1234
1237
  *
1235
- * @return a UTF-8 string of bytes.
1238
+ * @return a binary encoded string of bytes.
1236
1239
  */
1237
1240
  util.DataBuffer.prototype.getBytes = function(count) {
1238
1241
  // TODO: deprecate this method, it is poorly named and
@@ -1255,12 +1258,12 @@ util.DataBuffer.prototype.getBytes = function(count) {
1255
1258
  };
1256
1259
 
1257
1260
  /**
1258
- * Gets a UTF-8 encoded string of the bytes from this buffer without modifying
1259
- * the read pointer.
1261
+ * Gets a binary encoded string of the bytes from this buffer without
1262
+ * modifying the read pointer.
1260
1263
  *
1261
1264
  * @param count the number of bytes to get, omit to get all.
1262
1265
  *
1263
- * @return a string full of UTF-8 encoded characters.
1266
+ * @return a string full of binary encoded characters.
1264
1267
  */
1265
1268
  util.DataBuffer.prototype.bytes = function(count) {
1266
1269
  // TODO: deprecate this method, it is poorly named, add "getString()"
@@ -1407,12 +1410,13 @@ util.DataBuffer.prototype.toString = function(encoding) {
1407
1410
  /** End Buffer w/UInt8Array backing */
1408
1411
 
1409
1412
  /**
1410
- * Creates a buffer that stores bytes. A value may be given to put into the
1411
- * buffer that is either a string of bytes or a UTF-16 string that will
1412
- * be encoded using UTF-8 (to do the latter, specify 'utf8' as the encoding).
1413
+ * Creates a buffer that stores bytes. A value may be given to populate the
1414
+ * buffer with data. This value can either be string of encoded bytes or a
1415
+ * regular string of characters. When passing a string of binary encoded
1416
+ * bytes, the encoding `raw` should be given. This is also the default. When
1417
+ * passing a string of characters, the encoding `utf8` should be given.
1413
1418
  *
1414
- * @param [input] the bytes to wrap (as a string) or a UTF-16 string to encode
1415
- * as UTF-8.
1419
+ * @param [input] a string with encoded bytes to store in the buffer.
1416
1420
  * @param [encoding] (default: 'raw', other: 'utf8').
1417
1421
  */
1418
1422
  util.createBuffer = function(input, encoding) {
@@ -1641,24 +1645,27 @@ util.decode64 = function(input) {
1641
1645
  };
1642
1646
 
1643
1647
  /**
1644
- * UTF-8 encodes the given UTF-16 encoded string (a standard JavaScript
1645
- * string). Non-ASCII characters will be encoded as multiple bytes according
1646
- * to UTF-8.
1648
+ * Encodes the given string of characters (a standard JavaScript
1649
+ * string) as a binary encoded string where the bytes represent
1650
+ * a UTF-8 encoded string of characters. Non-ASCII characters will be
1651
+ * encoded as multiple bytes according to UTF-8.
1647
1652
  *
1648
- * @param str the string to encode.
1653
+ * @param str a standard string of characters to encode.
1649
1654
  *
1650
- * @return the UTF-8 encoded string.
1655
+ * @return the binary encoded string.
1651
1656
  */
1652
1657
  util.encodeUtf8 = function(str) {
1653
1658
  return unescape(encodeURIComponent(str));
1654
1659
  };
1655
1660
 
1656
1661
  /**
1657
- * Decodes a UTF-8 encoded string into a UTF-16 string.
1662
+ * Decodes a binary encoded string that contains bytes that
1663
+ * represent a UTF-8 encoded string of characters -- into a
1664
+ * string of characters (a standard JavaScript string).
1658
1665
  *
1659
- * @param str the string to decode.
1666
+ * @param str the binary encoded string to decode.
1660
1667
  *
1661
- * @return the UTF-16 encoded string (standard JavaScript string).
1668
+ * @return the resulting standard string of characters.
1662
1669
  */
1663
1670
  util.decodeUtf8 = function(str) {
1664
1671
  return decodeURIComponent(escape(str));
package/lib/x509.js CHANGED
@@ -2482,8 +2482,8 @@ function _CRIAttributesToAsn1(csr) {
2482
2482
  return rval;
2483
2483
  }
2484
2484
 
2485
- const jan_1_1950 = new Date('1950-01-01T00:00:00Z');
2486
- const jan_1_2050 = new Date('2050-01-01T00:00:00Z');
2485
+ var jan_1_1950 = new Date('1950-01-01T00:00:00Z');
2486
+ var jan_1_2050 = new Date('2050-01-01T00:00:00Z');
2487
2487
 
2488
2488
  /**
2489
2489
  * Converts a Date object to ASN.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-forge",
3
- "version": "0.8.3",
3
+ "version": "0.9.1",
4
4
  "description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
5
5
  "homepage": "https://github.com/digitalbazaar/forge",
6
6
  "author": {
@@ -59,7 +59,7 @@
59
59
  "dist/*.min.js.map"
60
60
  ],
61
61
  "engines": {
62
- "node": "*"
62
+ "node": ">= 4.5.0"
63
63
  },
64
64
  "keywords": [
65
65
  "aes",