use base58 encoding for signatures
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
142e9ec458
commit
612686a224
48
index.js
48
index.js
@ -103,10 +103,36 @@ function sign_object (obj, key, key_info = null) {
|
|||||||
obj,
|
obj,
|
||||||
...(typeof key_info === 'object' ? key_info : { key_info })
|
...(typeof key_info === 'object' ? key_info : { key_info })
|
||||||
};
|
};
|
||||||
const str = encoding.to_b64 (JSON.stringify (payload));
|
const str = encoding.to_b58 (JSON.stringify (payload));
|
||||||
const token = encoding.to_b64 (hash_sha512 (str, key), 'hex');
|
const token = encoding.to_b58 (hash_sha512 (str, key), 'hex');
|
||||||
const res = `${str}.${token}`;
|
const res = `${str}.${token}.2`;
|
||||||
return encodeURIComponent (res);
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_signature (str, key = null) {
|
||||||
|
let dec = str.split ('.');
|
||||||
|
const version = dec[2];
|
||||||
|
const res = {};
|
||||||
|
switch (version) {
|
||||||
|
case '2':
|
||||||
|
res.json = JSON.parse (encoding.to_utf8 (dec[0], 'base58'));
|
||||||
|
res.token = encoding.to_hex (dec[1], 'base58');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dec = decodeURIComponent (str)
|
||||||
|
.split ('.');
|
||||||
|
res.json = JSON.parse (
|
||||||
|
encoding.to_utf8 (dec[0], 'base64')
|
||||||
|
);
|
||||||
|
res.token = encoding.to_hex (dec[1], 'base64');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key !== null) {
|
||||||
|
const string_key = typeof key === 'string' ? key : key (res.json);
|
||||||
|
res.hash = hash_sha512 (dec[0], string_key);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,13 +146,8 @@ function sign_object (obj, key, key_info = null) {
|
|||||||
function verify_signature_get_info (str, key, timeout = 0) {
|
function verify_signature_get_info (str, key, timeout = 0) {
|
||||||
if (typeof str !== 'string')
|
if (typeof str !== 'string')
|
||||||
return null;
|
return null;
|
||||||
const dec = decodeURIComponent (str)
|
const { json, token, hash } = parse_signature (str, key);
|
||||||
.split ('.');
|
if (token !== hash)
|
||||||
const json = JSON.parse (encoding.to_utf8 (dec[0], 'base64'));
|
|
||||||
const token = encoding.to_hex (dec[1], 'base64');
|
|
||||||
const string_key = typeof key === 'string' ? key : key (json);
|
|
||||||
const verify_token = hash_sha512 (dec[0], string_key);
|
|
||||||
if (token !== verify_token)
|
|
||||||
return null;
|
return null;
|
||||||
const time = Date.now () - json.iat;
|
const time = Date.now () - json.iat;
|
||||||
const num_timeout = typeof timeout === 'number' ? timeout : timeout (json);
|
const num_timeout = typeof timeout === 'number' ? timeout : timeout (json);
|
||||||
@ -159,9 +180,7 @@ function verify_signature (str, key, timeout = 0) {
|
|||||||
function get_signature_info (str) {
|
function get_signature_info (str) {
|
||||||
if (typeof str !== 'string')
|
if (typeof str !== 'string')
|
||||||
return null;
|
return null;
|
||||||
const dec = decodeURIComponent (str)
|
const { json } = parse_signature (str);
|
||||||
.split ('.');
|
|
||||||
const json = JSON.parse (encoding.to_utf8 (dec[0], 'base64'));
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,4 +298,3 @@ module.exports = {
|
|||||||
verify_signature,
|
verify_signature,
|
||||||
verify_signature_get_info
|
verify_signature_get_info
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sapphirecode/crypto-helper",
|
"name": "@sapphirecode/crypto-helper",
|
||||||
"version": "1.2.1",
|
"version": "1.2.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Timo Hocker",
|
"name": "Timo Hocker",
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"compile": "tsc --allowJs --declaration --emitDeclarationOnly index.js"
|
"compile": "tsc --allowJs --declaration --emitDeclarationOnly index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sapphirecode/encoding-helper": "^1.0.38"
|
"@sapphirecode/encoding-helper": "^1.1.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
|
@ -10,8 +10,21 @@
|
|||||||
|
|
||||||
const crypto = require ('../../index');
|
const crypto = require ('../../index');
|
||||||
|
|
||||||
// eslint-disable-next-line max-lines-per-function
|
// eslint-disable-next-line max-lines-per-function, max-statements
|
||||||
describe ('crypto helper', () => {
|
describe ('crypto helper', () => {
|
||||||
|
beforeEach (() => {
|
||||||
|
jasmine.clock ()
|
||||||
|
.install ();
|
||||||
|
const base_time = (new Date);
|
||||||
|
jasmine.clock ()
|
||||||
|
.mockDate (base_time);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach (() => {
|
||||||
|
jasmine.clock ()
|
||||||
|
.uninstall ();
|
||||||
|
});
|
||||||
|
|
||||||
it ('random_hex', () => {
|
it ('random_hex', () => {
|
||||||
const hex = crypto.random_hex (16);
|
const hex = crypto.random_hex (16);
|
||||||
expect (hex.length)
|
expect (hex.length)
|
||||||
@ -200,12 +213,6 @@ describe ('crypto helper', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it ('should not fail verification if timeout unspecified', () => {
|
it ('should not fail verification if timeout unspecified', () => {
|
||||||
jasmine.clock ()
|
|
||||||
.install ();
|
|
||||||
const base_time = (new Date);
|
|
||||||
jasmine.clock ()
|
|
||||||
.mockDate (base_time);
|
|
||||||
|
|
||||||
const obj = { foo: 'bar' };
|
const obj = { foo: 'bar' };
|
||||||
const str = crypto.sign_object (obj, 'baz');
|
const str = crypto.sign_object (obj, 'baz');
|
||||||
|
|
||||||
@ -215,18 +222,9 @@ describe ('crypto helper', () => {
|
|||||||
const dec = crypto.verify_signature (str, 'baz');
|
const dec = crypto.verify_signature (str, 'baz');
|
||||||
expect (obj)
|
expect (obj)
|
||||||
.toEqual (dec);
|
.toEqual (dec);
|
||||||
|
|
||||||
jasmine.clock ()
|
|
||||||
.uninstall ();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('should reject old signatures', () => {
|
it ('should reject old signatures', () => {
|
||||||
jasmine.clock ()
|
|
||||||
.install ();
|
|
||||||
const base_time = (new Date);
|
|
||||||
jasmine.clock ()
|
|
||||||
.mockDate (base_time);
|
|
||||||
|
|
||||||
const obj = { foo: 'bar' };
|
const obj = { foo: 'bar' };
|
||||||
const str = crypto.sign_object (obj, 'baz');
|
const str = crypto.sign_object (obj, 'baz');
|
||||||
|
|
||||||
@ -236,18 +234,9 @@ describe ('crypto helper', () => {
|
|||||||
const dec = crypto.verify_signature (str, 'baz', 1);
|
const dec = crypto.verify_signature (str, 'baz', 1);
|
||||||
expect (dec)
|
expect (dec)
|
||||||
.toEqual (null);
|
.toEqual (null);
|
||||||
|
|
||||||
jasmine.clock ()
|
|
||||||
.uninstall ();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('should not reject valid signatures', () => {
|
it ('should not reject valid signatures', () => {
|
||||||
jasmine.clock ()
|
|
||||||
.install ();
|
|
||||||
const base_time = (new Date);
|
|
||||||
jasmine.clock ()
|
|
||||||
.mockDate (base_time);
|
|
||||||
|
|
||||||
const obj = { foo: 'bar' };
|
const obj = { foo: 'bar' };
|
||||||
const str = crypto.sign_object (obj, 'baz');
|
const str = crypto.sign_object (obj, 'baz');
|
||||||
|
|
||||||
@ -257,18 +246,9 @@ describe ('crypto helper', () => {
|
|||||||
const dec = crypto.verify_signature (str, 'baz', 100);
|
const dec = crypto.verify_signature (str, 'baz', 100);
|
||||||
expect (obj)
|
expect (obj)
|
||||||
.toEqual (dec);
|
.toEqual (dec);
|
||||||
|
|
||||||
jasmine.clock ()
|
|
||||||
.uninstall ();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('should verify signature using function retrieved timeout', () => {
|
it ('should verify signature using function retrieved timeout', () => {
|
||||||
jasmine.clock ()
|
|
||||||
.install ();
|
|
||||||
const base_time = (new Date);
|
|
||||||
jasmine.clock ()
|
|
||||||
.mockDate (base_time);
|
|
||||||
|
|
||||||
const obj = { foo: 'bar' };
|
const obj = { foo: 'bar' };
|
||||||
const str = crypto.sign_object (obj, 'baz', { to: 100 });
|
const str = crypto.sign_object (obj, 'baz', { to: 100 });
|
||||||
|
|
||||||
@ -278,18 +258,9 @@ describe ('crypto helper', () => {
|
|||||||
const dec = crypto.verify_signature (str, 'baz', (info) => info.to);
|
const dec = crypto.verify_signature (str, 'baz', (info) => info.to);
|
||||||
expect (obj)
|
expect (obj)
|
||||||
.toEqual (dec);
|
.toEqual (dec);
|
||||||
|
|
||||||
jasmine.clock ()
|
|
||||||
.uninstall ();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('verify_signature on almost timed out packet', () => {
|
it ('verify_signature on almost timed out packet', () => {
|
||||||
jasmine.clock ()
|
|
||||||
.install ();
|
|
||||||
const base_time = (new Date);
|
|
||||||
jasmine.clock ()
|
|
||||||
.mockDate (base_time);
|
|
||||||
|
|
||||||
const obj = { foo: 'bar' };
|
const obj = { foo: 'bar' };
|
||||||
const str = crypto.sign_object (obj, 'baz');
|
const str = crypto.sign_object (obj, 'baz');
|
||||||
|
|
||||||
@ -298,16 +269,29 @@ describe ('crypto helper', () => {
|
|||||||
const dec = crypto.verify_signature (str, 'baz', 10);
|
const dec = crypto.verify_signature (str, 'baz', 10);
|
||||||
expect (obj)
|
expect (obj)
|
||||||
.toEqual (dec);
|
.toEqual (dec);
|
||||||
|
|
||||||
jasmine.clock ()
|
|
||||||
.uninstall ();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('should decode problematic token', () => {
|
it ('should decode problematic token', () => {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
|
const str = 'wEJbzvUywiaiGWZUG6CtCXNkNmRGyVoi9icytpTe4gZhsb8Gk.5PZbhGL525mdV7EmYomTwUei6qULpLaZwSXy92eaUDNgbyXPHsr9dfUCeEBpTqmzuq3VtmmV43epUyWRoHocAsV3.2';
|
||||||
|
const obj = crypto.decode_signed (str);
|
||||||
|
expect (obj)
|
||||||
|
.toEqual ({ id: 1 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should automatically reencode b64 tokens', () => {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
const str = 'eyJpYXQiOjE1ODE0NDAwMTIyODgsIm9iaiI6eyJpZCI6MX19.24ZOsWrnfkNe%2FbM0r7DaVJMqE2bfn2aAM%2BZSzWeSf31OCTlXXNWD34RBL2X5v3UliYQ4IIsLNBFbaW9texPHug%3D%3D';
|
const str = 'eyJpYXQiOjE1ODE0NDAwMTIyODgsIm9iaiI6eyJpZCI6MX19.24ZOsWrnfkNe%2FbM0r7DaVJMqE2bfn2aAM%2BZSzWeSf31OCTlXXNWD34RBL2X5v3UliYQ4IIsLNBFbaW9texPHug%3D%3D';
|
||||||
const obj = crypto.decode_signed (str);
|
const obj = crypto.decode_signed (str);
|
||||||
expect (obj)
|
expect (obj)
|
||||||
.toEqual ({ id: 1 });
|
.toEqual ({ id: 1 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it ('verify_signature on b64 string', () => {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
const str = 'eyJpYXQiOjE2MDkzNDQ4MDMyMjcsIm9iaiI6eyJpZCI6MX19.N762xuMaNbT%2Fqb0uTKST68BZgSnmNxXaHl4GY7iAKqaDDEwZn3biYfg5DgJ45QgPZrndchczDjUqLkyXoqw4KQ%3D%3D';
|
||||||
|
const obj = crypto.verify_signature (str, 'baz');
|
||||||
|
expect (obj)
|
||||||
|
.toEqual ({ id: 1 });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user