Skip to content

Commit

Permalink
Implement HS256 verify
Browse files Browse the repository at this point in the history
  • Loading branch information
brianloveswords committed Jan 16, 2013
1 parent ab2be75 commit 0866d21
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
49 changes: 40 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,61 @@ const util = require('util');
const base64url = require('base64url');
const crypto = require('crypto');

exports.sign = function _jwsSign() {
exports.sign = function jwsSign() {
const opts = {};
if (typeof arguments[0] === 'object') {
if (typeof arguments[0] === 'object')
return jwsSign(arguments[0]);
}
if (arguments.length === 2) {
opts.header = { alg : 'HS256' };
opts.payload = arguments[0];
opts.secret = arguments[1];
return jwsSign(opts);
return jwsHS256Sign(opts);
}
}

function jwsSign(opts) {
function jwsHS256Sign(opts) {
var payload = opts.payload;
if (typeof opts.payload === 'object')
payload = JSON.stringify(opts.payload);
const secret = opts.secret;
const header = JSON.stringify(opts.header);
const hmac = crypto.createHmac('SHA256', opts.secret);
hmac.update(payload);
const signature = hmac.digest('base64');
const signature = createHS256Signature(header, payload, secret);
return jwsOutput(header, payload, signature);
}

function jwsOutput(header, payload, signature) {
return util.format(
'%s.%s.%s',
base64url(header),
base64url(payload),
base64url.fromBase64(signature));
signature);
}

function createHS256Signature(header, payload, secret) {
const hmac = crypto.createHmac('SHA256', secret);
const encodedHeader = base64url(header);
const encodedPayload = base64url(payload);
hmac.update(encodedHeader);
hmac.update('.');
hmac.update(encodedPayload);
const signature = hmac.digest('base64');
return base64url.fromBase64(signature);
}

exports.verify = function jwsVerify(jwsObject, keyOrSecret) {
const parts = jwsObject.split('.');
const encodedHeader = parts[0];
const encodedPayload = parts[1];
const encodedSignature = parts[2];
const rawHeader = base64url.decode(encodedHeader);
const payload = base64url.decode(encodedPayload);
const header = JSON.parse(rawHeader);
if (header.alg === 'HS256')
return jwsHS256Verify(rawHeader, payload, keyOrSecret, encodedSignature)
}

function jwsHS256Verify(header, payload, secret, expectedSignature) {
const calculatedSignature =
createHS256Signature(header, payload, secret);
return expectedSignature === calculatedSignature;
}
20 changes: 13 additions & 7 deletions test/jws.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const crypto = require('crypto');
const test = require('tap').test;
const jws = require('..');

test('HS256 algorithm', function (t) {
test('HS256 algorithm, signing', function (t) {
const testString = 'oh hey';
const secret = 'sup';
const expectedHeader = { alg: 'HS256' };
Expand All @@ -12,16 +12,22 @@ test('HS256 algorithm', function (t) {
const parts = jwsObject.split('.');
const header = JSON.parse(base64url.decode(parts[0]));
const payload = base64url.decode(parts[1]);
const signature = base64url.toBase64(parts[2]);

const hmac = crypto.createHmac('SHA256', secret);
hmac.update(testString);
const expectedSignature = hmac.digest('base64');

t.same(payload, testString, 'payload should match test string');
t.same(header, expectedHeader, 'header should match expectation');
t.same(signature, expectedSignature, 'signatures should match');
t.end();
});

test('HS256 algorithm, verifying', function (t) {
const testString = 'oh hey';
const secret = 'sup';
const jwsObject = jws.sign(testString, secret);

const verified = jws.verify(jwsObject, secret);
t.ok(verified, 'should be verified');

const notVerified = jws.verify(jwsObject, 'some other thing');
t.notOk(notVerified, 'should not be verified');
t.end();
});

0 comments on commit 0866d21

Please sign in to comment.