UNPKG

yarle-evernote-to-md

Version:

Yet Another Rope Ladder from Evernote

76 lines (65 loc) 2.73 kB
var CryptoJS = require("crypto-js"); import * as crypto from 'crypto'; import * as base64 from 'base64-js'; // PBKDF2 implementation (modified for SHA256 support) function pbkdf2(password: string, salt: Uint8Array, iterations: number, keyLength: number): Buffer { return crypto.pbkdf2Sync(password, salt, iterations, keyLength, 'sha256'); } // HMAC implementation function hmacSHA256(key: Buffer, data: Uint8Array): Buffer { const hmac = crypto.createHmac('sha256', key); hmac.update(data); return hmac.digest(); } // AES decryption function decryptAES(ciphertext: Uint8Array, key: Buffer, iv: Uint8Array): Buffer { const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv); let decrypted = decipher.update(ciphertext); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted; } interface EncryptedData { salt: Uint8Array, saltHmac: Uint8Array, iv: Uint8Array, cipherText: Uint8Array, body: Uint8Array, bodyHmac: Uint8Array } const extractDataFromEncryptedByteArray = (data: Uint8Array):EncryptedData => { const START_INDEX = 4; const TWO_BYTES = 16; const START_SALTHMAC = START_INDEX + TWO_BYTES; const START_IV = START_SALTHMAC + TWO_BYTES; const START_CIPHERTEXT = START_IV + TWO_BYTES; const FOUR_END_BYTES = -32 return { salt: data.subarray(START_INDEX, START_SALTHMAC), saltHmac: data.subarray(START_SALTHMAC, START_IV), iv: data.subarray(START_IV, START_CIPHERTEXT), cipherText: data.subarray(START_CIPHERTEXT, FOUR_END_BYTES), body: data.subarray(0, FOUR_END_BYTES), bodyHmac: data.subarray(FOUR_END_BYTES) } } export const performDecryption = (encryptedText: string, passwords: Array<string>): string => { try{ const encryptedDataByteArr = base64.toByteArray(encryptedText); const encryptedData = extractDataFromEncryptedByteArray(encryptedDataByteArr); // Use the password to generate a digest for the encrypted body // If it matches the existing digest, assume the password is correct for (const password of passwords){ const keyhmac = pbkdf2(password, encryptedData.saltHmac, 50000, 16); const testhmac = hmacSHA256(keyhmac, encryptedData.body); const matchHmac = crypto.timingSafeEqual(testhmac, encryptedData.bodyHmac); if (matchHmac) { const key = pbkdf2(password, encryptedData.salt, 50000, 16); const decrypted = decryptAES(encryptedData.cipherText, key, encryptedData.iv); return decrypted.toString() } } }catch(e: any){ console.log(e.message) } return encryptedText; }