node-forge 0.7.5 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +41 -39
- package/dist/forge.all.min.js +1 -1
- package/dist/forge.min.js +1 -1
- package/flash/package.json +28 -0
- package/lib/aesCipherSuites.js +2 -4
- package/lib/cipherModes.js +1 -1
- package/lib/des.js +2 -1
- package/lib/kem.js +2 -2
- package/lib/oids.js +2 -0
- package/lib/pkcs1.js +1 -1
- package/lib/pkcs7.js +30 -16
- package/lib/prng.js +6 -7
- package/lib/random.js +7 -7
- package/lib/rsa.js +162 -100
- package/lib/sha1.js +6 -6
- package/lib/sha512.js +1 -1
- package/lib/tls.js +43 -30
- package/lib/util.js +17 -2
- package/lib/x509.js +313 -251
- package/package.json +10 -13
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-forge-flash",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Flash build support for Forge.",
|
|
6
|
+
"homepage": "https://github.com/digitalbazaar/forge",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Digital Bazaar, Inc.",
|
|
9
|
+
"email": "support@digitalbazaar.com",
|
|
10
|
+
"url": "http://digitalbazaar.com/"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"flex-sdk": ""
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/digitalbazaar/forge"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/digitalbazaar/forge/issues",
|
|
21
|
+
"email": "support@digitalbazaar.com"
|
|
22
|
+
},
|
|
23
|
+
"license": "(BSD-3-Clause OR GPL-2.0)",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "mxmlc -debug=false -define=CONFIG::debugging,false -define=CONFIG::release,true -compiler.source-path=. -static-link-runtime-shared-libraries -output=swf/SocketPool.swf SocketPool.as",
|
|
26
|
+
"build-debug": "mxmlc -debug=true -define=CONFIG::debugging,true -define=CONFIG::release,false -compiler.source-path=. -static-link-runtime-shared-libraries -output=swf/SocketPool.swf SocketPool.as"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/lib/aesCipherSuites.js
CHANGED
|
@@ -16,7 +16,7 @@ var tls = module.exports = forge.tls;
|
|
|
16
16
|
* Supported cipher suites.
|
|
17
17
|
*/
|
|
18
18
|
tls.CipherSuites['TLS_RSA_WITH_AES_128_CBC_SHA'] = {
|
|
19
|
-
id: [0x00,0x2f],
|
|
19
|
+
id: [0x00, 0x2f],
|
|
20
20
|
name: 'TLS_RSA_WITH_AES_128_CBC_SHA',
|
|
21
21
|
initSecurityParameters: function(sp) {
|
|
22
22
|
sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes;
|
|
@@ -32,7 +32,7 @@ tls.CipherSuites['TLS_RSA_WITH_AES_128_CBC_SHA'] = {
|
|
|
32
32
|
initConnectionState: initConnectionState
|
|
33
33
|
};
|
|
34
34
|
tls.CipherSuites['TLS_RSA_WITH_AES_256_CBC_SHA'] = {
|
|
35
|
-
id: [0x00,0x35],
|
|
35
|
+
id: [0x00, 0x35],
|
|
36
36
|
name: 'TLS_RSA_WITH_AES_256_CBC_SHA',
|
|
37
37
|
initSecurityParameters: function(sp) {
|
|
38
38
|
sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes;
|
|
@@ -199,10 +199,8 @@ function decrypt_aes_cbc_sha1_padding(blockSize, output, decrypt) {
|
|
|
199
199
|
*
|
|
200
200
|
* @return true on success, false on failure.
|
|
201
201
|
*/
|
|
202
|
-
var count = 0;
|
|
203
202
|
function decrypt_aes_cbc_sha1(record, s) {
|
|
204
203
|
var rval = false;
|
|
205
|
-
++count;
|
|
206
204
|
|
|
207
205
|
var iv;
|
|
208
206
|
if(record.version.minor === tls.Versions.TLS_1_0.minor) {
|
package/lib/cipherModes.js
CHANGED
|
@@ -652,7 +652,7 @@ modes.gcm.prototype.encrypt = function(input, output, finish) {
|
|
|
652
652
|
this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
|
|
653
653
|
}
|
|
654
654
|
|
|
655
|
-
if(partialBytes
|
|
655
|
+
if(partialBytes <= 0 || finish) {
|
|
656
656
|
// handle overflow prior to hashing
|
|
657
657
|
if(finish) {
|
|
658
658
|
// get block overflow
|
package/lib/des.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* Paul Tero, July 2001
|
|
8
8
|
* http://www.tero.co.uk/des/
|
|
9
9
|
*
|
|
10
|
-
* Optimised for performance with large blocks by
|
|
10
|
+
* Optimised for performance with large blocks by
|
|
11
|
+
* Michael Hayworth, November 2001
|
|
11
12
|
* http://www.netdealing.com
|
|
12
13
|
*
|
|
13
14
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND
|
package/lib/kem.js
CHANGED
|
@@ -53,14 +53,14 @@ forge.kem.rsa.create = function(kdf, options) {
|
|
|
53
53
|
* key: the secret key to use for encrypting a message.
|
|
54
54
|
*/
|
|
55
55
|
kem.encrypt = function(publicKey, keyLength) {
|
|
56
|
-
// generate a random r where 1
|
|
56
|
+
// generate a random r where 1 < r < n
|
|
57
57
|
var byteLength = Math.ceil(publicKey.n.bitLength() / 8);
|
|
58
58
|
var r;
|
|
59
59
|
do {
|
|
60
60
|
r = new BigInteger(
|
|
61
61
|
forge.util.bytesToHex(prng.getBytesSync(byteLength)),
|
|
62
62
|
16).mod(publicKey.n);
|
|
63
|
-
} while(r.
|
|
63
|
+
} while(r.compareTo(BigInteger.ONE) <= 0);
|
|
64
64
|
|
|
65
65
|
// prepend r with zeros
|
|
66
66
|
r = forge.util.hexToBytes(r.toString(16));
|
package/lib/oids.js
CHANGED
|
@@ -108,9 +108,11 @@ _IN('2.5.4.7', 'localityName');
|
|
|
108
108
|
_IN('2.5.4.8', 'stateOrProvinceName');
|
|
109
109
|
_IN('2.5.4.10', 'organizationName');
|
|
110
110
|
_IN('2.5.4.11', 'organizationalUnitName');
|
|
111
|
+
_IN('2.5.4.13', 'description');
|
|
111
112
|
|
|
112
113
|
// X.509 extension OIDs
|
|
113
114
|
_IN('2.16.840.1.113730.1.1', 'nsCertType');
|
|
115
|
+
_IN('2.16.840.1.113730.1.13', 'nsComment'); // deprecated in theory; still widely used
|
|
114
116
|
_I_('2.5.29.1', 'authorityKeyIdentifier'); // deprecated, use .35
|
|
115
117
|
_I_('2.5.29.2', 'keyAttributes'); // obsolete use .37 or .15
|
|
116
118
|
_I_('2.5.29.3', 'certificatePolicies'); // deprecated, use .32
|
package/lib/pkcs1.js
CHANGED
package/lib/pkcs7.js
CHANGED
|
@@ -328,8 +328,11 @@ p7.createSignedData = function() {
|
|
|
328
328
|
|
|
329
329
|
/**
|
|
330
330
|
* Signs the content.
|
|
331
|
+
* @param options Options to apply when signing:
|
|
332
|
+
* [detached] boolean. If signing should be done in detached mode. Defaults to false.
|
|
331
333
|
*/
|
|
332
|
-
sign: function() {
|
|
334
|
+
sign: function(options) {
|
|
335
|
+
options = options || {};
|
|
333
336
|
// auto-generate content info
|
|
334
337
|
if(typeof msg.content !== 'object' || msg.contentInfo === null) {
|
|
335
338
|
// use Data ContentInfo
|
|
@@ -349,12 +352,16 @@ p7.createSignedData = function() {
|
|
|
349
352
|
content = forge.util.encodeUtf8(msg.content);
|
|
350
353
|
}
|
|
351
354
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
355
|
+
if (options.detached) {
|
|
356
|
+
msg.detachedContent = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, content);
|
|
357
|
+
} else {
|
|
358
|
+
msg.contentInfo.value.push(
|
|
359
|
+
// [0] EXPLICIT content
|
|
360
|
+
asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [
|
|
361
|
+
asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false,
|
|
362
|
+
content)
|
|
363
|
+
]));
|
|
364
|
+
}
|
|
358
365
|
}
|
|
359
366
|
}
|
|
360
367
|
|
|
@@ -437,10 +444,22 @@ p7.createSignedData = function() {
|
|
|
437
444
|
}
|
|
438
445
|
|
|
439
446
|
function addSignerInfos(mds) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
447
|
+
var content;
|
|
448
|
+
|
|
449
|
+
if (msg.detachedContent) {
|
|
450
|
+
// Signature has been made in detached mode.
|
|
451
|
+
content = msg.detachedContent;
|
|
452
|
+
} else {
|
|
453
|
+
// Note: ContentInfo is a SEQUENCE with 2 values, second value is
|
|
454
|
+
// the content field and is optional for a ContentInfo but required here
|
|
455
|
+
// since signers are present
|
|
456
|
+
// get ContentInfo content
|
|
457
|
+
content = msg.contentInfo.value[1];
|
|
458
|
+
// skip [0] EXPLICIT content wrapper
|
|
459
|
+
content = content.value[0];
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if(!content) {
|
|
444
463
|
throw new Error(
|
|
445
464
|
'Could not sign PKCS#7 message; there is no content to sign.');
|
|
446
465
|
}
|
|
@@ -448,11 +467,6 @@ p7.createSignedData = function() {
|
|
|
448
467
|
// get ContentInfo content type
|
|
449
468
|
var contentType = asn1.derToOid(msg.contentInfo.value[0].value);
|
|
450
469
|
|
|
451
|
-
// get ContentInfo content
|
|
452
|
-
var content = msg.contentInfo.value[1];
|
|
453
|
-
// skip [0] EXPLICIT content wrapper
|
|
454
|
-
content = content.value[0];
|
|
455
|
-
|
|
456
470
|
// serialize content
|
|
457
471
|
var bytes = asn1.toDer(content);
|
|
458
472
|
|
package/lib/prng.js
CHANGED
|
@@ -267,13 +267,12 @@ prng.create = function(plugin) {
|
|
|
267
267
|
function defaultSeedFile(needed) {
|
|
268
268
|
// use window.crypto.getRandomValues strong source of entropy if available
|
|
269
269
|
var getRandomValues = null;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
270
|
+
var globalScope = forge.util.globalScope;
|
|
271
|
+
var _crypto = globalScope.crypto || globalScope.msCrypto;
|
|
272
|
+
if(_crypto && _crypto.getRandomValues) {
|
|
273
|
+
getRandomValues = function(arr) {
|
|
274
|
+
return _crypto.getRandomValues(arr);
|
|
275
|
+
};
|
|
277
276
|
}
|
|
278
277
|
|
|
279
278
|
var b = forge.util.createBuffer();
|
package/lib/random.js
CHANGED
|
@@ -115,14 +115,14 @@ var _ctx = spawnPrng();
|
|
|
115
115
|
// add other sources of entropy only if window.crypto.getRandomValues is not
|
|
116
116
|
// available -- otherwise this source will be automatically used by the prng
|
|
117
117
|
var getRandomValues = null;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
118
|
+
var globalScope = forge.util.globalScope;
|
|
119
|
+
var _crypto = globalScope.crypto || globalScope.msCrypto;
|
|
120
|
+
if(_crypto && _crypto.getRandomValues) {
|
|
121
|
+
getRandomValues = function(arr) {
|
|
122
|
+
return _crypto.getRandomValues(arr);
|
|
123
|
+
};
|
|
125
124
|
}
|
|
125
|
+
|
|
126
126
|
if(forge.options.usePureJavaScript ||
|
|
127
127
|
(!forge.util.isNodejs && !getRandomValues)) {
|
|
128
128
|
// if this is a web worker, do not use weak entropy, instead register to
|
package/lib/rsa.js
CHANGED
|
@@ -74,9 +74,14 @@ if(typeof BigInteger === 'undefined') {
|
|
|
74
74
|
var BigInteger = forge.jsbn.BigInteger;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
var _crypto = forge.util.isNodejs ? require('crypto') : null;
|
|
78
|
+
|
|
77
79
|
// shortcut for asn.1 API
|
|
78
80
|
var asn1 = forge.asn1;
|
|
79
81
|
|
|
82
|
+
// shortcut for util API
|
|
83
|
+
var util = forge.util;
|
|
84
|
+
|
|
80
85
|
/*
|
|
81
86
|
* RSA encryption and decryption, see RFC 2313.
|
|
82
87
|
*/
|
|
@@ -682,7 +687,7 @@ pki.rsa.stepKeyPairGenerationState = function(state, n) {
|
|
|
682
687
|
var THIRTY = new BigInteger(null);
|
|
683
688
|
THIRTY.fromInt(30);
|
|
684
689
|
var deltaIdx = 0;
|
|
685
|
-
var op_or = function(x, y) {
|
|
690
|
+
var op_or = function(x, y) {return x | y;};
|
|
686
691
|
|
|
687
692
|
// keep stepping until time limit is reached or done
|
|
688
693
|
var t1 = +new Date();
|
|
@@ -731,7 +736,7 @@ pki.rsa.stepKeyPairGenerationState = function(state, n) {
|
|
|
731
736
|
// ensure number is coprime with e
|
|
732
737
|
state.pqState =
|
|
733
738
|
(state.num.subtract(BigInteger.ONE).gcd(state.e)
|
|
734
|
-
|
|
739
|
+
.compareTo(BigInteger.ONE) === 0) ? 3 : 0;
|
|
735
740
|
} else if(state.pqState === 3) {
|
|
736
741
|
// store p or q
|
|
737
742
|
state.pqState = 0;
|
|
@@ -820,7 +825,7 @@ pki.rsa.stepKeyPairGenerationState = function(state, n) {
|
|
|
820
825
|
* @param [bits] the size for the private key in bits, defaults to 2048.
|
|
821
826
|
* @param [e] the public exponent to use, defaults to 65537.
|
|
822
827
|
* @param [options] options for key-pair generation, if given then 'bits'
|
|
823
|
-
*
|
|
828
|
+
* and 'e' must *not* be given:
|
|
824
829
|
* bits the size for the private key in bits, (default: 2048).
|
|
825
830
|
* e the public exponent to use, (default: 65537 (0x10001)).
|
|
826
831
|
* workerScript the worker script URL.
|
|
@@ -830,7 +835,7 @@ pki.rsa.stepKeyPairGenerationState = function(state, n) {
|
|
|
830
835
|
* numbers for each web worker to check per work assignment,
|
|
831
836
|
* (default: 100).
|
|
832
837
|
* prng a custom crypto-secure pseudo-random number generator to use,
|
|
833
|
-
* that must define "getBytesSync".
|
|
838
|
+
* that must define "getBytesSync". Disables use of native APIs.
|
|
834
839
|
* algorithm the algorithm to use (default: 'PRIMEINC').
|
|
835
840
|
* @param [callback(err, keypair)] called once the operation completes.
|
|
836
841
|
*
|
|
@@ -883,63 +888,109 @@ pki.rsa.generateKeyPair = function(bits, e, options, callback) {
|
|
|
883
888
|
e = options.e || 0x10001;
|
|
884
889
|
}
|
|
885
890
|
|
|
886
|
-
//
|
|
887
|
-
|
|
888
|
-
if(!forge.options.usePureJavaScript && callback &&
|
|
891
|
+
// use native code if permitted, available, and parameters are acceptable
|
|
892
|
+
if(!forge.options.usePureJavaScript && !options.prng &&
|
|
889
893
|
bits >= 256 && bits <= 16384 && (e === 0x10001 || e === 3)) {
|
|
890
|
-
if(
|
|
891
|
-
//
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
privateKey: privateKey,
|
|
909
|
-
publicKey: pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
|
910
|
-
});
|
|
911
|
-
}
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
if(_detectSubtleMsCrypto('generateKey') &&
|
|
915
|
-
_detectSubtleMsCrypto('exportKey')) {
|
|
916
|
-
var genOp = window.msCrypto.subtle.generateKey({
|
|
917
|
-
name: 'RSASSA-PKCS1-v1_5',
|
|
918
|
-
modulusLength: bits,
|
|
919
|
-
publicExponent: _intToUint8Array(e),
|
|
920
|
-
hash: {name: 'SHA-256'}
|
|
921
|
-
}, true /* key can be exported*/, ['sign', 'verify']);
|
|
922
|
-
genOp.oncomplete = function(e) {
|
|
923
|
-
var pair = e.target.result;
|
|
924
|
-
var exportOp = window.msCrypto.subtle.exportKey(
|
|
925
|
-
'pkcs8', pair.privateKey);
|
|
926
|
-
exportOp.oncomplete = function(e) {
|
|
927
|
-
var pkcs8 = e.target.result;
|
|
928
|
-
var privateKey = pki.privateKeyFromAsn1(
|
|
929
|
-
asn1.fromDer(forge.util.createBuffer(pkcs8)));
|
|
894
|
+
if(callback) {
|
|
895
|
+
// try native async
|
|
896
|
+
if(_detectNodeCrypto('generateKeyPair')) {
|
|
897
|
+
return _crypto.generateKeyPair('rsa', {
|
|
898
|
+
modulusLength: bits,
|
|
899
|
+
publicExponent: e,
|
|
900
|
+
publicKeyEncoding: {
|
|
901
|
+
type: 'spki',
|
|
902
|
+
format: 'pem'
|
|
903
|
+
},
|
|
904
|
+
privateKeyEncoding: {
|
|
905
|
+
type: 'pkcs8',
|
|
906
|
+
format: 'pem'
|
|
907
|
+
}
|
|
908
|
+
}, function(err, pub, priv) {
|
|
909
|
+
if(err) {
|
|
910
|
+
return callback(err);
|
|
911
|
+
}
|
|
930
912
|
callback(null, {
|
|
931
|
-
privateKey:
|
|
932
|
-
publicKey: pki.
|
|
913
|
+
privateKey: pki.privateKeyFromPem(priv),
|
|
914
|
+
publicKey: pki.publicKeyFromPem(pub)
|
|
933
915
|
});
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
if(_detectSubtleCrypto('generateKey') &&
|
|
919
|
+
_detectSubtleCrypto('exportKey')) {
|
|
920
|
+
// use standard native generateKey
|
|
921
|
+
return util.globalScope.crypto.subtle.generateKey({
|
|
922
|
+
name: 'RSASSA-PKCS1-v1_5',
|
|
923
|
+
modulusLength: bits,
|
|
924
|
+
publicExponent: _intToUint8Array(e),
|
|
925
|
+
hash: {name: 'SHA-256'}
|
|
926
|
+
}, true /* key can be exported*/, ['sign', 'verify'])
|
|
927
|
+
.then(function(pair) {
|
|
928
|
+
return util.globalScope.crypto.subtle.exportKey(
|
|
929
|
+
'pkcs8', pair.privateKey);
|
|
930
|
+
// avoiding catch(function(err) {...}) to support IE <= 8
|
|
931
|
+
}).then(undefined, function(err) {
|
|
932
|
+
callback(err);
|
|
933
|
+
}).then(function(pkcs8) {
|
|
934
|
+
if(pkcs8) {
|
|
935
|
+
var privateKey = pki.privateKeyFromAsn1(
|
|
936
|
+
asn1.fromDer(forge.util.createBuffer(pkcs8)));
|
|
937
|
+
callback(null, {
|
|
938
|
+
privateKey: privateKey,
|
|
939
|
+
publicKey: pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
if(_detectSubtleMsCrypto('generateKey') &&
|
|
945
|
+
_detectSubtleMsCrypto('exportKey')) {
|
|
946
|
+
var genOp = util.globalScope.msCrypto.subtle.generateKey({
|
|
947
|
+
name: 'RSASSA-PKCS1-v1_5',
|
|
948
|
+
modulusLength: bits,
|
|
949
|
+
publicExponent: _intToUint8Array(e),
|
|
950
|
+
hash: {name: 'SHA-256'}
|
|
951
|
+
}, true /* key can be exported*/, ['sign', 'verify']);
|
|
952
|
+
genOp.oncomplete = function(e) {
|
|
953
|
+
var pair = e.target.result;
|
|
954
|
+
var exportOp = util.globalScope.msCrypto.subtle.exportKey(
|
|
955
|
+
'pkcs8', pair.privateKey);
|
|
956
|
+
exportOp.oncomplete = function(e) {
|
|
957
|
+
var pkcs8 = e.target.result;
|
|
958
|
+
var privateKey = pki.privateKeyFromAsn1(
|
|
959
|
+
asn1.fromDer(forge.util.createBuffer(pkcs8)));
|
|
960
|
+
callback(null, {
|
|
961
|
+
privateKey: privateKey,
|
|
962
|
+
publicKey: pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
|
963
|
+
});
|
|
964
|
+
};
|
|
965
|
+
exportOp.onerror = function(err) {
|
|
966
|
+
callback(err);
|
|
967
|
+
};
|
|
934
968
|
};
|
|
935
|
-
|
|
969
|
+
genOp.onerror = function(err) {
|
|
936
970
|
callback(err);
|
|
937
971
|
};
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
} else {
|
|
975
|
+
// try native sync
|
|
976
|
+
if(_detectNodeCrypto('generateKeyPairSync')) {
|
|
977
|
+
var keypair = _crypto.generateKeyPairSync('rsa', {
|
|
978
|
+
modulusLength: bits,
|
|
979
|
+
publicExponent: e,
|
|
980
|
+
publicKeyEncoding: {
|
|
981
|
+
type: 'spki',
|
|
982
|
+
format: 'pem'
|
|
983
|
+
},
|
|
984
|
+
privateKeyEncoding: {
|
|
985
|
+
type: 'pkcs8',
|
|
986
|
+
format: 'pem'
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
return {
|
|
990
|
+
privateKey: pki.privateKeyFromPem(keypair.privateKey),
|
|
991
|
+
publicKey: pki.publicKeyFromPem(keypair.publicKey)
|
|
992
|
+
};
|
|
993
|
+
}
|
|
943
994
|
}
|
|
944
995
|
}
|
|
945
996
|
|
|
@@ -1003,7 +1054,7 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
|
|
|
1003
1054
|
}
|
|
1004
1055
|
};
|
|
1005
1056
|
} else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) {
|
|
1006
|
-
scheme = {
|
|
1057
|
+
scheme = {encode: function(e) {return e;}};
|
|
1007
1058
|
} else if(typeof scheme === 'string') {
|
|
1008
1059
|
throw new Error('Unsupported encryption scheme: "' + scheme + '".');
|
|
1009
1060
|
}
|
|
@@ -1044,37 +1095,37 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
|
|
|
1044
1095
|
*
|
|
1045
1096
|
* @return true if the signature was verified, false if not.
|
|
1046
1097
|
*/
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1098
|
+
key.verify = function(digest, signature, scheme) {
|
|
1099
|
+
if(typeof scheme === 'string') {
|
|
1100
|
+
scheme = scheme.toUpperCase();
|
|
1101
|
+
} else if(scheme === undefined) {
|
|
1102
|
+
scheme = 'RSASSA-PKCS1-V1_5';
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
if(scheme === 'RSASSA-PKCS1-V1_5') {
|
|
1106
|
+
scheme = {
|
|
1107
|
+
verify: function(digest, d) {
|
|
1108
|
+
// remove padding
|
|
1109
|
+
d = _decodePkcs1_v1_5(d, key, true);
|
|
1110
|
+
// d is ASN.1 BER-encoded DigestInfo
|
|
1111
|
+
var obj = asn1.fromDer(d);
|
|
1112
|
+
// compare the given digest to the decrypted one
|
|
1113
|
+
return digest === obj.value[1].value;
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
} else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) {
|
|
1117
|
+
scheme = {
|
|
1118
|
+
verify: function(digest, d) {
|
|
1119
|
+
// remove padding
|
|
1120
|
+
d = _decodePkcs1_v1_5(d, key, true);
|
|
1121
|
+
return digest === d;
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// do rsa decryption w/o any decoding, then verify -- which does decoding
|
|
1127
|
+
var d = pki.rsa.decrypt(signature, key, true, false);
|
|
1128
|
+
return scheme.verify(digest, d, key.n.bitLength());
|
|
1078
1129
|
};
|
|
1079
1130
|
|
|
1080
1131
|
return key;
|
|
@@ -1132,7 +1183,7 @@ pki.setRsaPrivateKey = pki.rsa.setPrivateKey = function(
|
|
|
1132
1183
|
var d = pki.rsa.decrypt(data, key, false, false);
|
|
1133
1184
|
|
|
1134
1185
|
if(scheme === 'RSAES-PKCS1-V1_5') {
|
|
1135
|
-
scheme = {
|
|
1186
|
+
scheme = {decode: _decodePkcs1_v1_5};
|
|
1136
1187
|
} else if(scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') {
|
|
1137
1188
|
scheme = {
|
|
1138
1189
|
decode: function(d, key) {
|
|
@@ -1140,7 +1191,7 @@ pki.setRsaPrivateKey = pki.rsa.setPrivateKey = function(
|
|
|
1140
1191
|
}
|
|
1141
1192
|
};
|
|
1142
1193
|
} else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) {
|
|
1143
|
-
scheme = {
|
|
1194
|
+
scheme = {decode: function(d) {return d;}};
|
|
1144
1195
|
} else {
|
|
1145
1196
|
throw new Error('Unsupported encryption scheme: "' + scheme + '".');
|
|
1146
1197
|
}
|
|
@@ -1182,10 +1233,10 @@ pki.setRsaPrivateKey = pki.rsa.setPrivateKey = function(
|
|
|
1182
1233
|
}
|
|
1183
1234
|
|
|
1184
1235
|
if(scheme === undefined || scheme === 'RSASSA-PKCS1-V1_5') {
|
|
1185
|
-
scheme = {
|
|
1236
|
+
scheme = {encode: emsaPkcs1v15encode};
|
|
1186
1237
|
bt = 0x01;
|
|
1187
1238
|
} else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) {
|
|
1188
|
-
scheme = {
|
|
1239
|
+
scheme = {encode: function() {return md;}};
|
|
1189
1240
|
bt = 0x01;
|
|
1190
1241
|
}
|
|
1191
1242
|
|
|
@@ -1220,7 +1271,7 @@ pki.wrapRsaPrivateKey = function(rsaKey) {
|
|
|
1220
1271
|
// PrivateKey
|
|
1221
1272
|
asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false,
|
|
1222
1273
|
asn1.toDer(rsaKey).getBytes())
|
|
1223
|
-
|
|
1274
|
+
]);
|
|
1224
1275
|
};
|
|
1225
1276
|
|
|
1226
1277
|
/**
|
|
@@ -1727,6 +1778,17 @@ function _getMillerRabinTests(bits) {
|
|
|
1727
1778
|
return 2;
|
|
1728
1779
|
}
|
|
1729
1780
|
|
|
1781
|
+
/**
|
|
1782
|
+
* Performs feature detection on the Node crypto interface.
|
|
1783
|
+
*
|
|
1784
|
+
* @param fn the feature (function) to detect.
|
|
1785
|
+
*
|
|
1786
|
+
* @return true if detected, false if not.
|
|
1787
|
+
*/
|
|
1788
|
+
function _detectNodeCrypto(fn) {
|
|
1789
|
+
return forge.util.isNodejs && typeof _crypto[fn] === 'function';
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1730
1792
|
/**
|
|
1731
1793
|
* Performs feature detection on the SubtleCrypto interface.
|
|
1732
1794
|
*
|
|
@@ -1735,10 +1797,10 @@ function _getMillerRabinTests(bits) {
|
|
|
1735
1797
|
* @return true if detected, false if not.
|
|
1736
1798
|
*/
|
|
1737
1799
|
function _detectSubtleCrypto(fn) {
|
|
1738
|
-
return (typeof
|
|
1739
|
-
typeof
|
|
1740
|
-
typeof
|
|
1741
|
-
typeof
|
|
1800
|
+
return (typeof util.globalScope !== 'undefined' &&
|
|
1801
|
+
typeof util.globalScope.crypto === 'object' &&
|
|
1802
|
+
typeof util.globalScope.crypto.subtle === 'object' &&
|
|
1803
|
+
typeof util.globalScope.crypto.subtle[fn] === 'function');
|
|
1742
1804
|
}
|
|
1743
1805
|
|
|
1744
1806
|
/**
|
|
@@ -1751,10 +1813,10 @@ function _detectSubtleCrypto(fn) {
|
|
|
1751
1813
|
* @return true if detected, false if not.
|
|
1752
1814
|
*/
|
|
1753
1815
|
function _detectSubtleMsCrypto(fn) {
|
|
1754
|
-
return (typeof
|
|
1755
|
-
typeof
|
|
1756
|
-
typeof
|
|
1757
|
-
typeof
|
|
1816
|
+
return (typeof util.globalScope !== 'undefined' &&
|
|
1817
|
+
typeof util.globalScope.msCrypto === 'object' &&
|
|
1818
|
+
typeof util.globalScope.msCrypto.subtle === 'object' &&
|
|
1819
|
+
typeof util.globalScope.msCrypto.subtle[fn] === 'function');
|
|
1758
1820
|
}
|
|
1759
1821
|
|
|
1760
1822
|
function _intToUint8Array(x) {
|
package/lib/sha1.js
CHANGED
|
@@ -113,12 +113,12 @@ sha1.create = function() {
|
|
|
113
113
|
return md;
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Produces the digest.
|
|
118
|
+
*
|
|
119
|
+
* @return a byte buffer containing the digest value.
|
|
120
|
+
*/
|
|
121
|
+
md.digest = function() {
|
|
122
122
|
/* Note: Here we copy the remaining bytes in the input buffer and
|
|
123
123
|
add the appropriate SHA-1 padding. Then we do the final update
|
|
124
124
|
on a copy of the state so that if the user wants to get
|