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:
		
							
								
								
									
										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 });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user