refactoring, asymmetric signatures and encryption
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:
27
test/spec/hashing.js
Normal file
27
test/spec/hashing.js
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require ('../../index');
|
||||
|
||||
describe ('hashing', () => {
|
||||
it ('sha512', () => {
|
||||
const hash = crypto.hash_sha512 ('a', 'b');
|
||||
expect (
|
||||
hash
|
||||
)
|
||||
.toEqual (
|
||||
// eslint-disable-next-line max-len
|
||||
'2d408a0717ec188158278a796c689044361dc6fdde28d6f04973b80896e1823975cdbf12eb63f9e0591328ee235d80e9b5bf1aa6a44f4617ff3caf6400eb172d'
|
||||
);
|
||||
});
|
||||
|
||||
it ('checksum', () => {
|
||||
const hash = crypto.checksum ('foo');
|
||||
expect (
|
||||
hash
|
||||
)
|
||||
.toEqual (
|
||||
// eslint-disable-next-line max-len
|
||||
'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
||||
);
|
||||
});
|
||||
});
|
72
test/spec/random.js
Normal file
72
test/spec/random.js
Normal file
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require ('../../index');
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
describe ('random', () => {
|
||||
it ('random_hex', () => {
|
||||
const hex = crypto.random_hex (16);
|
||||
expect (hex.length)
|
||||
.toEqual (16);
|
||||
expect (hex)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
|
||||
it ('random_hex with default length', () => {
|
||||
const hex = crypto.random_hex ();
|
||||
expect (hex.length)
|
||||
.toEqual (8);
|
||||
expect (hex)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
|
||||
it ('random_hex should refuse length smaller 1', () => {
|
||||
expect (
|
||||
() => (crypto.random_hex (0))
|
||||
)
|
||||
.toThrowError ('invalid length');
|
||||
});
|
||||
|
||||
it ('random_hex should always return correct length', () => {
|
||||
for (let i = 1; i < 32; i++) {
|
||||
const hex = crypto.random_hex (i);
|
||||
expect (hex.length)
|
||||
.toEqual (i);
|
||||
}
|
||||
});
|
||||
|
||||
it ('random_string', () => {
|
||||
const str = crypto.random_string (16);
|
||||
expect (str.length)
|
||||
.toEqual (16);
|
||||
});
|
||||
|
||||
it ('random_string with default length', () => {
|
||||
const str = crypto.random_string ();
|
||||
expect (str.length)
|
||||
.toEqual (8);
|
||||
});
|
||||
|
||||
it ('random_string should refuse length smaller 1', () => {
|
||||
expect (
|
||||
() => (crypto.random_string (0))
|
||||
)
|
||||
.toThrowError ('invalid length');
|
||||
});
|
||||
|
||||
it ('random_string should always return correct length', () => {
|
||||
for (let i = 1; i < 32; i++) {
|
||||
const str = crypto.random_string (i);
|
||||
expect (str.length)
|
||||
.toEqual (i);
|
||||
}
|
||||
});
|
||||
|
||||
it ('create_salt', () => {
|
||||
const salt = crypto.create_salt ();
|
||||
expect (salt.length)
|
||||
.toEqual (64);
|
||||
expect (salt)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
});
|
133
test/spec/rsa.js
Normal file
133
test/spec/rsa.js
Normal file
@ -0,0 +1,133 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require ('../../index');
|
||||
|
||||
const key_length = 512;
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
describe ('rsa', () => {
|
||||
it ('should create a keypair', async () => {
|
||||
const k = await crypto.generate_keypair ();
|
||||
|
||||
expect (k.private_key)
|
||||
.toMatch (/^-----BEGIN PRIVATE KEY-----.+-----END PRIVATE KEY-----\n$/su);
|
||||
expect (k.public_key)
|
||||
// eslint-disable-next-line max-len
|
||||
.toMatch (/^-----BEGIN RSA PUBLIC KEY-----.+-----END RSA PUBLIC KEY-----\n$/su);
|
||||
});
|
||||
|
||||
it ('should throw on too small key size', async () => {
|
||||
await expectAsync (crypto.generate_keypair (16))
|
||||
.toBeRejectedWithError (
|
||||
'error:0408F078:rsa routines:pkey_rsa_ctrl:key size too small'
|
||||
);
|
||||
});
|
||||
|
||||
it ('should encrypt and decrypt', async () => {
|
||||
const k = await crypto.generate_keypair (key_length);
|
||||
const data = 'foobar';
|
||||
const enc = crypto.asym_encrypt (data, k.public_key);
|
||||
const dec = crypto.asym_decrypt (enc, k.private_key);
|
||||
expect (dec)
|
||||
.toEqual (data);
|
||||
expect (enc).not.toEqual (data);
|
||||
});
|
||||
|
||||
it ('should throw if encryption key is invalid', () => {
|
||||
const key = '-----BEGIN RSA PUBLIC KEY-----\n'
|
||||
+ 'MEgCCQDGvKLaq1SB/BTzocR4ZqGNr8dz1ylxxUpDncCu0C/ayOGPnCilB0LGEdqK\n'
|
||||
+ 'rORlsYpIaDvLv6x6k8iSg6A/TsybAgMBAAE=\n'
|
||||
+ '-----END RSA PUBLIC KEY-----\n';
|
||||
const data = 'foobar';
|
||||
expect (() => crypto.asym_encrypt (data, key))
|
||||
.toThrow ();
|
||||
});
|
||||
|
||||
it ('should throw on invalid decryption key', () => {
|
||||
const data = 'EHsGr2eSVqZKTX1U9Qj4crGRFkk299kmxhiiO3fyaIS'
|
||||
+ 'olB9+UYDdqrwcf/INwNddW4AzjA2Kf4dYaXIRLZsU1Q==';
|
||||
const key = '-----BEGIN PRIVATE KEY-----\n'
|
||||
+ 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAxryi2qtUgfwU86HE\n'
|
||||
+ 'eGahja/Hc9cpccVKQ53ArtXv2sjhj5wopQdCxhHaiqzkZbGKSGg7y7+sepPIkoOg\n'
|
||||
+ 'P07MmwIDAQABAkBKIk3hoi24+07ZfwuqGibDksGlLarxHLZSOMOKsnBXfRRyGqMr\n'
|
||||
+ '/Z+qtQ9VPRWHBzGHZ9rXAVKa8gnRirik+ez5AiEA/XL6tOy92Yvxm46ewswmZ7ab\n'
|
||||
+ 'V1KvChsXziaRj5eLzacCIQDIvLBO8og5Ng4r7E/dOAYrvzOLFqlN5UCuCRZzuFpv\n'
|
||||
+ '7QIgCnj5ywgNQDP8I8Vc4ge1fouZF56fBPfhn+8QDLLiX/kCIHewKd+otJiIJoMB\n'
|
||||
+ '78yTLvq+klkINgKAAsTCHmT5MtMxAiEAkFE70ms8C73JvTkd0znq8H6fBJV0iZxQ\n'
|
||||
+ 'qOXON8bzv8A=\n'
|
||||
+ '-----END PRIVATE KEY-----\n';
|
||||
expect (() => crypto.asym_decrypt (data, key))
|
||||
.toThrow ();
|
||||
});
|
||||
|
||||
it ('should throw on invalid decryption data', () => {
|
||||
const data = 'EHsGr2eSkqZKTX1U9Qj4crGRFkk299kmxhiiO3fyaIS'
|
||||
+ 'olB9+UYDdqrwcf/INwNddW4AzjA2Kf4dYaXIRLZsU1Q==';
|
||||
const key = '-----BEGIN PRIVATE KEY-----\n'
|
||||
+ 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAxryi2qtUgfwU86HE\n'
|
||||
+ 'eGahja/Hc9cpccVKQ53ArtAv2sjhj5wopQdCxhHaiqzkZbGKSGg7y7+sepPIkoOg\n'
|
||||
+ 'P07MmwIDAQABAkBKIk3hoi24+07ZfwuqGibDksGlLarxHLZSOMOKsnBXfRRyGqMr\n'
|
||||
+ '/Z+qtQ9VPRWHBzGHZ9rXAVKa8gnRirik+ez5AiEA/XL6tOy92Yvxm46ewswmZ7ab\n'
|
||||
+ 'V1KvChsXziaRj5eLzacCIQDIvLBO8og5Ng4r7E/dOAYrvzOLFqlN5UCuCRZzuFpv\n'
|
||||
+ '7QIgCnj5ywgNQDP8I8Vc4ge1fouZF56fBPfhn+8QDLLiX/kCIHewKd+otJiIJoMB\n'
|
||||
+ '78yTLvq+klkINgKAAsTCHmT5MtMxAiEAkFE70ms8C73JvTkd0znq8H6fBJV0iZxQ\n'
|
||||
+ 'qOXON8bzv8A=\n'
|
||||
+ '-----END PRIVATE KEY-----\n';
|
||||
expect (() => crypto.asym_decrypt (data, key))
|
||||
.toThrow ();
|
||||
});
|
||||
|
||||
it ('should create a signature and verify it', async () => {
|
||||
const data = 'foobar';
|
||||
const k = await crypto.generate_keypair (key_length);
|
||||
const signature = crypto.asym_sign (data, k.private_key);
|
||||
expect (typeof signature)
|
||||
.toEqual ('string');
|
||||
expect (signature)
|
||||
.toMatch (/^[a-f0-9]+$/ui);
|
||||
expect (crypto.asym_verify (data, k.public_key, signature))
|
||||
.toBeTrue ();
|
||||
});
|
||||
|
||||
it ('should throw on invalid sign key', () => {
|
||||
const key = '-----BEGIN PRIVATE KEY-----\n'
|
||||
+ 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAl4RZveQ8IXHPZTUf\n'
|
||||
+ 'djwgDxIB5444yFvhIRasdasdasdApz+FmsXxGCatnPUCIHO9P1EfxasdaIq/Lpng\n'
|
||||
+ 'y2ZQh2IaDYxC7K7tvGZwSY/CEcGfAiAcNgsg5ZMIQOWxn2KbFM81ne3b5FzD3Ozh\n'
|
||||
+ 'GxItcBfKuw==\n'
|
||||
+ '-----END PRIVATE KEY-----\n';
|
||||
const data = 'foobar';
|
||||
expect (() => crypto.asym_sign (data, key))
|
||||
.toThrow ();
|
||||
});
|
||||
|
||||
it ('should throw on invalid verify key', () => {
|
||||
const key = '-----BEGIN RSA PUBLIC KEY-----\n'
|
||||
+ 'MEgCQQCXhFm95DwDcc9lNasdasdasdasdasdHhEqigZupsWUxX/3tKn9tvEKV/\n'
|
||||
+ 'zjoENWN63aorN+O+5MxDZMnEk+z9AgMBAAE=\n'
|
||||
+ '-----END RSA PUBLIC KEY-----\n';
|
||||
const data = 'foobar';
|
||||
const signature = '3433ef165d6be80430e1107be0d7183bee769dbb38ea7d2737'
|
||||
+ '1429c853fcab78bf1d3256fc16ee93a38cfd4ae79a74748e59fe9e9a65400c720d'
|
||||
+ 'adb2dbcc1fa3';
|
||||
expect (() => crypto.asym_verify (data, key, signature))
|
||||
.toThrow ();
|
||||
});
|
||||
|
||||
it ('should not throw on invalid data or signature', () => {
|
||||
const key = '-----BEGIN RSA PUBLIC KEY-----\n'
|
||||
+ 'MEgCQQC+9nw80cG+AsZ2euIZx4ptmUykJgEUgs4JiEvC+IaiIRAd9zGc0TcQAeND\n'
|
||||
+ '171lw77kE02KJ4ARl1hkcLCW2bIrAgMBAAE=\n'
|
||||
+ '-----END RSA PUBLIC KEY-----\n';
|
||||
const data = 'foobar';
|
||||
const signature = '6bae51b0449d71ca2e04099268bd0f6506a5dfc6f810bd72d'
|
||||
+ '47865574a99910e404e5856da650cd45ee88365a2511fcc0866a0b5d1faf15c067'
|
||||
+ 'ab8a4427554bf';
|
||||
expect (crypto.asym_verify (data, key, signature))
|
||||
.toBeTrue ();
|
||||
expect (crypto.asym_verify (data.replace ('b', 'c'), key, signature))
|
||||
.toBeFalse ();
|
||||
expect (crypto.asym_verify (data, key, signature.replace ('f', 'e')))
|
||||
.toBeFalse ();
|
||||
});
|
||||
});
|
@ -1,17 +1,10 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of crypto-helper which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
'use strict';
|
||||
|
||||
const crypto = require ('../../index');
|
||||
const rsa = require ('../../lib/rsa');
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function, max-statements
|
||||
describe ('crypto helper', () => {
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
describe ('signatures', () => {
|
||||
beforeEach (() => {
|
||||
jasmine.clock ()
|
||||
.install ();
|
||||
@ -25,95 +18,6 @@ describe ('crypto helper', () => {
|
||||
.uninstall ();
|
||||
});
|
||||
|
||||
it ('random_hex', () => {
|
||||
const hex = crypto.random_hex (16);
|
||||
expect (hex.length)
|
||||
.toEqual (16);
|
||||
expect (hex)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
|
||||
it ('random_hex with default length', () => {
|
||||
const hex = crypto.random_hex ();
|
||||
expect (hex.length)
|
||||
.toEqual (8);
|
||||
expect (hex)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
|
||||
it ('random_hex should refuse length smaller 1', () => {
|
||||
expect (
|
||||
() => (crypto.random_hex (0))
|
||||
)
|
||||
.toThrowError ('invalid length');
|
||||
});
|
||||
|
||||
it ('random_hex should always return correct length', () => {
|
||||
for (let i = 1; i < 32; i++) {
|
||||
const hex = crypto.random_hex (i);
|
||||
expect (hex.length)
|
||||
.toEqual (i);
|
||||
}
|
||||
});
|
||||
|
||||
it ('random_string', () => {
|
||||
const str = crypto.random_string (16);
|
||||
expect (str.length)
|
||||
.toEqual (16);
|
||||
});
|
||||
|
||||
it ('random_string with default length', () => {
|
||||
const str = crypto.random_string ();
|
||||
expect (str.length)
|
||||
.toEqual (8);
|
||||
});
|
||||
|
||||
it ('random_string should refuse length smaller 1', () => {
|
||||
expect (
|
||||
() => (crypto.random_string (0))
|
||||
)
|
||||
.toThrowError ('invalid length');
|
||||
});
|
||||
|
||||
it ('random_string should always return correct length', () => {
|
||||
for (let i = 1; i < 32; i++) {
|
||||
const str = crypto.random_string (i);
|
||||
expect (str.length)
|
||||
.toEqual (i);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it ('hash_sha512', () => {
|
||||
const hash = crypto.hash_sha512 ('a', 'b');
|
||||
expect (
|
||||
hash
|
||||
)
|
||||
.toEqual (
|
||||
// eslint-disable-next-line max-len
|
||||
'2d408a0717ec188158278a796c689044361dc6fdde28d6f04973b80896e1823975cdbf12eb63f9e0591328ee235d80e9b5bf1aa6a44f4617ff3caf6400eb172d'
|
||||
);
|
||||
});
|
||||
|
||||
it ('checksum', () => {
|
||||
const hash = crypto.checksum ('foo');
|
||||
expect (
|
||||
hash
|
||||
)
|
||||
.toEqual (
|
||||
// eslint-disable-next-line max-len
|
||||
'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
||||
);
|
||||
});
|
||||
|
||||
it ('create_salt', () => {
|
||||
const salt = crypto.create_salt ();
|
||||
expect (salt.length)
|
||||
.toEqual (64);
|
||||
expect (salt)
|
||||
.toMatch (/^[0-9a-f]+$/iu);
|
||||
});
|
||||
|
||||
it ('sign_object', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
expect (() => {
|
||||
@ -123,6 +27,59 @@ describe ('crypto helper', () => {
|
||||
}).not.toThrow ();
|
||||
});
|
||||
|
||||
it ('sign_object with rsa key', async () => {
|
||||
const obj = { foo: 'bar' };
|
||||
const k = await rsa.generate_keypair ();
|
||||
expect (() => {
|
||||
const str = crypto.sign_object (obj, k.private_key);
|
||||
expect (typeof str)
|
||||
.toEqual ('string');
|
||||
}).not.toThrow ();
|
||||
});
|
||||
|
||||
it ('verify_signature with rsa key', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
const str = 'U1GcsN3yZzSKxPH8jhCGTKiswfazB9rMfUtE5351LT11t6EmS7xfPjnt'
|
||||
+ '.5ytniC6q2ovoF7ZqbD8qk9r2kjjAcA9EYhLwC3wwJKPPsKdHSTFd7d9TzBP1skQ98X'
|
||||
+ 'LjRUkc2M8M84LmWLg76EvcY2pw6HwsFvCUoZYcKAJp3vkp9MQVrVYdHKMPkBjQKyy2V'
|
||||
+ 'KtEZiBsomBVJd6Hudd1YLMQ4J4s52iHsegDswKE9djYVEmgKkJUAiZJ2viFHw3fBbp2'
|
||||
+ 'Abo2Dm5oqYtw7Nn9RFstW3CcNQHV1PzHDKD56Uw3opuYwVZhQth8ux2CdkC2yMvgVsT'
|
||||
+ 'dUyCuu78ugaGvzsMXCbe2BzaPFDTE9JYtMcDFFP43nUGHNd6cWwzoKTZBX852Exz6Rb'
|
||||
+ 'VjcWUvL81dLPBLJV.2';
|
||||
const key = '-----BEGIN RSA PUBLIC KEY-----\n'
|
||||
+ 'MIIBCgKCAQEA4LCEoJYNwwksuzPESpmPziHp98WhY5Qml6RiN9uxrKGPV6QwwmDQ\n'
|
||||
+ 'ks6C+ZfYbFG9NCx1MEuWL0Tvp/6ZBhMyaJrI5iwo0CmSX3WdFcbXmdl0l6N1+5r7\n'
|
||||
+ 'l3SkKsr/AX4gwcDor4dYuLEv5KawGdfcP0IxsoAcIN1UJ5HJ+eheB3fVcSh/IIBf\n'
|
||||
+ 'O+cL/4Chw8eAaDBG5mZ1Xgd4gIjJGYAxgUNvaShGzs8k1y+jqjD5IkZ1h9dgoGJG\n'
|
||||
+ 'dUmjCLWrOzx8SqdqJYmQJX+6GNswnvVF30bkW+/MJZF/P2jLFtSa24Monh7axIqx\n'
|
||||
+ '8HG0xDw1Z98WV9oQh/vDP/KAs1cPp0AJlwIDAQAB\n'
|
||||
+ '-----END RSA PUBLIC KEY-----\n';
|
||||
const ver = crypto.verify_signature (str, key);
|
||||
expect (ver)
|
||||
.toEqual (obj);
|
||||
});
|
||||
|
||||
it ('verify_signature reject with rsa key', () => {
|
||||
const str = 'U1GcsN3yZzSKxPH8jhCGTKiswfazB9rMfUtE5351LT11t6EmS7xfPjnt'
|
||||
+ '.5ytniC6q2ovoF7ZqbD8qk9r2kjjAcA9EYhLwC3wwJKPPsKdHSTFd7d9TzBP1skQ98X'
|
||||
+ 'LjRUkc2M8M84LmWLg76EvcY2pw6HwsFvCUoZYcKAJp3vkp9MQVrVYdHKMPkBjQKyy2V'
|
||||
+ 'KtEZiBsomBVJd6Hudd1YLMQ4J4s52iHsegDswKE9djYVEmgKkJUAiZJ2viFHw3fBbp2'
|
||||
+ 'Abo2Dm5oqYtw7Nn9RFstW3CcNQHV1PzHDKD56Uw3opuYwVZhQth8ux2CdkC2yMvgVsT'
|
||||
+ 'dUyCuu78ugaGvzsMXCbe2BzaPFDTE9JYtMcDFFP43nUGHNd6cWwzoKTZBX852Exz6Rb'
|
||||
+ 'VjcWUvL81dLPBLJA.2';
|
||||
const key = '-----BEGIN RSA PUBLIC KEY-----\n'
|
||||
+ 'MIIBCgKCAQEA4LCEoJYNwwksuzPESpmPziHp98WhY5Qml6RiN9uxrKGPV6QwwmDQ\n'
|
||||
+ 'ks6C+ZfYbFG9NCx1MEuWL0Tvp/6ZBhMyaJrI5iwo0CmSX3WdFcbXmdl0l6N1+5r7\n'
|
||||
+ 'l3SkKsr/AX4gwcDor4dYuLEv5KawGdfcP0IxsoAcIN1UJ5HJ+eheB3fVcSh/IIBf\n'
|
||||
+ 'O+cL/4Chw8eAaDBG5mZ1Xgd4gIjJGYAxgUNvaShGzs8k1y+jqjD5IkZ1h9dgoGJG\n'
|
||||
+ 'dUmjCLWrOzx8SqdqJYmQJX+6GNswnvVF30bkW+/MJZF/P2jLFtSa24Monh7axIqx\n'
|
||||
+ '8HG0xDw1Z98WV9oQh/vDP/KAs1cPp0AJlwIDAQAB\n'
|
||||
+ '-----END RSA PUBLIC KEY-----\n';
|
||||
const ver = crypto.verify_signature (str, key);
|
||||
expect (ver)
|
||||
.toBeNull ();
|
||||
});
|
||||
|
||||
it ('should sign object with key info', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
expect (() => {
|
Reference in New Issue
Block a user