From a9d80bef8fec4f1ab2ece7fa0b5195ab58c61521 Mon Sep 17 00:00:00 2001 From: fyears Date: Tue, 2 Nov 2021 02:39:24 +0800 Subject: [PATCH] yes encryption! --- package.json | 2 + src/encrypt.ts | 117 +++++++++++++++++++++++++++++-------------------- src/misc.ts | 8 ++++ 3 files changed, 79 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index e89f1f9..c6fabdb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "author": "", "license": "Apache-2.0", "devDependencies": { + "@types/crypto-js": "^4.0.2", "@types/node": "^14.14.37", "prettier": "^2.4.1", "terser-webpack-plugin": "^5.2.4", @@ -36,6 +37,7 @@ "console-browserify": "^1.2.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", + "crypto-js": "^4.1.1", "domain-browser": "^4.22.0", "events": "^3.3.0", "hi-base32": "^0.5.1", diff --git a/src/encrypt.ts b/src/encrypt.ts index 8e99d15..ff0c035 100644 --- a/src/encrypt.ts +++ b/src/encrypt.ts @@ -1,54 +1,65 @@ -import * as crypto from "crypto"; +import * as CryptoJS from "crypto-js"; import * as base32 from "hi-base32"; -import { bufferToArrayBuffer, arrayBufferToBuffer } from "./misc"; - +import { + bufferToArrayBuffer, + arrayBufferToBuffer, + arrayBufferToBase64, + base64ToArrayBuffer, +} from "./misc"; const DEFAULT_ITER = 10000; -export const encryptBuffer = ( - buf: Buffer, +export const encryptWordArray = ( + wa: CryptoJS.lib.WordArray, password: string, rounds: number = DEFAULT_ITER ) => { - const salt = crypto.randomBytes(8); - const derivedKey = crypto.pbkdf2Sync( - password, - salt, - rounds, - 32 + 16, - "sha256" + const prefix = CryptoJS.enc.Utf8.parse("Salted__"); + const salt = CryptoJS.lib.WordArray.random(8); + const derivedKey = CryptoJS.PBKDF2(password, salt, { + keySize: 32 + 16, + iterations: rounds, + hasher: CryptoJS.algo.SHA256, + }); + const key = CryptoJS.lib.WordArray.create(derivedKey.words.slice(0, 32 / 4)); + const iv = CryptoJS.lib.WordArray.create( + derivedKey.words.slice(32 / 4, (32 + 16) / 4) ); - const key = derivedKey.slice(0, 32); - const iv = derivedKey.slice(32, 32 + 16); - const cipher = crypto.createCipheriv("aes-256-cbc", key, iv); - cipher.write(buf); - cipher.end(); - const encrypted = cipher.read(); - const res = Buffer.concat([Buffer.from("Salted__"), salt, encrypted]); + const encrypted = CryptoJS.AES.encrypt(wa, key, { iv: iv }).ciphertext; + const res = CryptoJS.lib.WordArray.create() + .concat(prefix) + .concat(salt) + .concat(encrypted); return res; }; -export const decryptBuffer = ( - buf: Buffer, +export const decryptWordArray = ( + wa: CryptoJS.lib.WordArray, password: string, rounds: number = DEFAULT_ITER ) => { - const prefix = buf.slice(0, 8); - const salt = buf.slice(8, 16); - const derivedKey = crypto.pbkdf2Sync( - password, - salt, - rounds, - 32 + 16, - "sha256" + const prefix = CryptoJS.lib.WordArray.create(wa.words.slice(0, 8 / 4)); + + const salt = CryptoJS.lib.WordArray.create( + wa.words.slice(8 / 4, (8 + 8) / 4) ); - const key = derivedKey.slice(0, 32); - const iv = derivedKey.slice(32, 32 + 16); - const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv); - decipher.write(buf.slice(16)); - decipher.end(); - const decrypted = decipher.read(); - return decrypted as Buffer; + const derivedKey = CryptoJS.PBKDF2(password, salt, { + keySize: 32 + 16, + iterations: rounds, + hasher: CryptoJS.algo.SHA256, + }); + const key = CryptoJS.lib.WordArray.create(derivedKey.words.slice(0, 32 / 4)); + const iv = CryptoJS.lib.WordArray.create( + derivedKey.words.slice(32 / 4, 32 / 4 + 16 / 4) + ); + const decrypted = CryptoJS.AES.decrypt( + CryptoJS.lib.CipherParams.create({ + ciphertext: CryptoJS.lib.WordArray.create(wa.words.slice((8 + 8) / 4)), + }), + key, + { iv: iv } + ); + return decrypted; }; export const encryptArrayBuffer = ( @@ -56,9 +67,12 @@ export const encryptArrayBuffer = ( password: string, rounds: number = DEFAULT_ITER ) => { - return bufferToArrayBuffer( - encryptBuffer(arrayBufferToBuffer(arrBuf), password, rounds) - ); + const b64 = arrayBufferToBase64(arrBuf); + const wa = CryptoJS.enc.Base64.parse(b64); + const enc = encryptWordArray(wa, password, rounds); + const resb64 = CryptoJS.enc.Base64.stringify(enc); + const res = base64ToArrayBuffer(resb64); + return res; }; export const decryptArrayBuffer = ( @@ -66,9 +80,12 @@ export const decryptArrayBuffer = ( password: string, rounds: number = DEFAULT_ITER ) => { - return bufferToArrayBuffer( - decryptBuffer(arrayBufferToBuffer(arrBuf), password, rounds) - ); + const b64 = arrayBufferToBase64(arrBuf); + const wa = CryptoJS.enc.Base64.parse(b64); + const dec = decryptWordArray(wa, password, rounds); + const resb64 = CryptoJS.enc.Base64.stringify(dec); + const res = base64ToArrayBuffer(resb64); + return res; }; export const encryptStringToBase32 = ( @@ -76,7 +93,11 @@ export const encryptStringToBase32 = ( password: string, rounds: number = DEFAULT_ITER ) => { - return base32.encode(encryptBuffer(Buffer.from(text), password, rounds)); + const wa = CryptoJS.enc.Utf8.parse(text); + const enc = encryptWordArray(wa, password, rounds); + const enctext = CryptoJS.enc.Base64.stringify(enc); + const res = base32.encode(base64ToArrayBuffer(enctext)); + return res; }; export const decryptBase32ToString = ( @@ -84,9 +105,9 @@ export const decryptBase32ToString = ( password: string, rounds: number = DEFAULT_ITER ) => { - return decryptBuffer( - Buffer.from(base32.decode.asBytes(text)), - password, - rounds - ).toString(); + const enc = Buffer.from(base32.decode.asBytes(text)).toString("base64"); + const wa = CryptoJS.enc.Base64.parse(enc); + const dec = decryptWordArray(wa, password, rounds); + const dectext = CryptoJS.enc.Utf8.stringify(dec); + return dectext; }; diff --git a/src/misc.ts b/src/misc.ts index b94d639..00419e1 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -58,3 +58,11 @@ export const bufferToArrayBuffer = (b: Buffer) => { export const arrayBufferToBuffer = (b: ArrayBuffer) => { return Buffer.from(b); }; + +export const arrayBufferToBase64 = (b: ArrayBuffer) => { + return arrayBufferToBuffer(b).toString("base64"); +}; + +export const base64ToArrayBuffer = (b64text: string) => { + return bufferToArrayBuffer(Buffer.from(b64text, "base64")); +};