UNPKG

kaven-utils

Version:

Utils for Node.js.

129 lines (128 loc) 6.41 kB
/******************************************************************** * @author: Kaven * @email: kaven@wuwenkai.com * @website: http://blog.kaven.xyz * @file: [Kaven-Utils] /src/KavenUtility.Crypto.ts * @create: 2020-07-11 09:17:40.793 * @modify: 2025-10-14 22:58:04.821 * @version: 6.1.0 * @times: 23 * @lines: 183 * @copyright: Copyright © 2020-2025 Kaven. All Rights Reserved. * @description: [description] * @license: [license] ********************************************************************/ import { GeneratePassword, String2StringArray, StringArray2String, Strings_DoubleQuotes, SurroundBy } from "kaven-basic"; import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "node:crypto"; import { GeneratedCertificateFiles } from "./GeneratedCertificateFiles.js"; import { Execute } from "./KavenUtility.ChildProcess.js"; import { AppendPathThenCreateParentDirectory } from "./KavenUtility.FileSystem.js"; import { CertificateSubjectToString } from "./KavenUtility.js"; /** * @since 2.0.7 * @version 2020-07-11 */ export function GenerateEncryptPassword(keySize = 32, ivSize = 16) { // Use the async `scrypt()` instead. const key = scryptSync(GeneratePassword(32), GeneratePassword(32), keySize); // Use `randomBytes` to generate a random iv instead of the static iv // shown here. const iv = randomBytes(ivSize); // Buffer.alloc(16, 0); // Initialization vector. return StringArray2String(key.toString("hex"), iv.toString("hex")); } /** * * @param str some clear text data * @param password Password used to generate key, use `GenerateEncryptPassword` to generate it. * @param algorithm * @since 2.0.7 * @version 2020-07-11 */ export function EncryptString(str, password, algorithm = "aes-256-cbc") { const strArray = String2StringArray(password); if (strArray && strArray.length === 2) { const key = Buffer.from(strArray[0], "hex"); const iv = Buffer.from(strArray[1], "hex"); const cipher = createCipheriv(algorithm, key, iv); let encrypted = cipher.update(str, "utf8", "hex"); encrypted += cipher.final("hex"); return encrypted; } throw new Error("Invalid Password"); } /** * * @param encryptedStr * @param password Password used to generate key * @param algorithm * @since 2.0.7 * @version 2020-07-11 */ export function DecryptString(encryptedStr, password, algorithm = "aes-256-cbc") { const strArray = String2StringArray(password); if (strArray && strArray.length === 2) { const key = Buffer.from(strArray[0], "hex"); const iv = Buffer.from(strArray[1], "hex"); const decipher = createDecipheriv(algorithm, key, iv); let decrypted = decipher.update(encryptedStr, "hex", "utf8"); decrypted += decipher.final("utf8"); return decrypted; } throw new Error("Invalid Password"); } /** * Please make sure you have `openssl` already installed on your system/container. * @param options * @since 4.1.0 * @version 2025-10-13 */ export async function GenerateCertificate(options) { options ??= {}; options.caKey = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.caKey ?? "ca-key.pem"); options.caCert = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.caCert ?? "ca-cert.pem"); options.serverKey = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.serverKey ?? "server-key.pem"); options.serverReq = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.serverReq ?? "server-req.pem"); options.serverCert = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.serverCert ?? "server-cert.pem"); options.clientKey = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.clientKey ?? "client-key.pem"); options.clientReq = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.clientReq ?? "client-req.pem"); options.clientCert = AppendPathThenCreateParentDirectory(options.certGenerateDir, options.clientCert ?? "client-cert.pem"); options.size = options?.size ?? 2048; options.days = options?.days ?? 365; let openssl = "openssl"; if (options.openssl) { openssl = `"${openssl}"`; } let { caKey, caCert, serverKey, serverReq, serverCert, clientKey, clientReq, clientCert, } = options; caKey = SurroundBy(caKey, Strings_DoubleQuotes); caCert = SurroundBy(caCert, Strings_DoubleQuotes); serverKey = SurroundBy(serverKey, Strings_DoubleQuotes); serverReq = SurroundBy(serverReq, Strings_DoubleQuotes); serverCert = SurroundBy(serverCert, Strings_DoubleQuotes); clientKey = SurroundBy(clientKey, Strings_DoubleQuotes); clientReq = SurroundBy(clientReq, Strings_DoubleQuotes); clientCert = SurroundBy(clientCert, Strings_DoubleQuotes); const commands = [ // 1. Creating the Certificate Authority's Certificate and Keys // Generate a private key for the CA `${openssl} genrsa -out ${caKey} ${options.size}`, // Generate the X509 certificate for the CA `${openssl} req -new -x509 -nodes -days ${options.days} -key ${caKey} -out ${caCert} ${CertificateSubjectToString(options.caSubj)}`, // 2. Creating the Server's Certificate and Keys // Generate the private key and certificate request `${openssl} req -newkey rsa:${options.size} -nodes -keyout ${serverKey} -out ${serverReq} ${CertificateSubjectToString(options?.serverSubj)}`, // Generate the X509 certificate for the server `${openssl} x509 -req -days ${options.days} -in ${serverReq} -out ${serverCert} -CA ${caCert} -CAkey ${caKey}`, // 3. Creating the Client's Certificate and Keys // Generate the private key and certificate request `${openssl} req -newkey rsa:${options.size} -nodes -keyout ${clientKey} -out ${clientReq} ${CertificateSubjectToString(options?.clientSubj)}`, // Generate the X509 certificate for the server `${openssl} x509 -req -days ${options.days} -in ${clientReq} -out ${clientCert} -CA ${caCert} -CAkey ${caKey}`, ]; for (const command of commands) { await Execute(command, { logger: options.logger, }); } const result = new GeneratedCertificateFiles(options); return result; }