UNPKG

1.96 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const DEFAULT_HASH_METHOD = 'sha256';
7const DEFAULT_HASH_LENGTH = 64;
8const DEFAULT_SALT_LENGTH = 8;
9const HEX_REGEX = /^[a-f0-9]+$/;
10
11module.exports = class SecurityHelper {
12
13 static isHexString (data) {
14 return HEX_REGEX.test(data)
15 }
16
17 static getRandomString (length) {
18 if (isNaN(length)) {
19 throw new Error('Length must be a number');
20 }
21 return crypto.randomBytes(length).toString('hex');
22 }
23
24 static createSalt (length = DEFAULT_SALT_LENGTH) {
25 if (length % 2) {
26 throw new Error('length must be a multiple of 2');
27 }
28 return crypto.randomBytes(length / 2).toString('hex');
29 }
30
31 static extractSalt (hash, length = DEFAULT_HASH_LENGTH) {
32 return hash.substring(length);
33 }
34
35 static hashPassword (password) {
36 return !password ? '' : this.hashValue(password, this.createSalt());
37 }
38
39 static hashValue (value, salt, method = DEFAULT_HASH_METHOD) {
40 return crypto.createHmac(method, salt).update(value).digest('hex') + salt;
41 }
42
43 static async hashFile (file, method = DEFAULT_HASH_METHOD) {
44 const data = await fs.promises.readFile(file);
45 return crypto.createHash(method).update(data).digest('hex');
46 }
47
48 static checkHash (hash, hashLength = DEFAULT_HASH_LENGTH, saltLength = DEFAULT_SALT_LENGTH) {
49 return typeof hash === 'string'
50 && hash.length === hashLength + saltLength
51 && this.isHexString(hash);
52 }
53
54 static checkPassword (password, hash) {
55 if (typeof password !== 'string' || !password || !this.checkHash(hash)) {
56 return false;
57 }
58 return this.hashValue(password, this.extractSalt(hash)) === hash;
59 }
60};
61
62const crypto = require('crypto');
63const fs = require('fs');
\No newline at end of file