Socket
Socket
Sign inDemoInstall

node-jose

Package Overview
Dependencies
Maintainers
2
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-jose - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

19

CHANGELOG.md
# Release Notes
<a name="1.1.0"></a>
## [1.1.0](https://github.com/cisco/node-jose/compare/1.0.0...1.1.0) (2018-11-05)
### Bug Fixes
* remove setImmediate/nextTick hack (fixes [#203](https://github.com/cisco/node-jose/issues/203)) ([4e24931](https://github.com/cisco/node-jose/commit/4e24931))
* correct jws verify input validation check (fixes [#210](https://github.com/cisco/node-jose/issues/210)) ([be66519](https://github.com/cisco/node-jose/commit/be66519))
* [node] use native crypto for RS signing (fixes [#202](https://github.com/cisco/node-jose/issues/202)) ([59636c3](https://github.com/cisco/node-jose/commit/59636c3))
### Features
* [node] use native crypto for AES-KW Key-Wrapping ([f18011f](https://github.com/cisco/node-jose/commit/f18011f))
* [node] use native crypto for RSA-OAEP and RSA1_5 encryption ([bba0a13](https://github.com/cisco/node-jose/commit/bba0a13))
* [node] use native crypto for RSA1_5 decryption ([2a9e48a](https://github.com/cisco/node-jose/commit/2a9e48a))
* [node] use native crypto for RSA-PSS ([8a05f35](https://github.com/cisco/node-jose/commit/8a05f35))
* [node] use native crypto for ECDSA ([aa5a48d](https://github.com/cisco/node-jose/commit/aa5a48d))
<a name="1.0.0"></a>

@@ -4,0 +23,0 @@ ## [1.0.0](https://github.com/cisco/node-jose/compare/0.11.0...1.0.0) (2018-05-30)

70

lib/algorithms/aes-kw.js

@@ -125,4 +125,36 @@ /*!

};
var node = function(key, pdata) {
try {
commonChecks(key, pdata);
} catch (err) {
return Promise.reject(err);
}
return helpers.setupFallback(null, webcrypto, fallback);
// split input into chunks
var R = split(pdata, 8),
iv = Buffer.alloc(16);
var A,
B,
count;
A = A0;
for (var jdx = 0; 6 > jdx; jdx++) {
for (var idx = 0; R.length > idx; idx++) {
count = (R.length * jdx) + idx + 1;
B = Buffer.concat([A, R[idx]]);
var cipher = helpers.nodeCrypto.createCipheriv("AES" + size, key, iv);
B = cipher.update(B);
A = xor(B.slice(0, 8),
longToBigEndian(count));
R[idx] = B.slice(8, 16);
}
}
R = [A].concat(R);
var cdata = Buffer.concat(R);
return Promise.resolve({
data: cdata
});
};
return helpers.setupFallback(node, webcrypto, fallback);
}

@@ -203,4 +235,38 @@ function kwDecryptFN(size) {

};
var node = function(key, cdata) {
try {
commonChecks(key, cdata);
} catch (err) {
return Promise.reject(err);
}
return helpers.setupFallback(null, webcrypto, fallback);
// prepare inputs
var R = split(cdata, 8),
iv = Buffer.alloc(16),
A,
B,
count;
A = R[0];
R = R.slice(1);
for (var jdx = 5; 0 <= jdx; --jdx) {
for (var idx = R.length - 1; 0 <= idx; --idx) {
count = (R.length * jdx) + idx + 1;
B = xor(A,
longToBigEndian(count));
B = Buffer.concat([B, R[idx], iv]);
var cipher = helpers.nodeCrypto.createDecipheriv("AES" + size, key, iv);
B = cipher.update(B);
A = B.slice(0, 8);
R[idx] = B.slice(8, 16);
}
}
if (A.toString() !== A0.toString()) {
return Promise.reject(new Error("decryption failed"));
}
var pdata = Buffer.concat(R);
return Promise.resolve(pdata);
};
return helpers.setupFallback(node, webcrypto, fallback);
}

@@ -207,0 +273,0 @@

@@ -81,2 +81,171 @@ /*!

function curveNameToOid(crv) {
switch (crv) {
case "P-256":
return "1.2.840.10045.3.1.7";
case "P-384":
return "1.3.132.0.34";
case "P-521":
return "1.3.132.0.35";
default:
return null;
}
}
var EC_OID = "1.2.840.10045.2.1";
function convertToPEM(key, isPrivate) {
// curveName to OID
var oid = key.crv;
oid = curveNameToOid(oid);
oid = forge.asn1.oidToDer(oid);
// key as bytes
var type,
pub,
asn1;
if (isPrivate) {
type = "EC PRIVATE KEY";
pub = Buffer.concat([
Buffer.from([0x00, 0x04]),
key.x,
key.y
]).toString("binary");
key = key.d.toString("binary");
asn1 = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.INTEGER, false, "\u0001"),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OCTETSTRING, false, key),
forge.asn1.create(forge.asn1.Class.CONTEXT_SPECIFIC, 0, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, oid.bytes())
]),
forge.asn1.create(forge.asn1.Class.CONTEXT_SPECIFIC, 1, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.BITSTRING, false, pub)
])
]);
} else {
type = "PUBLIC KEY";
key = Buffer.concat([
Buffer.from([0x00, 0x04]),
key.x,
key.y
]).toString("binary");
asn1 = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, forge.asn1.oidToDer(EC_OID).bytes()),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, oid.bytes())
]),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.BITSTRING, false, key)
]);
}
asn1 = forge.asn1.toDer(asn1).bytes();
var pem = forge.pem.encode({
type: type,
body: asn1
});
return pem;
}
// Inspired by teifip/node-webtokens/blob/master/lib/ecdsa.js
var ERR_MSG = 'Could not extract parameters from DER signature';
function derToConcat(signature, size) {
var offset = 0;
if (signature[offset++] !== 0x30) {
throw new Error(ERR_MSG);
}
var seqLength = signature[offset++];
if (seqLength === 0x81) {
seqLength = signature[offset++];
}
if (seqLength > signature.length - offset) {
throw new Error(ERR_MSG);
}
if (signature[offset++] !== 0x02) {
throw new Error(ERR_MSG);
}
var rLength = signature[offset++];
if (rLength > signature.length - offset - 2) {
throw new Error(ERR_MSG);
}
if (rLength > size + 1) {
throw new Error(ERR_MSG);
}
var rOffset = offset;
offset += rLength;
if (signature[offset++] !== 0x02) {
throw new Error(ERR_MSG);
}
var sLength = signature[offset++];
if (sLength !== signature.length - offset) {
throw new Error(ERR_MSG);
}
if (sLength > size + 1) {
throw new Error(ERR_MSG);
}
var sOffset = offset;
offset += sLength;
if (offset !== signature.length) {
throw new Error(ERR_MSG);
}
var rPadding = size - rLength;
var sPadding = size - sLength;
var dst = Buffer.alloc(rPadding + rLength + sPadding + sLength);
for (offset = 0; offset < rPadding; ++offset) {
dst[offset] = 0;
}
var rPad = Math.max(-rPadding, 0);
signature.copy(dst, offset, rOffset + rPad, rOffset + rLength);
offset = size;
for (var o = offset; offset < o + sPadding; ++offset) {
dst[offset] = 0;
}
var sPad = Math.max(-sPadding, 0);
signature.copy(dst, offset, sOffset + sPad, sOffset + sLength);
return dst;
}
function countPadding(buf, start, stop) {
var padding = 0;
while (start + padding < stop && buf[start + padding] === 0) {
++padding;
}
var needsSign = buf[start + padding] >= 0x80;
if (needsSign) {
--padding;
}
return padding;
}
function concatToDer(signature, size) {
var rPadding = countPadding(signature, 0, size);
var sPadding = countPadding(signature, size, signature.length);
var rLength = size - rPadding;
var sLength = size - sPadding;
var rsBytes = rLength + sLength + 4;
var shortLength = rsBytes < 0x80;
var dst = Buffer.alloc((shortLength ? 2 : 3) + rsBytes);
var offset = 0;
dst[offset++] = 0x30;
if (shortLength) {
dst[offset++] = rsBytes;
} else {
dst[offset++] = 0x81;
dst[offset++] = rsBytes & 0xFF;
}
dst[offset++] = 0x02;
dst[offset++] = rLength;
if (rPadding < 0) {
dst[offset++] = 0;
offset += signature.copy(dst, offset, 0, size);
} else {
offset += signature.copy(dst, offset, rPadding, size);
}
dst[offset++] = 0x02;
dst[offset++] = sLength;
if (sPadding < 0) {
dst[offset++] = 0;
signature.copy(dst, offset, size);
} else {
signature.copy(dst, offset, size + sPadding);
}
return dst;
}
module.exports = {

@@ -87,3 +256,7 @@ convertToForge: convertToForge,

convertToBuffer: convertToBuffer,
curveSize: curveSize
curveSize: curveSize,
derToConcat: derToConcat,
concatToDer: concatToDer,
convertToPEM: convertToPEM,
EC_OID: EC_OID
};

@@ -83,3 +83,46 @@ /*!

return helpers.setupFallback(null, webcrypto, fallback);
var nodejs;
var nodeHash = hash.toLowerCase().replace("-", "");
if (helpers.nodeCrypto && helpers.nodeCrypto.getHashes().indexOf(nodeHash) > -1) {
nodejs = function(key, pdata) {
if (curve !== key.crv) {
return Promise.reject(new Error("invalid curve"));
}
var promise;
promise = Promise.resolve(helpers.nodeCrypto.createSign(nodeHash));
promise = promise.then(function (sign) {
sign.update(pdata);
return sign;
});
var size;
switch (nodeHash.slice(-3)) {
case "384":
size = 48;
break;
case "512":
size = 66;
break;
default:
size = 32;
}
promise = promise.then(function (sign) {
return ecUtil.derToConcat(sign.sign(ecUtil.convertToPEM(key, true)), size);
});
promise = promise.then(function (result) {
return {
data: pdata,
mac: result
};
});
return promise;
};
}
return helpers.setupFallback(nodejs, webcrypto, fallback);
}

@@ -155,3 +198,45 @@

return helpers.setupFallback(null, webcrypto, fallback);
var nodejs;
var nodeHash = hash.toLowerCase().replace("-", "");
if (helpers.nodeCrypto && helpers.nodeCrypto.getHashes().indexOf(nodeHash) > -1) {
nodejs = function(key, pdata, mac /* , props */) {
if (curve !== key.crv) {
return Promise.reject(new Error("invalid curve"));
}
var size;
switch (nodeHash.slice(-3)) {
case "384":
size = 48;
break;
case "512":
size = 66;
break;
default:
size = 32;
}
var promise;
promise = Promise.resolve(helpers.nodeCrypto.createVerify(nodeHash));
promise = promise.then(function (verify) {
verify.update(pdata);
verify.end();
return verify.verify(ecUtil.convertToPEM(key, false), ecUtil.concatToDer(mac, size));
});
promise = promise.then(function (result) {
if (!result) {
throw new Error('verification failed');
}
return {
data: pdata,
mac,
valid: true,
};
});
return promise;
};
}
return helpers.setupFallback(nodejs, webcrypto, fallback);
}

@@ -158,0 +243,0 @@

7

lib/algorithms/rsa-util.js

@@ -54,4 +54,5 @@ /*!

function convertToPem(key, isPublic) {
if (key.__cachedPem) {
return key.__cachedPem;
var cacheKey = isPublic ? `__cachedPublicPem` : `__cachedPrivatePem`;
if (key[cacheKey]) {
return key[cacheKey];
}

@@ -66,3 +67,3 @@

Object.defineProperty(key, '__cachedPem', { value: value });
Object.defineProperty(key, cacheKey, { value: value });
return value;

@@ -69,0 +70,0 @@ }

/*!
* algorithms/rsassa.js - RSA Signatures
* algorithms/rsaes.js - RSA Signatures
*

@@ -13,2 +13,11 @@ * Copyright (c) 2015 Cisco Systems, Inc. See LICENSE file.

var nodeSupport = {
'RSA-OAEP': 'RSA_PKCS1_OAEP_PADDING',
RSA1_5: 'RSA_PKCS1_PADDING',
};
function nodeSupportCheck(name) {
return helpers.nodeCrypto && helpers.nodeCrypto.constants && Object.keys(nodeSupport).indexOf(name) !== -1;
}
// ### RSAES-PKCS1-v1_5

@@ -80,3 +89,19 @@

return helpers.setupFallback(null, webcrypto, fallback);
var nodejs;
if (nodeSupportCheck(name)) {
nodejs = function (key, pdata) {
key = rsaUtil.convertToPem(key, true);
var cdata = helpers.nodeCrypto.publicEncrypt({
key,
padding: helpers.nodeCrypto.constants[nodeSupport[name]],
}, pdata);
return {
data: cdata,
};
};
}
return helpers.setupFallback(nodejs, webcrypto, fallback);
}

@@ -144,5 +169,13 @@

var nodejs;
if (helpers.nodeCrypto && name === "RSA-OAEP") { // node only support SHA1, plain RSA-OAEP
if (nodeSupportCheck(name)) { // node ^6.12.0 || >= 8.0.0
nodejs = function(key, pdata) {
key = rsaUtil.convertToPem(key, false);
return helpers.nodeCrypto.privateDecrypt({
key,
padding: helpers.nodeCrypto.constants[nodeSupport[name]],
}, pdata);
};
} else if (helpers.nodeCrypto && name === 'RSA-OAEP') { // node (>= 6.0.0 && < 6.12.0) || ^7.0.0
nodejs = function(key, pdata) {
key = rsaUtil.convertToPem(key, false);
return helpers.nodeCrypto.privateDecrypt(key, pdata);

@@ -149,0 +182,0 @@ };

@@ -13,2 +13,6 @@ /*!

function nodePSSsupport() {
return helpers.nodeCrypto && helpers.nodeCrypto.constants && helpers.nodeCrypto.constants.RSA_PSS_SALTLEN_DIGEST;
}
// ### RSASSA-PKCS1-v1_5

@@ -65,6 +69,6 @@

var nodejs;
if (helpers.nodeCrypto && helpers.nodeCrypto.getHashes().indexOf(hash) > -1) {
var nodeHash = "RSA-" + hash.replace("-", "");
if (helpers.nodeCrypto && helpers.nodeCrypto.getHashes().indexOf(nodeHash) > -1) {
nodejs = function(key, pdata) {
key = rsaUtil.convertToPem(key, false);
var sign = helpers.nodeCrypto.createSign(hash);
var sign = helpers.nodeCrypto.createSign(nodeHash);
sign.update(pdata);

@@ -216,3 +220,23 @@

return helpers.setupFallback(null, webcrypto, fallback);
var nodejs;
var nodeHash = "RSA-" + hash.replace("-", "");
if (nodePSSsupport()) {
nodejs = function(key, pdata) {
var sign = helpers.nodeCrypto.createSign(nodeHash);
sign.update(pdata);
var sig = sign.sign({
key: rsaUtil.convertToPem(key, false),
padding: helpers.nodeCrypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: helpers.nodeCrypto.constants.RSA_PSS_SALTLEN_DIGEST,
});
return {
data: pdata,
mac: sig
};
};
}
return helpers.setupFallback(nodejs, webcrypto, fallback);
}

@@ -284,3 +308,25 @@

return helpers.setupFallback(null, webcrypto, fallback);
var nodejs;
if (nodePSSsupport()) {
nodejs = function(key, pdata, mac) {
var verify = helpers.nodeCrypto.createVerify(md);
verify.update(pdata);
verify.end();
var result = verify.verify({
key: rsaUtil.convertToPem(key, true),
padding: helpers.nodeCrypto.constants.RSA_PKCS1_PSS_PADDING,
}, mac);
if (!result) {
return Promise.reject(new Error("verification failed"));
}
return {
data: pdata,
mac: mac,
valid: true,
};
};
}
return helpers.setupFallback(nodejs, webcrypto, fallback);
}

@@ -287,0 +333,0 @@

@@ -91,9 +91,2 @@ /*!

// Prevent nextTick from being used when possible
if ("function" === typeof setImmediate) {
forge.util.setImmediate = forge.util.nextTick = function(callback) {
setImmediate(callback);
};
}
module.exports = forge;

@@ -29,3 +29,3 @@ /*!

var EC_OID = "1.2.840.10045.2.1";
var EC_OID = ecutil.EC_OID;
function oidToCurveName(oid) {

@@ -43,14 +43,2 @@ switch (oid) {

}
function curveNameToOid(crv) {
switch (crv) {
case "P-256":
return "1.2.840.10045.3.1.7";
case "P-384":
return "1.3.132.0.34";
case "P-521":
return "1.3.132.0.35";
default:
return null;
}
}

@@ -156,54 +144,5 @@ var JWKEcCfg = {

return keys.public;
},
convertToPEM: function(key, isPrivate) {
// curveName to OID
var oid = key.crv;
oid = curveNameToOid(oid);
oid = forge.asn1.oidToDer(oid);
// key as bytes
var type,
pub,
asn1;
if (isPrivate) {
type = "EC PRIVATE KEY";
pub = Buffer.concat([
Buffer.from([0x00, 0x04]),
key.x,
key.y
]).toString("binary");
key = key.d.toString("binary");
asn1 = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.INTEGER, false, "\u0001"),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OCTETSTRING, false, key),
forge.asn1.create(forge.asn1.Class.CONTEXT_SPECIFIC, 0, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, oid.bytes())
]),
forge.asn1.create(forge.asn1.Class.CONTEXT_SPECIFIC, 1, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.BITSTRING, false, pub)
])
]);
} else {
type = "PUBLIC KEY";
key = Buffer.concat([
Buffer.from([0x00, 0x04]),
key.x,
key.y
]).toString("binary");
asn1 = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, forge.asn1.oidToDer(EC_OID).bytes()),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, oid.bytes())
]),
forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.BITSTRING, false, key)
]);
}
asn1 = forge.asn1.toDer(asn1).bytes();
var pem = forge.pem.encode({
type: type,
body: asn1
});
return pem;
}
};
JWKEcCfg.convertToPEM = ecutil.convertToPEM;

@@ -210,0 +149,0 @@ // Inspired by digitalbaazar/node-forge/js/rsa.js

@@ -69,3 +69,3 @@ /*!

};
} else if (!input || "object" === input) {
} else if (!input || "object" !== typeof input) {
throw new Error("invalid input");

@@ -72,0 +72,0 @@ }

{
"name": "node-jose",
"version": "1.0.0",
"version": "1.1.0",
"description": "A JavaScript implementation of the JSON Object Signing and Encryption (JOSE) for current web browsers and node.js-based servers",
"main": "lib/index.js",
"scripts": {
"test": "gulp test:nodejs"
},
"repository": {
"type": "git",
"url": "https://github.com/cisco/node-jose.git"
},
"keywords": [
"crypto",
"jose",
"jwa",
"jwe",
"jwk",
"jws",
"jwe",
"jwa"
"jws"
],
"repository": {
"type": "git",
"url": "https://github.com/cisco/node-jose.git"
},
"license": "Apache-2.0",
"author": "Cisco Systems, Inc. <https://www.cisco.com>",

@@ -28,19 +25,25 @@ "contributors": [

],
"license": "Apache-2.0",
"main": "lib/index.js",
"scripts": {
"test": "gulp test:nodejs"
},
"browser": {
"crypto": false
},
"dependencies": {
"base64url": "^3.0.0",
"es6-promise": "^4.0.5",
"lodash.assign": "^4.0.8",
"lodash.clone": "^4.3.2",
"lodash.fill": "^3.2.2",
"lodash.flatten": "^4.2.0",
"lodash.intersection": "^4.1.2",
"lodash.merge": "^4.3.5",
"lodash.omit": "^4.2.1",
"lodash.partialright": "^4.1.3",
"lodash.pick": "^4.2.0",
"lodash.uniq": "^4.2.1",
"es6-promise": "^4.2.5",
"lodash.assign": "^4.2.0",
"lodash.clone": "^4.5.0",
"lodash.fill": "^3.4.0",
"lodash.flatten": "^4.4.0",
"lodash.intersection": "^4.4.0",
"lodash.merge": "^4.6.1",
"lodash.omit": "^4.5.0",
"lodash.partialright": "^4.2.1",
"lodash.pick": "^4.4.0",
"lodash.uniq": "^4.5.0",
"long": "^4.0.0",
"node-forge": "^0.7.1",
"uuid": "^3.0.1"
"node-forge": "^0.7.6",
"uuid": "^3.3.2"
},

@@ -61,2 +64,3 @@ "devDependencies": {

"gulp-util": "^3.0.7",
"is-safari": "^1.0.0",
"istanbul": "^0.4.0",

@@ -85,6 +89,3 @@ "jose-cookbook": "git+https://github.com/ietf-jose/cookbook.git",

"yargs": "^11.1.0"
},
"browser": {
"crypto": false
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc