node-forge 0.6.34 → 0.6.39

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/.travis.yml CHANGED
@@ -2,7 +2,11 @@ language: node_js
2
2
  node_js:
3
3
  - "0.10"
4
4
  - "0.12"
5
- - iojs
5
+ - "4.0"
6
+ - "4.2"
7
+ - "node"
8
+ - "iojs"
9
+ sudo: false
6
10
  install: (cd nodejs && npm install)
7
11
  script:
8
12
  - (cd nodejs && npm test)
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Forge
2
2
 
3
- [![Build Status][travis-ci-png]][travis-ci-site]
4
- [travis-ci-png]: https://travis-ci.org/digitalbazaar/forge.png?branch=master
5
- [travis-ci-site]: https://travis-ci.org/digitalbazaar/forge
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
6
 
7
7
  A native implementation of [TLS][] (and various other cryptographic tools) in
8
8
  [JavaScript][].
package/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge",
3
- "version": "0.6.34",
3
+ "version": "0.6.39",
4
4
  "description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
5
5
  "moduleType": ["amd"],
6
6
  "authors": [
package/js/md5.js CHANGED
@@ -41,8 +41,10 @@ md5.create = function() {
41
41
  digestLength: 16,
42
42
  // 56-bit length of message so far (does not including padding)
43
43
  messageLength: 0,
44
- // true 64-bit message length as two 32-bit ints
45
- messageLength64: [0, 0]
44
+ // true message length
45
+ fullMessageLength: null,
46
+ // size of message length in bytes
47
+ messageLengthSize: 8
46
48
  };
47
49
 
48
50
  /**
@@ -51,8 +53,15 @@ md5.create = function() {
51
53
  * @return this digest object.
52
54
  */
53
55
  md.start = function() {
56
+ // up to 56-bit message length for convenience
54
57
  md.messageLength = 0;
55
- md.messageLength64 = [0, 0];
58
+
59
+ // full message length (set md.messageLength64 for backwards-compatibility)
60
+ md.fullMessageLength = md.messageLength64 = [];
61
+ var int32s = md.messageLengthSize / 4;
62
+ for(var i = 0; i < int32s; ++i) {
63
+ md.fullMessageLength.push(0);
64
+ }
56
65
  _input = forge.util.createBuffer();
57
66
  _state = {
58
67
  h0: 0x67452301,
@@ -81,9 +90,15 @@ md5.create = function() {
81
90
  }
82
91
 
83
92
  // update message length
84
- md.messageLength += msg.length;
85
- md.messageLength64[0] += (msg.length / 0x100000000) >>> 0;
86
- md.messageLength64[1] += msg.length >>> 0;
93
+ var len = msg.length;
94
+ md.messageLength += len;
95
+ len = [(len / 0x100000000) >>> 0, len >>> 0];
96
+ for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
97
+ md.fullMessageLength[i] += len[1];
98
+ len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
99
+ md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
100
+ len[0] = ((len[1] / 0x100000000) >>> 0);
101
+ }
87
102
 
88
103
  // add bytes to input buffer
89
104
  _input.putBytes(msg);
@@ -125,28 +140,36 @@ md5.create = function() {
125
140
  must *always* be present, so if the message length is already
126
141
  congruent to 448 mod 512, then 512 padding bits must be added. */
127
142
 
128
- // 512 bits == 64 bytes, 448 bits == 56 bytes, 64 bits = 8 bytes
129
- // _padding starts with 1 byte with first bit is set in it which
130
- // is byte value 128, then there may be up to 63 other pad bytes
131
- var padBytes = forge.util.createBuffer();
132
- padBytes.putBytes(_input.bytes());
133
- // 64 - (remaining msg + 8 bytes msg length) mod 64
134
- padBytes.putBytes(
135
- _padding.substr(0, 64 - ((md.messageLength64[1] + 8) & 0x3F)));
136
-
137
- /* Now append length of the message. The length is appended in bits
138
- as a 64-bit number in little-endian order. Since we store the length in
139
- bytes, we must multiply the 64-bit length by 8 (or left shift by 3). */
140
- padBytes.putInt32Le(md.messageLength64[1] << 3);
141
- padBytes.putInt32Le(
142
- (md.messageLength64[0] << 3) | (md.messageLength64[0] >>> 28));
143
+ var finalBlock = forge.util.createBuffer();
144
+ finalBlock.putBytes(_input.bytes());
145
+
146
+ // compute remaining size to be digested (include message length size)
147
+ var remaining = (
148
+ md.fullMessageLength[md.fullMessageLength.length - 1] +
149
+ md.messageLengthSize);
150
+
151
+ // add padding for overflow blockSize - overflow
152
+ // _padding starts with 1 byte with first bit is set (byte value 128), then
153
+ // there may be up to (blockSize - 1) other pad bytes
154
+ var overflow = remaining & (md.blockLength - 1);
155
+ finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
156
+
157
+ // serialize message length in bits in little-endian order; since length
158
+ // is stored in bytes we multiply by 8 and add carry
159
+ var bits, carry = 0;
160
+ for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
161
+ bits = md.fullMessageLength[i] * 8 + carry;
162
+ carry = (bits / 0x100000000) >>> 0;
163
+ finalBlock.putInt32Le(bits >>> 0);
164
+ }
165
+
143
166
  var s2 = {
144
167
  h0: _state.h0,
145
168
  h1: _state.h1,
146
169
  h2: _state.h2,
147
170
  h3: _state.h3
148
171
  };
149
- _update(s2, _w, padBytes);
172
+ _update(s2, _w, finalBlock);
150
173
  var rval = forge.util.createBuffer();
151
174
  rval.putInt32Le(s2.h0);
152
175
  rval.putInt32Le(s2.h1);
package/js/oids.js CHANGED
@@ -196,6 +196,7 @@ oids['2.5.29.32'] = 'certificatePolicies';
196
196
  oids['2.5.29.33'] = 'policyMappings';
197
197
  oids['2.5.29.34'] = 'policyConstraints'; // deprecated use .36
198
198
  oids['2.5.29.35'] = 'authorityKeyIdentifier';
199
+ oids['authorityKeyIdentifier'] = '2.5.29.35';
199
200
  oids['2.5.29.36'] = 'policyConstraints';
200
201
  oids['2.5.29.37'] = 'extKeyUsage';
201
202
  oids['extKeyUsage'] = '2.5.29.37';
package/js/rsa.js CHANGED
@@ -407,9 +407,11 @@ var _modPow = function(x, key, pub) {
407
407
  so we add p until this is true (since we will be mod'ing with
408
408
  p anyway). Then, there is a known timing attack on algorithms
409
409
  using the CRT. To mitigate this risk, "cryptographic blinding"
410
- should be used. This requires simply generating a random number r between
411
- 0 and n-1 and its inverse and multiplying x by r^e before calculating y
412
- and then multiplying y by r^-1 afterwards.
410
+ should be used. This requires simply generating a random number r
411
+ between 0 and n-1 and its inverse and multiplying x by r^e before
412
+ calculating y and then multiplying y by r^-1 afterwards. Note that
413
+ r must be coprime with n (gcd(r, n) === 1) in order to have an
414
+ inverse.
413
415
  */
414
416
 
415
417
  // cryptographic blinding
@@ -417,8 +419,8 @@ var _modPow = function(x, key, pub) {
417
419
  do {
418
420
  r = new BigInteger(
419
421
  forge.util.bytesToHex(forge.random.getBytes(key.n.bitLength() / 8)),
420
- 16).mod(key.n);
421
- } while(r.equals(BigInteger.ZERO));
422
+ 16);
423
+ } while(r.compareTo(key.n) >= 0 || !r.gcd(key.n).equals(BigInteger.ONE));
422
424
  x = x.multiply(r.modPow(key.e, key.n)).mod(key.n);
423
425
 
424
426
  // calculate xp and xq
package/js/sha1.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @author Dave Longley
5
5
  *
6
- * Copyright (c) 2010-2014 Digital Bazaar, Inc.
6
+ * Copyright (c) 2010-2015 Digital Bazaar, Inc.
7
7
  */
8
8
  (function() {
9
9
  /* ########## Begin module implementation ########## */
@@ -41,8 +41,10 @@ sha1.create = function() {
41
41
  digestLength: 20,
42
42
  // 56-bit length of message so far (does not including padding)
43
43
  messageLength: 0,
44
- // true 64-bit message length as two 32-bit ints
45
- messageLength64: [0, 0]
44
+ // true message length
45
+ fullMessageLength: null,
46
+ // size of message length in bytes
47
+ messageLengthSize: 8
46
48
  };
47
49
 
48
50
  /**
@@ -51,8 +53,15 @@ sha1.create = function() {
51
53
  * @return this digest object.
52
54
  */
53
55
  md.start = function() {
56
+ // up to 56-bit message length for convenience
54
57
  md.messageLength = 0;
55
- md.messageLength64 = [0, 0];
58
+
59
+ // full message length (set md.messageLength64 for backwards-compatibility)
60
+ md.fullMessageLength = md.messageLength64 = [];
61
+ var int32s = md.messageLengthSize / 4;
62
+ for(var i = 0; i < int32s; ++i) {
63
+ md.fullMessageLength.push(0);
64
+ }
56
65
  _input = forge.util.createBuffer();
57
66
  _state = {
58
67
  h0: 0x67452301,
@@ -82,9 +91,15 @@ sha1.create = function() {
82
91
  }
83
92
 
84
93
  // update message length
85
- md.messageLength += msg.length;
86
- md.messageLength64[0] += (msg.length / 0x100000000) >>> 0;
87
- md.messageLength64[1] += msg.length >>> 0;
94
+ var len = msg.length;
95
+ md.messageLength += len;
96
+ len = [(len / 0x100000000) >>> 0, len >>> 0];
97
+ for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
98
+ md.fullMessageLength[i] += len[1];
99
+ len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
100
+ md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
101
+ len[0] = ((len[1] / 0x100000000) >>> 0);
102
+ }
88
103
 
89
104
  // add bytes to input buffer
90
105
  _input.putBytes(msg);
@@ -126,21 +141,33 @@ sha1.create = function() {
126
141
  must *always* be present, so if the message length is already
127
142
  congruent to 448 mod 512, then 512 padding bits must be added. */
128
143
 
129
- // 512 bits == 64 bytes, 448 bits == 56 bytes, 64 bits = 8 bytes
130
- // _padding starts with 1 byte with first bit is set in it which
131
- // is byte value 128, then there may be up to 63 other pad bytes
132
- var padBytes = forge.util.createBuffer();
133
- padBytes.putBytes(_input.bytes());
134
- // 64 - (remaining msg + 8 bytes msg length) mod 64
135
- padBytes.putBytes(
136
- _padding.substr(0, 64 - ((md.messageLength64[1] + 8) & 0x3F)));
137
-
138
- /* Now append length of the message. The length is appended in bits
139
- as a 64-bit number in big-endian order. Since we store the length in
140
- bytes, we must multiply the 64-bit length by 8 (or left shift by 3). */
141
- padBytes.putInt32(
142
- (md.messageLength64[0] << 3) | (md.messageLength64[0] >>> 28));
143
- padBytes.putInt32(md.messageLength64[1] << 3);
144
+ var finalBlock = forge.util.createBuffer();
145
+ finalBlock.putBytes(_input.bytes());
146
+
147
+ // compute remaining size to be digested (include message length size)
148
+ var remaining = (
149
+ md.fullMessageLength[md.fullMessageLength.length - 1] +
150
+ md.messageLengthSize);
151
+
152
+ // add padding for overflow blockSize - overflow
153
+ // _padding starts with 1 byte with first bit is set (byte value 128), then
154
+ // there may be up to (blockSize - 1) other pad bytes
155
+ var overflow = remaining & (md.blockLength - 1);
156
+ finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
157
+
158
+ // serialize message length in bits in big-endian order; since length
159
+ // is stored in bytes we multiply by 8 and add carry from next int
160
+ var messageLength = forge.util.createBuffer();
161
+ var next, carry;
162
+ var bits = md.fullMessageLength[0] * 8;
163
+ for(var i = 0; i < md.fullMessageLength.length; ++i) {
164
+ next = md.fullMessageLength[i + 1] * 8;
165
+ carry = (next / 0x100000000) >>> 0;
166
+ bits += carry;
167
+ finalBlock.putInt32(bits >>> 0);
168
+ bits = next;
169
+ }
170
+
144
171
  var s2 = {
145
172
  h0: _state.h0,
146
173
  h1: _state.h1,
@@ -148,7 +175,7 @@ sha1.create = function() {
148
175
  h3: _state.h3,
149
176
  h4: _state.h4
150
177
  };
151
- _update(s2, _w, padBytes);
178
+ _update(s2, _w, finalBlock);
152
179
  var rval = forge.util.createBuffer();
153
180
  rval.putInt32(s2.h0);
154
181
  rval.putInt32(s2.h1);
package/js/sha256.js CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @author Dave Longley
7
7
  *
8
- * Copyright (c) 2010-2014 Digital Bazaar, Inc.
8
+ * Copyright (c) 2010-2015 Digital Bazaar, Inc.
9
9
  */
10
10
  (function() {
11
11
  /* ########## Begin module implementation ########## */
@@ -43,8 +43,10 @@ sha256.create = function() {
43
43
  digestLength: 32,
44
44
  // 56-bit length of message so far (does not including padding)
45
45
  messageLength: 0,
46
- // true 64-bit message length as two 32-bit ints
47
- messageLength64: [0, 0]
46
+ // true message length
47
+ fullMessageLength: null,
48
+ // size of message length in bytes
49
+ messageLengthSize: 8
48
50
  };
49
51
 
50
52
  /**
@@ -53,8 +55,15 @@ sha256.create = function() {
53
55
  * @return this digest object.
54
56
  */
55
57
  md.start = function() {
58
+ // up to 56-bit message length for convenience
56
59
  md.messageLength = 0;
57
- md.messageLength64 = [0, 0];
60
+
61
+ // full message length (set md.messageLength64 for backwards-compatibility)
62
+ md.fullMessageLength = md.messageLength64 = [];
63
+ var int32s = md.messageLengthSize / 4;
64
+ for(var i = 0; i < int32s; ++i) {
65
+ md.fullMessageLength.push(0);
66
+ }
58
67
  _input = forge.util.createBuffer();
59
68
  _state = {
60
69
  h0: 0x6A09E667,
@@ -87,9 +96,15 @@ sha256.create = function() {
87
96
  }
88
97
 
89
98
  // update message length
90
- md.messageLength += msg.length;
91
- md.messageLength64[0] += (msg.length / 0x100000000) >>> 0;
92
- md.messageLength64[1] += msg.length >>> 0;
99
+ var len = msg.length;
100
+ md.messageLength += len;
101
+ len = [(len / 0x100000000) >>> 0, len >>> 0];
102
+ for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
103
+ md.fullMessageLength[i] += len[1];
104
+ len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
105
+ md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
106
+ len[0] = ((len[1] / 0x100000000) >>> 0);
107
+ }
93
108
 
94
109
  // add bytes to input buffer
95
110
  _input.putBytes(msg);
@@ -131,21 +146,33 @@ sha256.create = function() {
131
146
  must *always* be present, so if the message length is already
132
147
  congruent to 448 mod 512, then 512 padding bits must be added. */
133
148
 
134
- // 512 bits == 64 bytes, 448 bits == 56 bytes, 64 bits = 8 bytes
135
- // _padding starts with 1 byte with first bit is set in it which
136
- // is byte value 128, then there may be up to 63 other pad bytes
137
- var padBytes = forge.util.createBuffer();
138
- padBytes.putBytes(_input.bytes());
139
- // 64 - (remaining msg + 8 bytes msg length) mod 64
140
- padBytes.putBytes(
141
- _padding.substr(0, 64 - ((md.messageLength64[1] + 8) & 0x3F)));
142
-
143
- /* Now append length of the message. The length is appended in bits
144
- as a 64-bit number in big-endian order. Since we store the length in
145
- bytes, we must multiply the 64-bit length by 8 (or left shift by 3). */
146
- padBytes.putInt32(
147
- (md.messageLength64[0] << 3) | (md.messageLength64[0] >>> 28));
148
- padBytes.putInt32(md.messageLength64[1] << 3);
149
+ var finalBlock = forge.util.createBuffer();
150
+ finalBlock.putBytes(_input.bytes());
151
+
152
+ // compute remaining size to be digested (include message length size)
153
+ var remaining = (
154
+ md.fullMessageLength[md.fullMessageLength.length - 1] +
155
+ md.messageLengthSize);
156
+
157
+ // add padding for overflow blockSize - overflow
158
+ // _padding starts with 1 byte with first bit is set (byte value 128), then
159
+ // there may be up to (blockSize - 1) other pad bytes
160
+ var overflow = remaining & (md.blockLength - 1);
161
+ finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
162
+
163
+ // serialize message length in bits in big-endian order; since length
164
+ // is stored in bytes we multiply by 8 and add carry from next int
165
+ var messageLength = forge.util.createBuffer();
166
+ var next, carry;
167
+ var bits = md.fullMessageLength[0] * 8;
168
+ for(var i = 0; i < md.fullMessageLength.length; ++i) {
169
+ next = md.fullMessageLength[i + 1] * 8;
170
+ carry = (next / 0x100000000) >>> 0;
171
+ bits += carry;
172
+ finalBlock.putInt32(bits >>> 0);
173
+ bits = next;
174
+ }
175
+
149
176
  var s2 = {
150
177
  h0: _state.h0,
151
178
  h1: _state.h1,
@@ -156,7 +183,7 @@ sha256.create = function() {
156
183
  h6: _state.h6,
157
184
  h7: _state.h7
158
185
  };
159
- _update(s2, _w, padBytes);
186
+ _update(s2, _w, finalBlock);
160
187
  var rval = forge.util.createBuffer();
161
188
  rval.putInt32(s2.h0);
162
189
  rval.putInt32(s2.h1);
package/js/sha512.js CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @author Dave Longley
10
10
  *
11
- * Copyright (c) 2014 Digital Bazaar, Inc.
11
+ * Copyright (c) 2014-2015 Digital Bazaar, Inc.
12
12
  */
13
13
  (function() {
14
14
  /* ########## Begin module implementation ########## */
@@ -89,8 +89,10 @@ sha512.create = function(algorithm) {
89
89
  digestLength: 64,
90
90
  // 56-bit length of message so far (does not including padding)
91
91
  messageLength: 0,
92
- // true 128-bit message length as four 32-bit ints
93
- messageLength128: [0, 0, 0, 0]
92
+ // true message length
93
+ fullMessageLength: null,
94
+ // size of message length in bytes
95
+ messageLengthSize: 16
94
96
  };
95
97
 
96
98
  /**
@@ -99,8 +101,15 @@ sha512.create = function(algorithm) {
99
101
  * @return this digest object.
100
102
  */
101
103
  md.start = function() {
104
+ // up to 56-bit message length for convenience
102
105
  md.messageLength = 0;
103
- md.messageLength128 = [0, 0, 0, 0];
106
+
107
+ // full message length (set md.messageLength128 for backwards-compatibility)
108
+ md.fullMessageLength = md.messageLength128 = [];
109
+ var int32s = md.messageLengthSize / 4;
110
+ for(var i = 0; i < int32s; ++i) {
111
+ md.fullMessageLength.push(0);
112
+ }
104
113
  _input = forge.util.createBuffer();
105
114
  _h = new Array(_state.length);
106
115
  for(var i = 0; i < _state.length; ++i) {
@@ -127,13 +136,13 @@ sha512.create = function(algorithm) {
127
136
  }
128
137
 
129
138
  // update message length
130
- md.messageLength += msg.length;
131
139
  var len = msg.length;
140
+ md.messageLength += len;
132
141
  len = [(len / 0x100000000) >>> 0, len >>> 0];
133
- for(var i = 3; i >= 0; --i) {
134
- md.messageLength128[i] += len[1];
135
- len[1] = len[0] + ((md.messageLength128[i] / 0x100000000) >>> 0);
136
- md.messageLength128[i] = md.messageLength128[i] >>> 0;
142
+ for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
143
+ md.fullMessageLength[i] += len[1];
144
+ len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
145
+ md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
137
146
  len[0] = ((len[1] / 0x100000000) >>> 0);
138
147
  }
139
148
 
@@ -177,34 +186,38 @@ sha512.create = function(algorithm) {
177
186
  must *always* be present, so if the message length is already
178
187
  congruent to 896 mod 1024, then 1024 padding bits must be added. */
179
188
 
180
- // 1024 bits == 128 bytes, 896 bits == 112 bytes, 128 bits = 16 bytes
181
- // _padding starts with 1 byte with first bit is set in it which
182
- // is byte value 128, then there may be up to 127 other pad bytes
183
- var padBytes = forge.util.createBuffer();
184
- padBytes.putBytes(_input.bytes());
185
- // 128 - (remaining msg + 16 bytes msg length) mod 128
186
- padBytes.putBytes(
187
- _padding.substr(0, 128 - ((md.messageLength128[3] + 16) & 0x7F)));
188
-
189
- /* Now append length of the message. The length is appended in bits
190
- as a 128-bit number in big-endian order. Since we store the length in
191
- bytes, we must multiply the 128-bit length by 8 (or left shift by 3). */
192
- var bitLength = [];
193
- for(var i = 0; i < 3; ++i) {
194
- bitLength[i] = ((md.messageLength128[i] << 3) |
195
- (md.messageLength128[i - 1] >>> 28));
189
+ var finalBlock = forge.util.createBuffer();
190
+ finalBlock.putBytes(_input.bytes());
191
+
192
+ // compute remaining size to be digested (include message length size)
193
+ var remaining = (
194
+ md.fullMessageLength[md.fullMessageLength.length - 1] +
195
+ md.messageLengthSize);
196
+
197
+ // add padding for overflow blockSize - overflow
198
+ // _padding starts with 1 byte with first bit is set (byte value 128), then
199
+ // there may be up to (blockSize - 1) other pad bytes
200
+ var overflow = remaining & (md.blockLength - 1);
201
+ finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
202
+
203
+ // serialize message length in bits in big-endian order; since length
204
+ // is stored in bytes we multiply by 8 and add carry from next int
205
+ var messageLength = forge.util.createBuffer();
206
+ var next, carry;
207
+ var bits = md.fullMessageLength[0] * 8;
208
+ for(var i = 0; i < md.fullMessageLength.length; ++i) {
209
+ next = md.fullMessageLength[i + 1] * 8;
210
+ carry = (next / 0x100000000) >>> 0;
211
+ bits += carry;
212
+ finalBlock.putInt32(bits >>> 0);
213
+ bits = next;
196
214
  }
197
- // shift the last integer normally
198
- bitLength[3] = md.messageLength128[3] << 3;
199
- padBytes.putInt32(bitLength[0]);
200
- padBytes.putInt32(bitLength[1]);
201
- padBytes.putInt32(bitLength[2]);
202
- padBytes.putInt32(bitLength[3]);
215
+
203
216
  var h = new Array(_h.length);
204
217
  for(var i = 0; i < _h.length; ++i) {
205
218
  h[i] = _h[i].slice(0);
206
219
  }
207
- _update(h, _w, padBytes);
220
+ _update(h, _w, finalBlock);
208
221
  var rval = forge.util.createBuffer();
209
222
  var hlen;
210
223
  if(algorithm === 'SHA-512') {
package/js/util.js CHANGED
@@ -1838,9 +1838,9 @@ util.text.utf8.decode = function(bytes) {
1838
1838
  util.text.utf16.encode = function(str, output, offset) {
1839
1839
  var out = output;
1840
1840
  if(!out) {
1841
- out = new Uint8Array(str.length);
1841
+ out = new Uint8Array(str.length * 2);
1842
1842
  }
1843
- var view = new Uint16Array(out);
1843
+ var view = new Uint16Array(out.buffer);
1844
1844
  offset = offset || 0;
1845
1845
  var j = offset;
1846
1846
  var k = offset;
@@ -1859,7 +1859,7 @@ util.text.utf16.encode = function(str, output, offset) {
1859
1859
  * @return the resulting string.
1860
1860
  */
1861
1861
  util.text.utf16.decode = function(bytes) {
1862
- return String.fromCharCode.apply(null, new Uint16Array(bytes));
1862
+ return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer));
1863
1863
  };
1864
1864
 
1865
1865
  /**
package/js/x509.js CHANGED
@@ -1073,6 +1073,9 @@ pki.createCertificate = function() {
1073
1073
  case 'sha256WithRSAEncryption':
1074
1074
  md = forge.md.sha256.create();
1075
1075
  break;
1076
+ case 'sha512WithRSAEncryption':
1077
+ md = forge.md.sha512.create();
1078
+ break;
1076
1079
  case 'RSASSA-PSS':
1077
1080
  md = forge.md.sha256.create();
1078
1081
  break;
@@ -1337,6 +1340,9 @@ pki.certificateFromAsn1 = function(obj, computeHash) {
1337
1340
  case 'sha256WithRSAEncryption':
1338
1341
  cert.md = forge.md.sha256.create();
1339
1342
  break;
1343
+ case 'sha512WithRSAEncryption':
1344
+ cert.md = forge.md.sha512.create();
1345
+ break;
1340
1346
  case 'RSASSA-PSS':
1341
1347
  cert.md = forge.md.sha256.create();
1342
1348
  break;
@@ -1687,6 +1693,9 @@ pki.certificationRequestFromAsn1 = function(obj, computeHash) {
1687
1693
  case 'sha256WithRSAEncryption':
1688
1694
  csr.md = forge.md.sha256.create();
1689
1695
  break;
1696
+ case 'sha512WithRSAEncryption':
1697
+ csr.md = forge.md.sha512.create();
1698
+ break;
1690
1699
  case 'RSASSA-PSS':
1691
1700
  csr.md = forge.md.sha256.create();
1692
1701
  break;
@@ -1839,6 +1848,7 @@ pki.createCertificationRequest = function() {
1839
1848
  if(md === null) {
1840
1849
  // check signature OID for supported signature types
1841
1850
  if(csr.signatureOid in oids) {
1851
+ // TODO: create DRY `OID to md` function
1842
1852
  var oid = oids[csr.signatureOid];
1843
1853
  switch(oid) {
1844
1854
  case 'sha1WithRSAEncryption':
@@ -1850,6 +1860,9 @@ pki.createCertificationRequest = function() {
1850
1860
  case 'sha256WithRSAEncryption':
1851
1861
  md = forge.md.sha256.create();
1852
1862
  break;
1863
+ case 'sha512WithRSAEncryption':
1864
+ md = forge.md.sha512.create();
1865
+ break;
1853
1866
  case 'RSASSA-PSS':
1854
1867
  md = forge.md.sha256.create();
1855
1868
  break;
@@ -2265,6 +2278,36 @@ function _fillMissingExtensionFields(e, options) {
2265
2278
  // OCTETSTRING w/digest
2266
2279
  e.value = asn1.create(
2267
2280
  asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, ski.getBytes());
2281
+ } else if(e.name === 'authorityKeyIdentifier' && options.cert) {
2282
+ // SYNTAX SEQUENCE
2283
+ e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2284
+ var seq = e.value.value;
2285
+
2286
+ if(e.keyIdentifier) {
2287
+ var keyIdentifier = (e.keyIdentifier === true ?
2288
+ options.cert.generateSubjectKeyIdentifier().getBytes() :
2289
+ e.keyIdentifier);
2290
+ seq.push(
2291
+ asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier));
2292
+ }
2293
+
2294
+ if(e.authorityCertIssuer) {
2295
+ var authorityCertIssuer = [
2296
+ asn1.create(asn1.Class.CONTEXT_SPECIFIC, 4, true, [
2297
+ _dnToAsn1(e.authorityCertIssuer === true ?
2298
+ options.cert.issuer : e.authorityCertIssuer)
2299
+ ])
2300
+ ];
2301
+ seq.push(
2302
+ asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer));
2303
+ }
2304
+
2305
+ if(e.serialNumber) {
2306
+ var serialNumber = forge.util.hexToBytes(e.serialNumber === true ?
2307
+ options.cert.serialNumber : e.serialNumber);
2308
+ seq.push(
2309
+ asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber));
2310
+ }
2268
2311
  }
2269
2312
 
2270
2313
  // ensure value has been defined by now
@@ -382,6 +382,115 @@ function Tests(ASSERT, UTIL) {
382
382
  var addr = UTIL.bytesToIP(bytes);
383
383
  ASSERT.equal(addr, '2001:db8:0:1:1:1:1:1');
384
384
  });
385
+
386
+ it('should convert "foo" to its UTF-8 representation', function() {
387
+ if(typeof Uint8Array === 'undefined') {
388
+ return;
389
+ }
390
+ var result = UTIL.text.utf8.encode('foo');
391
+ ASSERT.equal(result.byteLength, 3);
392
+ ASSERT.equal(result[0], 102);
393
+ ASSERT.equal(result[1], 111);
394
+ ASSERT.equal(result[2], 111);
395
+ });
396
+
397
+ it('should convert "foo" from its UTF-8 representation', function() {
398
+ if(typeof Uint8Array === 'undefined') {
399
+ return;
400
+ }
401
+ var bytes = new Uint8Array([102, 111, 111]);
402
+ // FIXME: remove try/catch once phantomjs supports apply(TypedArray)
403
+ // or a fallback is implemented
404
+ try {
405
+ var result = UTIL.text.utf8.decode(bytes);
406
+ ASSERT.equal(result, 'foo');
407
+ } catch(e) {
408
+ ASSERT.isTrue(e instanceof TypeError);
409
+ }
410
+ });
411
+
412
+ it('should convert "\ud83c\udc00" to its UTF-8 representation', function() {
413
+ if(typeof Uint8Array === 'undefined') {
414
+ return;
415
+ }
416
+ var result = UTIL.text.utf8.encode('\ud83c\udc00');
417
+ ASSERT.equal(result.byteLength, 4);
418
+ ASSERT.equal(result[0], 240);
419
+ ASSERT.equal(result[1], 159);
420
+ ASSERT.equal(result[2], 128);
421
+ ASSERT.equal(result[3], 128);
422
+ });
423
+
424
+ it('should convert "\ud83c\udc00" from its UTF-8 representation', function() {
425
+ if(typeof Uint8Array === 'undefined') {
426
+ return;
427
+ }
428
+ var bytes = new Uint8Array([240, 159, 128, 128]);
429
+ // FIXME: remove try/catch once phantomjs supports apply(TypedArray)
430
+ // or a fallback is implemented
431
+ try {
432
+ var result = UTIL.text.utf8.decode(bytes);
433
+ ASSERT.equal(result, '\ud83c\udc00');
434
+ } catch(e) {
435
+ ASSERT.isTrue(e instanceof TypeError);
436
+ }
437
+ });
438
+
439
+ it('should convert "foo" to its UTF-16 representation', function() {
440
+ if(typeof Uint8Array === 'undefined') {
441
+ return;
442
+ }
443
+ var result = UTIL.text.utf16.encode('foo');
444
+ ASSERT.equal(result.byteLength, 6);
445
+ ASSERT.equal(result[0], 102);
446
+ ASSERT.equal(result[1], 0);
447
+ ASSERT.equal(result[2], 111);
448
+ ASSERT.equal(result[3], 0);
449
+ ASSERT.equal(result[4], 111);
450
+ ASSERT.equal(result[5], 0);
451
+ });
452
+
453
+ it('should convert "foo" from its UTF-16 representation', function() {
454
+ if(typeof Uint8Array === 'undefined') {
455
+ return;
456
+ }
457
+ var bytes = new Uint8Array([102, 0, 111, 0, 111, 0]);
458
+ // FIXME: remove try/catch once phantomjs supports apply(TypedArray)
459
+ // or a fallback is implemented
460
+ try {
461
+ var result = UTIL.text.utf16.decode(bytes);
462
+ ASSERT.equal(result, 'foo');
463
+ } catch(e) {
464
+ ASSERT.isTrue(e instanceof TypeError);
465
+ }
466
+ });
467
+
468
+ it('should convert "\ud83c\udc00" to its UTF-16 representation', function() {
469
+ if(typeof Uint8Array === 'undefined') {
470
+ return;
471
+ }
472
+ var result = UTIL.text.utf16.encode('\ud83c\udc00');
473
+ ASSERT.equal(result.byteLength, 4);
474
+ ASSERT.equal(result[0], 60);
475
+ ASSERT.equal(result[1], 216);
476
+ ASSERT.equal(result[2], 0);
477
+ ASSERT.equal(result[3], 220);
478
+ });
479
+
480
+ it('should convert "\ud83c\udc00" from its UTF-16 representation', function() {
481
+ if(typeof Uint8Array === 'undefined') {
482
+ return;
483
+ }
484
+ var bytes = new Uint8Array([60, 216, 0, 220]);
485
+ // FIXME: remove try/catch once phantomjs supports apply(TypedArray)
486
+ // or a fallback is implemented
487
+ try {
488
+ var result = UTIL.text.utf16.decode(bytes);
489
+ ASSERT.equal(result, '\ud83c\udc00');
490
+ } catch(e) {
491
+ ASSERT.isTrue(e instanceof TypeError);
492
+ }
493
+ });
385
494
  });
386
495
  }
387
496
 
@@ -44,17 +44,229 @@ function Tests(ASSERT, PKI, MD, UTIL) {
44
44
  '-----END CERTIFICATE-----\r\n'
45
45
  };
46
46
 
47
+ var _pem_sha256 = {
48
+ privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
49
+ 'MIIEpAIBAAKCAQEAgqu7/2ntXa9rzqiUvDD2swStK8w7MFtha/OiwzEDJng7mZUs\r\n' +
50
+ 'uy7Neqh5S1Z+nWq7NP51ol//tnNCrWM6VozrJKTAEC2qj3k+bMWnjuTU7sTJHpoZ\r\n' +
51
+ '9wdCqS9q7oOJhqwBxS7M9l8LNA+6I4Qj1bY1g2XeZsxEjJfCvILa3yBzztL3CxSF\r\n' +
52
+ 'R36FoOo9IpzYlVcE9mqTdJgTwR43ZsFNCRAkfSqJjLKy1A2+aDxUcrom2OrLSITI\r\n' +
53
+ 'CWqz5R1hFIIIB0aprjpz5F2MunciUAhTjUqrQPCtw17wmwmaeXZsu0zoq9P/VtKE\r\n' +
54
+ 'AxtQkS4tqgnodBzmmgM8YemjkJAVHQzkH8jiGQIDAQABAoIBAQAMuYiPMNOKogCP\r\n' +
55
+ 'mV8SjHoZqMTsVPEWnm94QbuB4o35+w9iv2IhwEcGQM2/BmdCERi16mmuLEcMj2DY\r\n' +
56
+ '3abastJbOSfy61+GpTntAbp1cddCgStMrZkFs1FMhG+XVnvX/3wUpaAUBeFjanyn\r\n' +
57
+ '5MBQmXPQneTwgcfTIRw3m06RF+nvI/ssIz6oHTDTTwRanTa64KYCww/fcX0XCLGw\r\n' +
58
+ 'D4GYaRrBLvglp27omQCLuCBp1Dedwx5+JRnybyQm1ZYVJ0kirD/qVDRJqQN6z2N/\r\n' +
59
+ '3XmvOc6yNnzNQwKDlFFs6VxLG/i/sv+TekiPIP2LIQ1V/0ojUJriRdPAe/dhER5E\r\n' +
60
+ 'ku2n+k75AoGBAPDUZNyqPqFTUaLj6mdTEIvLbG0Dx0/EZTalUohFUBpJSxSUuNIS\r\n' +
61
+ '6z+2dohTO5qj6Mv1JpXqXEWmRQisBl8ibizD5KJkgQW0EptmJf5BU9bnqYllgjZj\r\n' +
62
+ 'jJsBixFFcwbFUwD4vg7NjYrxEv2Wjv8II0rVNbEh61F35vMNdmgMsu0TAoGBAIrm\r\n' +
63
+ '7NbFDDBWREyFZKZdVhTo2AR8JyWuWdOO7EFbv+mzHy7TkgscwYlV4yeU/+TG6KLG\r\n' +
64
+ 'WPo5AX2mWL/zI2Zjd2Quw002e6Y9ZIO8CUK8iocrvhNy+Bfli2XyjYZxRIILQeKX\r\n' +
65
+ 'ID/h+gyzViKOXFclbUkubnm/kEGwWO8hRQvh/TWjAoGAUwbGZxUCVpfk8yVkMI8A\r\n' +
66
+ 'i1FsZgEBe8yXoElKtNRAk29lRQko1rPTCrobD1CyodOUdIxl6xVLDnAOKLk10SKL\r\n' +
67
+ 'nT9D2YCQwqicKZsDyi43e0WOu2GVjK6xUNctXJz21QS+Yv1eeLgA7j/Cbk6zqdTi\r\n' +
68
+ 'ZfAvfIvXFtUhd/XSNnj6TqUCgYBKGrE4U6ARGbUObgwohZsrRJ4apnHsNHxP1exN\r\n' +
69
+ 'Yjmc4Kc+QDmmHA1Uy7GIqIFs+IGcdd16gXc+JcUrgvfb5C0KEbi4NNz67730WhlG\r\n' +
70
+ 'tXfibX/WuHuLpDceiKzgkQVPq9nWnXHjIxhYNkU54mF5TMplRJRD9+NqaD7KNSG1\r\n' +
71
+ 'GTgRqQKBgQCSJ2W29p2uOrl+OcogFMSfZYkwJsKR25S/c7BAvsH7dVdtqSdBsRg2\r\n' +
72
+ 'zWEwWAGyd7BJsZd0gVCea9CHfZYwDoCC4nA7sRFVLAqWfRsmrALORIiXHBYD6SrL\r\n' +
73
+ 'H1G4nr6HK6/Ur0WTQQmwyz1Yw+ZhyShVRo+9NN2a3gA1n25wP3n6gQ==\r\n' +
74
+ '-----END RSA PRIVATE KEY-----\r\n',
75
+ publicKey: '-----BEGIN PUBLIC KEY-----\r\n' +
76
+ 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgqu7/2ntXa9rzqiUvDD2\r\n' +
77
+ 'swStK8w7MFtha/OiwzEDJng7mZUsuy7Neqh5S1Z+nWq7NP51ol//tnNCrWM6Vozr\r\n' +
78
+ 'JKTAEC2qj3k+bMWnjuTU7sTJHpoZ9wdCqS9q7oOJhqwBxS7M9l8LNA+6I4Qj1bY1\r\n' +
79
+ 'g2XeZsxEjJfCvILa3yBzztL3CxSFR36FoOo9IpzYlVcE9mqTdJgTwR43ZsFNCRAk\r\n' +
80
+ 'fSqJjLKy1A2+aDxUcrom2OrLSITICWqz5R1hFIIIB0aprjpz5F2MunciUAhTjUqr\r\n' +
81
+ 'QPCtw17wmwmaeXZsu0zoq9P/VtKEAxtQkS4tqgnodBzmmgM8YemjkJAVHQzkH8ji\r\n' +
82
+ 'GQIDAQAB\r\n' +
83
+ '-----END PUBLIC KEY-----\r\n',
84
+ certificate: '-----BEGIN CERTIFICATE-----\r\n' +
85
+ 'MIIECTCCAvGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBpMRQwEgYDVQQDEwtleGFt\r\n' +
86
+ 'cGxlLm9yZzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYDVQQH\r\n' +
87
+ 'EwpCbGFja3NidXJnMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MB4XDTE1\r\n' +
88
+ 'MTAwOTE3NTc1NloXDTE2MTAwOTE3NTc1NlowaTEUMBIGA1UEAxMLZXhhbXBsZS5v\r\n' +
89
+ 'cmcxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxh\r\n' +
90
+ 'Y2tzYnVyZzENMAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDCCASIwDQYJKoZI\r\n' +
91
+ 'hvcNAQEBBQADggEPADCCAQoCggEBAIKru/9p7V2va86olLww9rMErSvMOzBbYWvz\r\n' +
92
+ 'osMxAyZ4O5mVLLsuzXqoeUtWfp1quzT+daJf/7ZzQq1jOlaM6ySkwBAtqo95PmzF\r\n' +
93
+ 'p47k1O7EyR6aGfcHQqkvau6DiYasAcUuzPZfCzQPuiOEI9W2NYNl3mbMRIyXwryC\r\n' +
94
+ '2t8gc87S9wsUhUd+haDqPSKc2JVXBPZqk3SYE8EeN2bBTQkQJH0qiYyystQNvmg8\r\n' +
95
+ 'VHK6Jtjqy0iEyAlqs+UdYRSCCAdGqa46c+RdjLp3IlAIU41Kq0DwrcNe8JsJmnl2\r\n' +
96
+ 'bLtM6KvT/1bShAMbUJEuLaoJ6HQc5poDPGHpo5CQFR0M5B/I4hkCAwEAAaOBuzCB\r\n' +
97
+ 'uDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIC9DA7BgNVHSUENDAyBggrBgEFBQcD\r\n' +
98
+ 'AQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwEQYJYIZI\r\n' +
99
+ 'AYb4QgEBBAQDAgD3MCwGA1UdEQQlMCOGG2h0dHA6Ly9leGFtcGxlLm9yZy93ZWJp\r\n' +
100
+ 'ZCNtZYcEfwAAATAdBgNVHQ4EFgQUyX839dHHD+pAfU9F5t/rpQaq3LQwDQYJKoZI\r\n' +
101
+ 'hvcNAQELBQADggEBAGfr9yMwTXoHbZAj/8bRCfKUUg/xIbQY0RtuDwGKBnzVcz7r\r\n' +
102
+ 'NpocyEBUFvlbsXK4Dwpql41nYPwEpmm486gpWDqSBB0p0jF3HNHihKhCcR0LDQLt\r\n' +
103
+ 'hBP7SbX76uL4cHoJkbAVbc4FGARCkE7eVZ0sBWUPmLqVh2JmzlC3geq7Obs7HCvq\r\n' +
104
+ 'eStorsBlDZt27/N+xhvxdUTGJgiTBxk6BrRLGxUeor9TLRpZ2wsoMSnkIcQyooZ4\r\n' +
105
+ 'iGAZsqUyanWODz0o6R02kSpTA3zx6LssLuLdnxfi1EmHMSM27Lxuw308XzirTxM2\r\n' +
106
+ '/N0H5AwUc057+HoygLPfddxOfxHGXz4VmEKMcJ8=\r\n' +
107
+ '-----END CERTIFICATE-----\r\n'
108
+ };
109
+
110
+ var _pem_sha512 = {
111
+ privateKey: '-----BEGIN RSA PRIVATE KEY-----\r\n' +
112
+ 'MIIEowIBAAKCAQEAmy+xwQpZMYkMWHhw+kh2TDGbG+AF1w6BFVQ6CduEjUzD5d/j\r\n' +
113
+ 'URtkaeb0RO/uba+J92DMgJJLWlcTe5FpQMb2lxOrNoYP+suWnNxU7QD5vQ4OiJ+i\r\n' +
114
+ '3nTMly9LMB3BEEea2ZJRpVboJxRBeGl6pKz4obFfoFxqtSww38Cw8h5Nplt+LXR/\r\n' +
115
+ 'wq8yCpmN9hTE4CSw8iioIqxOZem3sz4//jcMHJ5/aiTjXwseE8eWjaVfvpDESuwQ\r\n' +
116
+ 'MNjfJYYP0onzEZmTtztyAspsyf0GZBjd1ew2nVCY0cCkQ1+tqYk7H9rjlj1PxduC\r\n' +
117
+ 'a4aGVKZjIBFnZXhCE23znOgVt9PxFMPUrmHwqwIDAQABAoIBAC68UWMak7wIUxB9\r\n' +
118
+ 'zUCC/CV8NwNRF1EqDBP5VrVLSAMp4EFliNcPUdFW/a+ZNowP9pPqsgvygwEFAlgP\r\n' +
119
+ 'dcxNX0wmX0S/YSadk5FQBb+OsKeQCS56LRmjwU2yr4khHNijR+5IU5BguO+z+Pej\r\n' +
120
+ 'hIz9jq9bdLoduwEu+tUX+fIg0C/OGfxKQrOXIW3hiJDilx2Bt+eyUYrtIxBhwNC9\r\n' +
121
+ 'jwwMCUFlcbvQSwq+Vx50v2LVjqalJMdMLQiULsF9nPw7EdUJz+aoM4STv7l4miXi\r\n' +
122
+ 'utkF4xlAl8lnJKOycsFPbqBBaypZoY3O3mKkWtSFRjD4oNW/juBGHTimPWRYgW3V\r\n' +
123
+ 'Q+IVHpkCgYEA75+vMp2Expq+iCa+UoV48HIVdiCaCk4vRedVe4IHyWxEkaliCHga\r\n' +
124
+ 'e9wAsxWipDxROv3yoLxlbddnZSD2YaYaIALH/xpSWlcBHZupyq6jNF7R+14Yx155\r\n' +
125
+ '88iGyoYKNE2VrcVlL164LIqaEB4lxYanhotwqcC5O6IOhpZZ7jSC/H8CgYEApcq9\r\n' +
126
+ '/G5po1BgYVZ2hdxTqdx8wniWaQNd7EVpogBhJ4KLC+tN42+vBHJT6BQp/PFRWjY5\r\n' +
127
+ 'fiC1zwI8ufL12F4T8+ZcQVZkHpLjKporYolYmQm/T8wNDwOziYB67Jp9M2EHdei/\r\n' +
128
+ 'HNo2FUsXRm+Tb1utiQn7AyJ6PHwwJAU1LbtYpdUCgYEAg4R/YiZ2c5MHNC8fkqdT\r\n' +
129
+ 'Q5U6FkW6hiF3bMSVdF5f67uSvufauI9C6exMLf6X79BzPQ+YlYQRn4H0a9r1n47N\r\n' +
130
+ 'E/iy0F8gCBlssVV4kZfcV6gbU/3HV9WQ1a6f3JRJEX/rwR5wdNll+HxyJpqFXK6V\r\n' +
131
+ 'UBFEWsc+Y26EznXDEiycH/0CgYBxwfMqSfhh/ryjDVi18L/XRVq1dVh/JbhEbjxU\r\n' +
132
+ '1D3VhlUyEHqZHADS5D9+dpd433wakipQyND3AWn5jSPzGlpGeEHE8yovcEo+6Rnr\r\n' +
133
+ 'uqH4ICAM+M3dB4UhS+8MedR+dI1R8ilv+qoxYhzOT7CyMA2agiaht/53kh7WGFys\r\n' +
134
+ 'zGe/IQKBgALJnE5CVQLaJgFcWGH2rnD6hWVh1DdV8ockzLg7ulUW0U5gueHWnaWv\r\n' +
135
+ 'PhP/P0YWF250IWmEm73LCZi3Cv3gBIwvn5pV3GHjMUexTQ3iODsGC8SdL0svnUTc\r\n' +
136
+ '5/VlSjAKS4Mn9gwutcXX9/Y2AJa4O6S/QfAQeU5aqkk/Fs+31ose\r\n' +
137
+ '-----END RSA PRIVATE KEY-----\r\n',
138
+ publicKey: '-----BEGIN PUBLIC KEY-----\r\n' +
139
+ 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmy+xwQpZMYkMWHhw+kh2\r\n' +
140
+ 'TDGbG+AF1w6BFVQ6CduEjUzD5d/jURtkaeb0RO/uba+J92DMgJJLWlcTe5FpQMb2\r\n' +
141
+ 'lxOrNoYP+suWnNxU7QD5vQ4OiJ+i3nTMly9LMB3BEEea2ZJRpVboJxRBeGl6pKz4\r\n' +
142
+ 'obFfoFxqtSww38Cw8h5Nplt+LXR/wq8yCpmN9hTE4CSw8iioIqxOZem3sz4//jcM\r\n' +
143
+ 'HJ5/aiTjXwseE8eWjaVfvpDESuwQMNjfJYYP0onzEZmTtztyAspsyf0GZBjd1ew2\r\n' +
144
+ 'nVCY0cCkQ1+tqYk7H9rjlj1PxduCa4aGVKZjIBFnZXhCE23znOgVt9PxFMPUrmHw\r\n' +
145
+ 'qwIDAQAB\r\n' +
146
+ '-----END PUBLIC KEY-----\r\n',
147
+ certificate: '-----BEGIN CERTIFICATE-----\r\n' +
148
+ 'MIIECTCCAvGgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBpMRQwEgYDVQQDEwtleGFt\r\n' +
149
+ 'cGxlLm9yZzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYDVQQH\r\n' +
150
+ 'EwpCbGFja3NidXJnMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MB4XDTE1\r\n' +
151
+ 'MTAwOTE4MDEwOVoXDTE2MTAwOTE4MDEwOVowaTEUMBIGA1UEAxMLZXhhbXBsZS5v\r\n' +
152
+ 'cmcxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxh\r\n' +
153
+ 'Y2tzYnVyZzENMAsGA1UEChMEVGVzdDENMAsGA1UECxMEVGVzdDCCASIwDQYJKoZI\r\n' +
154
+ 'hvcNAQEBBQADggEPADCCAQoCggEBAJsvscEKWTGJDFh4cPpIdkwxmxvgBdcOgRVU\r\n' +
155
+ 'OgnbhI1Mw+Xf41EbZGnm9ETv7m2vifdgzICSS1pXE3uRaUDG9pcTqzaGD/rLlpzc\r\n' +
156
+ 'VO0A+b0ODoifot50zJcvSzAdwRBHmtmSUaVW6CcUQXhpeqSs+KGxX6BcarUsMN/A\r\n' +
157
+ 'sPIeTaZbfi10f8KvMgqZjfYUxOAksPIoqCKsTmXpt7M+P/43DByef2ok418LHhPH\r\n' +
158
+ 'lo2lX76QxErsEDDY3yWGD9KJ8xGZk7c7cgLKbMn9BmQY3dXsNp1QmNHApENframJ\r\n' +
159
+ 'Ox/a45Y9T8XbgmuGhlSmYyARZ2V4QhNt85zoFbfT8RTD1K5h8KsCAwEAAaOBuzCB\r\n' +
160
+ 'uDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIC9DA7BgNVHSUENDAyBggrBgEFBQcD\r\n' +
161
+ 'AQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwEQYJYIZI\r\n' +
162
+ 'AYb4QgEBBAQDAgD3MCwGA1UdEQQlMCOGG2h0dHA6Ly9leGFtcGxlLm9yZy93ZWJp\r\n' +
163
+ 'ZCNtZYcEfwAAATAdBgNVHQ4EFgQUaC1StQewfZ4bMUDUsnpzy/4+CZ8wDQYJKoZI\r\n' +
164
+ 'hvcNAQENBQADggEBAGy58GzpSG3KAv0DILJPWhtxTRvbnd02AWO6fhCdx+siyQ02\r\n' +
165
+ 'aKgkf1sAS0MGDDMGiwMKvBTz8+8HnfFx6cA7NG7xtuw9m8yb1LeNLbOc3/TCrG/U\r\n' +
166
+ 'A27ZediP+hCqElB9MtNHyOx/vv+gdKXTFDG4PlykNFmFsGjrA+sA0OtwKRLPQCxp\r\n' +
167
+ 'rUtGw+cw+xy3O68/unCl86wc8PA5r4uAaQBXdWThpAL0KJI1ky7auUwpsR+aWILJ\r\n' +
168
+ '0x6a9LOUnCMbbOTN31vRweFxD0qS2J8QMDkfNflvEWmpIZHF4UEoietXk+suP9tc\r\n' +
169
+ '87rtT63BEY6KcZJJ+oDnKiZuAujmf1iezC+YORs=\r\n' +
170
+ '-----END CERTIFICATE-----\r\n'
171
+ };
172
+
173
+
47
174
  describe('x509', function() {
48
- it('should convert certificate to/from PEM', function() {
175
+ it('should convert SHA-1 based certificate to/from PEM', function() {
49
176
  var certificate = PKI.certificateFromPem(_pem.certificate);
50
177
  ASSERT.equal(PKI.certificateToPem(certificate), _pem.certificate);
51
178
  });
52
179
 
53
- it('should verify self-signed certificate', function() {
180
+ it('should convert SHA-256 based certificate to/from PEM', function() {
181
+ var certificate = PKI.certificateFromPem(_pem_sha256.certificate);
182
+ ASSERT.equal(PKI.certificateToPem(certificate), _pem_sha256.certificate);
183
+ });
184
+
185
+ it('should convert SHA-512 based certificate to/from PEM', function() {
186
+ var certificate = PKI.certificateFromPem(_pem_sha512.certificate);
187
+ ASSERT.equal(PKI.certificateToPem(certificate), _pem_sha512.certificate);
188
+ });
189
+
190
+ it('should verify SHA-1 based self-signed certificate', function() {
54
191
  var certificate = PKI.certificateFromPem(_pem.certificate);
55
192
  ASSERT.ok(certificate.verify(certificate));
56
193
  });
57
194
 
195
+ it('should verify SHA-256 based self-signed certificate', function() {
196
+ var certificate = PKI.certificateFromPem(_pem_sha256.certificate);
197
+ ASSERT.ok(certificate.verify(certificate));
198
+ });
199
+
200
+ it('should verify SHA-512 based self-signed certificate', function() {
201
+ var certificate = PKI.certificateFromPem(_pem_sha512.certificate);
202
+ ASSERT.ok(certificate.verify(certificate));
203
+ });
204
+
205
+ it('should generate a certificate with authorityKeyIdentifier extension', function() {
206
+ var keys = {
207
+ privateKey: PKI.privateKeyFromPem(_pem.privateKey),
208
+ publicKey: PKI.publicKeyFromPem(_pem.publicKey)
209
+ };
210
+ var attrs = [{
211
+ name: 'commonName',
212
+ value: 'example.org'
213
+ }, {
214
+ name: 'countryName',
215
+ value: 'US'
216
+ }, {
217
+ shortName: 'ST',
218
+ value: 'Virginia'
219
+ }, {
220
+ name: 'localityName',
221
+ value: 'Blacksburg'
222
+ }, {
223
+ name: 'organizationName',
224
+ value: 'Test'
225
+ }, {
226
+ shortName: 'OU',
227
+ value: 'Test'
228
+ }];
229
+ var cert = createCertificate({
230
+ publicKey: keys.publicKey,
231
+ signingKey: keys.privateKey,
232
+ extensions: [{
233
+ name: 'authorityKeyIdentifier',
234
+ keyIdentifier: true,
235
+ authorityCertIssuer: true,
236
+ serialNumber: true
237
+ }],
238
+ serialNumber: '01',
239
+ subject: attrs,
240
+ issuer: attrs,
241
+ isCA: true
242
+ });
243
+
244
+ // verify certificate encoding/parsing
245
+ var pem = PKI.certificateToPem(cert);
246
+ cert = PKI.certificateFromPem(pem);
247
+
248
+ // verify authorityKeyIdentifier extension
249
+ var index = findIndex(cert.extensions, {id: '2.5.29.35'});
250
+ ASSERT.ok(index !== -1);
251
+ var ext = cert.extensions[index];
252
+ ASSERT.equal(ext.name, 'authorityKeyIdentifier');
253
+ ASSERT.equal(ext.value, UTIL.hexToBytes(
254
+ '3081888014f57563e0c75d6e9b03fafdb2fd72349f23030300a16da46b30693114' +
255
+ '30120603550403130b6578616d706c652e6f7267310b3009060355040613025553' +
256
+ '3111300f0603550408130856697267696e6961311330110603550407130a426c61' +
257
+ '636b7362757267310d300b060355040a130454657374310d300b060355040b1304' +
258
+ '54657374820101'));
259
+
260
+ // verify certificate chain
261
+ var caStore = PKI.createCaStore();
262
+ caStore.addCertificate(cert);
263
+ PKI.verifyCertificateChain(caStore, [cert], function(vfd, depth, chain) {
264
+ ASSERT.equal(vfd, true);
265
+ ASSERT.ok(cert.verifySubjectKeyIdentifier());
266
+ return true;
267
+ });
268
+ });
269
+
58
270
  it('should generate and verify a self-signed certificate', function() {
59
271
  var keys = {
60
272
  privateKey: PKI.privateKeyFromPem(_pem.privateKey),
@@ -554,6 +766,8 @@ function Tests(ASSERT, PKI, MD, UTIL) {
554
766
  });
555
767
  });
556
768
 
769
+ // TODO: add sha-512 and sha-256 fingerprint tests
770
+
557
771
  describe('public key fingerprints', function() {
558
772
  it('should get a SHA-1 RSAPublicKey fingerprint', function() {
559
773
  var publicKey = PKI.publicKeyFromPem(_pem.publicKey);
@@ -642,6 +856,19 @@ function Tests(ASSERT, PKI, MD, UTIL) {
642
856
  });
643
857
  });
644
858
 
859
+ function findIndex(array, predicateObj) {
860
+ var result = -1;
861
+ array.forEach(function(el, index) {
862
+ var match = Object.keys(predicateObj).reduce(function(soFar, key) {
863
+ return soFar && el[key] === predicateObj[key];
864
+ }, true);
865
+ if(match) {
866
+ result = index;
867
+ }
868
+ });
869
+ return result;
870
+ }
871
+
645
872
  function createCertificate(options) {
646
873
  var publicKey = options.publicKey;
647
874
  var signingKey = options.signingKey;
@@ -659,7 +886,7 @@ function Tests(ASSERT, PKI, MD, UTIL) {
659
886
  cert.validity.notBefore.getFullYear() + 1);
660
887
  cert.setSubject(subject);
661
888
  cert.setIssuer(issuer);
662
- var extensions = [];
889
+ var extensions = options.extensions || [];
663
890
  if(isCA) {
664
891
  extensions.push({
665
892
  name: 'basicConstraints',
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "node-forge",
3
- "version": "0.6.34",
3
+ "version": "0.6.39",
4
4
  "description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
5
- "homepage": "http://github.com/digitalbazaar/forge",
5
+ "homepage": "https://github.com/digitalbazaar/forge",
6
6
  "author": {
7
7
  "name": "Digital Bazaar, Inc.",
8
8
  "email": "support@digitalbazaar.com",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "repository": {
31
31
  "type": "git",
32
- "url": "http://github.com/digitalbazaar/forge"
32
+ "url": "https://github.com/digitalbazaar/forge"
33
33
  },
34
34
  "bugs": {
35
35
  "url": "https://github.com/digitalbazaar/forge/issues",