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 +5 -1
- package/README.md +3 -3
- package/bower.json +1 -1
- package/js/md5.js +45 -22
- package/js/oids.js +1 -0
- package/js/rsa.js +7 -5
- package/js/sha1.js +50 -23
- package/js/sha256.js +50 -23
- package/js/sha512.js +45 -32
- package/js/util.js +3 -3
- package/js/x509.js +43 -0
- package/nodejs/test/util.js +109 -0
- package/nodejs/test/x509.js +230 -3
- package/package.json +3 -3
package/.travis.yml
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Forge
|
|
2
2
|
|
|
3
|
-
[](https://nodei.co/npm/node-forge/)
|
|
4
|
+
|
|
5
|
+
[](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
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
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
85
|
-
md.
|
|
86
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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,
|
|
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
|
|
411
|
-
0 and n-1 and its inverse and multiplying x by r^e before
|
|
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)
|
|
421
|
-
} while(r.equals(BigInteger.
|
|
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-
|
|
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
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
md.
|
|
87
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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,
|
|
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-
|
|
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
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
91
|
-
md.
|
|
92
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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,
|
|
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
|
|
93
|
-
|
|
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
|
-
|
|
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 =
|
|
134
|
-
md.
|
|
135
|
-
len[1] = len[0] + ((md.
|
|
136
|
-
md.
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
package/nodejs/test/util.js
CHANGED
|
@@ -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
|
|
package/nodejs/test/x509.js
CHANGED
|
@@ -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
|
|
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.
|
|
3
|
+
"version": "0.6.39",
|
|
4
4
|
"description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
|
|
5
|
-
"homepage": "
|
|
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": "
|
|
32
|
+
"url": "https://github.com/digitalbazaar/forge"
|
|
33
33
|
},
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/digitalbazaar/forge/issues",
|