Socket
Socket
Sign inDemoInstall

jws

Package Overview
Dependencies
22
Maintainers
2
Versions
23
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0 to 3.0.0

readme.md

12

CHANGELOG.md
# Change Log
All notable changes to this project will be documented in this file.
## [3.0.0]
### Changed
- **BREAKING**: `jwt.verify` now requires an `algorithm` parameter, and
`jws.createVerify` requires an `algorithm` option. The `"alg"` field
signature headers is ignored. This mitigates a critical security flaw
in the library which would allow an attacker to generate signatures with
arbitrary contents that would be accepted by `jwt.verify`. See
https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
for details.
## [2.0.0] - 2015-01-30

@@ -19,3 +29,3 @@ ### Changed

[unreleased]: https://github.com/brianloveswords/node-jws/compare/v2.0.0...HEAD
[2.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v2.0.0...v1.0.1
[2.0.0]: https://github.com/brianloveswords/node-jws/compare/v1.0.1...v2.0.0

@@ -22,0 +32,0 @@ [7880050]: https://github.com/brianloveswords/node-jws/commit/7880050

31

lib/verify-stream.js

@@ -30,21 +30,2 @@ /*global module*/

function algoFromJWS(jwsSig) {
var err;
const header = headerFromJWS(jwsSig);
if (typeof header != 'object') {
err = new Error("Invalid token: no header in signature '" + jwsSig + "'");
err.code = "MISSING_HEADER";
err.signature = jwsSig;
throw err;
}
if (!header.alg) {
err = new Error("Missing `alg` field in header for signature '"+ jwsSig +"'");
err.code = "MISSING_ALGORITHM";
err.header = header;
err.signature = jwsSig;
throw err;
}
return header.alg;
}
function signatureFromJWS(jwsSig) {

@@ -64,7 +45,12 @@ return jwsSig.split('.')[2];

function jwsVerify(jwsSig, secretOrKey) {
function jwsVerify(jwsSig, algorithm, secretOrKey) {
if (!algorithm) {
var err = new Error("Missing algorithm parameter for jws.verify");
err.code = "MISSING_ALGORITHM";
throw err;
}
jwsSig = toString(jwsSig);
const signature = signatureFromJWS(jwsSig);
const securedInput = securedInputFromJWS(jwsSig);
const algo = jwa(algoFromJWS(jwsSig));
const algo = jwa(algorithm);
return algo.verify(securedInput, signature, secretOrKey);

@@ -101,2 +87,3 @@ }

this.readable = true;
this.algorithm = opts.algorithm;
this.encoding = opts.encoding;

@@ -117,3 +104,3 @@ this.secret = this.publicKey = this.key = secretStream;

VerifyStream.prototype.verify = function verify() {
const valid = jwsVerify(this.signature.buffer, this.key.buffer);
const valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer);
const obj = jwsDecode(this.signature.buffer, this.encoding);

@@ -120,0 +107,0 @@ this.emit('done', valid, obj);

{
"name": "jws",
"version": "2.0.0",
"version": "3.0.0",
"description": "Implementation of JSON Web Signatures",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -49,3 +49,4 @@ /*global process*/

test('HMAC using SHA-'+bits+' hash algorithm', function (t) {
const header = { alg: 'HS'+bits, typ: 'JWT' };
const alg = 'HS'+bits;
const header = { alg: alg, typ: 'JWT' };
const secret = 'sup';

@@ -59,4 +60,5 @@ const jwsObj = jws.sign({

const parts = jws.decode(jwsObj);
t.ok(jws.verify(jwsObj, secret), 'should verify');
t.notOk(jws.verify(jwsObj, 'something else'), 'should not verify');
t.ok(jws.verify(jwsObj, alg, secret), 'should verify');
t.notOk(jws.verify(jwsObj, alg, 'something else'), 'should not verify with non-matching secret');
t.notOk(jws.verify(jwsObj, 'RS'+bits, secret), 'should not verify with non-matching algorithm');
t.same(parts.payload, payload, 'should match payload');

@@ -70,3 +72,4 @@ t.same(parts.header, header, 'should match header');

test('RSASSA using SHA-'+bits+' hash algorithm', function (t) {
const header = { alg: 'RS'+bits };
const alg = 'RS'+bits;
const header = { alg: alg };
const privateKey = rsaPrivateKey;

@@ -81,4 +84,5 @@ const publicKey = rsaPublicKey;

const parts = jws.decode(jwsObj, { json: true });
t.ok(jws.verify(jwsObj, publicKey), 'should verify');
t.notOk(jws.verify(jwsObj, wrongPublicKey), 'should not verify');
t.ok(jws.verify(jwsObj, alg, publicKey), 'should verify');
t.notOk(jws.verify(jwsObj, alg, wrongPublicKey), 'should not verify with non-matching public key');
t.notOk(jws.verify(jwsObj, 'HS'+bits, publicKey), 'should not verify with non-matching algorithm');
t.same(parts.payload, payload, 'should match payload');

@@ -93,3 +97,4 @@ t.same(parts.header, header, 'should match header');

test('ECDSA using P-'+curve+' curve and SHA-'+bits+' hash algorithm', function (t) {
const header = { alg: 'ES'+bits };
const alg = 'ES'+bits;
const header = { alg: alg };
const privateKey = ecdsaPrivateKey['256'];

@@ -104,4 +109,5 @@ const publicKey = ecdsaPublicKey['256'];

const parts = jws.decode(jwsObj);
t.ok(jws.verify(jwsObj, publicKey), 'should verify');
t.notOk(jws.verify(jwsObj, wrongPublicKey), 'should not verify');
t.ok(jws.verify(jwsObj, alg, publicKey), 'should verify');
t.notOk(jws.verify(jwsObj, alg, wrongPublicKey), 'should not verify with non-matching public key');
t.notOk(jws.verify(jwsObj, 'HS'+bits, publicKey), 'should not verify with non-matching algorithm');
t.same(parts.payload, payloadString, 'should match payload');

@@ -114,3 +120,4 @@ t.same(parts.header, header, 'should match header');

test('No digital signature or MAC value included', function (t) {
const header = { alg: 'none' };
const alg = 'none';
const header = { alg: alg };
const payload = 'oh hey José!';

@@ -122,4 +129,5 @@ const jwsObj = jws.sign({

const parts = jws.decode(jwsObj);
t.ok(jws.verify(jwsObj), 'should verify');
t.ok(jws.verify(jwsObj, 'anything'), 'should still verify');
t.ok(jws.verify(jwsObj, alg), 'should verify');
t.ok(jws.verify(jwsObj, alg, 'anything'), 'should still verify');
t.notOk(jws.verify(jwsObj, 'HS256', 'anything'), 'should not verify with non-matching algorithm');
t.same(parts.payload, payload, 'should match payload');

@@ -139,3 +147,3 @@ t.same(parts.header, header, 'should match header');

sig.on('done', function (signature) {
t.ok(jws.verify(signature, secret), 'should verify');
t.ok(jws.verify(signature, 'HS256', secret), 'should verify');
t.end();

@@ -160,4 +168,4 @@ });

sig.on('done', function (signature) {
t.ok(jws.verify(signature, publicKey), 'should verify');
t.notOk(jws.verify(signature, wrongPublicKey), 'should not verify');
t.ok(jws.verify(signature, 'RS256', publicKey), 'should verify');
t.notOk(jws.verify(signature, 'RS256', wrongPublicKey), 'should not verify');
t.same(jws.decode(signature).payload, readfile('data.txt'), 'got all the data');

@@ -179,4 +187,4 @@ t.end();

sig.on('done', function (signature) {
t.ok(jws.verify(signature, publicKey), 'should verify');
t.notOk(jws.verify(signature, wrongPublicKey), 'should not verify');
t.ok(jws.verify(signature, 'RS256', publicKey), 'should verify');
t.notOk(jws.verify(signature, 'RS256', wrongPublicKey), 'should not verify');
t.same(jws.decode(signature).payload, readfile('data.txt'), 'got all the data');

@@ -196,3 +204,3 @@ t.end();

});
const verifier = jws.createVerify();
const verifier = jws.createVerify({algorithm: 'ES512'});
sigStream.pipe(verifier.signature);

@@ -216,2 +224,3 @@ publicKeyStream.pipe(verifier.key);

const verifier = jws.createVerify({
algorithm: 'ES512',
signature: sigStream,

@@ -241,10 +250,14 @@ publicKey: publicKeyStream,

test('jws.decode: missing algo in header', function (t) {
test('jws.verify: missing or invalid algorithm', function (t) {
const header = Buffer('{"something":"not an algo"}').toString('base64');
const payload = Buffer('sup').toString('base64');
const sig = header + '.' + payload + '.';
try { jws.verify(sig, 'whatever') }
try { jws.verify(sig) }
catch (e) {
t.same(e.code, 'MISSING_ALGORITHM');
}
try { jws.verify(sig, 'whatever') }
catch (e) {
t.ok(e.message.match('"whatever" is not a valid algorithm.'));
}
t.end();

@@ -251,0 +264,0 @@ });

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc