UNPKG

@lakutata/core

Version:

Lakutata Framework Core

274 lines (252 loc) 6.29 kB
import stringRandom from 'string-random' import { AES, enc, HmacMD5, HmacSHA1, HmacSHA224, HmacSHA256, HmacSHA3, HmacSHA384, HmacSHA512, MD5, SHA1, SHA224, SHA256, SHA3, SHA384, SHA512 } from 'crypto-js' import sortKeys from 'sort-keys' import {compare, compareSync, genSalt, genSaltSync, hash, hashSync} from 'bcryptjs' import {Plugin} from '../base/Plugin' import {JSON} from './JSON' import {Crypto} from './Crypto' import {Configurable, Inject} from '../decorators/DependencyInjection' declare module '../Core' { interface Application { Security: Security } } export class Security extends Plugin { @Inject('JSON') private readonly JSON: JSON @Inject('Crypto') private readonly Crypto: Crypto /** * 盐值 * @type {number} * @protected */ @Configurable() protected readonly saltRound: number = 8 /** * 将数据转换为字符串 * @param data * @returns {string} * @protected */ protected stringifyData(data: any): string { return typeof data === 'string' ? data : this.JSON.stringify(sortKeys(this.JSON.parse(this.JSON.stringify(data)), {deep: true})) } /** * 生成随机字符串 * @param {number} length * @param {{numbers: boolean | string, letters: boolean | string, specials: boolean | string}} options * @returns {string} */ public generateRandomString(length: number = 16, options: { numbers: boolean | string, letters: boolean | string, specials: boolean | string } = { numbers: true, letters: true, specials: false }): string { return stringRandom(length, { numbers: options.numbers === undefined ? true : options.numbers, letters: options.letters === undefined ? true : options.letters, specials: options.specials === undefined ? false : options.specials }) } /** * 计算MD5哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public MD5(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacMD5(stringData, key).toString() } else { return MD5(stringData).toString() } } /** * 计算SHA1哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA1(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA1(stringData, key).toString() } else { return SHA1(stringData).toString() } } /** * 计算SHA3哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA3(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA3(stringData, key).toString() } else { return SHA3(stringData).toString() } } /** * 计算SHA224哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA224(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA224(stringData, key).toString() } else { return SHA224(stringData).toString() } } /** * 计算SHA256哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA256(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA256(stringData, key).toString() } else { return SHA256(stringData).toString() } } /** * 计算SHA384哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA384(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA384(stringData, key).toString() } else { return SHA384(stringData).toString() } } /** * 计算SHA512哈希值 * @param data * @param {string} key * @returns {string} * @constructor */ public SHA512(data: any, key?: string): string { const stringData: string = this.stringifyData(data) if (key) { return HmacSHA512(stringData, key).toString() } else { return SHA512(stringData).toString() } } /** * 使用密码加密数据 * @param data * @param {string} password * @returns {string} */ public encryptByPassword<T = any>(data: T, password: string): string { const stringData: string = this.stringifyData(data) return AES.encrypt(stringData, password).toString() } /** * 使用密码解密数据 * @param {string} ciphertext * @param {string} password * @returns {T} */ public decryptByPassword<T = any>(ciphertext: string, password: string): T { const decryptString: string = AES.decrypt(ciphertext, password).toString(enc.Utf8) try { return this.JSON.parse(decryptString) } catch (e) { return decryptString as any } } /** * 使用密钥加密数据 * @param {T} data * @param {string} secretKey * @returns {string} */ public encryptByKey<T = any>(data: T, secretKey: string): string { return this.Crypto.encrypt(data, secretKey) } /** * 使用密钥解密数据 * @param {string} ciphertext * @param {string} secretKey * @returns {T} */ public decryptByKey<T = any>(ciphertext: string, secretKey: string): T { return this.Crypto.decrypt(ciphertext, secretKey) } /** * 生成带盐值的密码哈希 * @param {string} password * @returns {string} */ public generatePasswordHashSync(password: string): string { const salt: string = genSaltSync(this.saltRound) return hashSync(password, salt) } /** * 异步生成带盐值的密码哈希 * @param {string} password * @returns {Promise<string>} */ public async generatePasswordHash(password: string): Promise<string> { const salt: string = await genSalt(this.saltRound) return await hash(password, salt) } /** * 验证密码与哈希是否匹配 * @param {string} password * @param {string} hash * @returns {boolean} */ public validatePasswordSync(password: string, hash: string): boolean { return compareSync(password, hash) } /** * 异步验证密码与哈希是否匹配 * @param {string} password * @param {string} hash * @returns {Promise<boolean>} */ public async validatePassword(password: string, hash: string): Promise<boolean> { return await compare(password, hash) } }