"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const MD5 = require('js-md5');
const crypto_1 = require("./crypto");
const crypto_2 = require("crypto");
function addPadding(b, k) {
    const padLen = k - (b.length % k);
    const paddingBytes = Buffer.alloc(padLen);
    paddingBytes.fill(padLen);
    return Buffer.concat([b, paddingBytes]);
}
const saltPrefix = Buffer.from('Salted__');
function encrypt(input, secret) {
    return __awaiter(this, void 0, void 0, function* () {
        const salt = crypto_1.randomBytes(8);
        const pbe = generateKey(secret, salt);
        const saltBlock = Buffer.concat([saltPrefix, salt]);
        const cipher = crypto_2.createCipheriv('aes-256-cbc', pbe.key, pbe.iv);
        const enc = cipher.update(input, 'utf8');
        return Buffer.concat([saltBlock, enc, cipher.final()]);
    });
}
exports.encrypt = encrypt;
function decrypt(cipherText, secret) {
    return __awaiter(this, void 0, void 0, function* () {
        const salt = cipherText.slice(8, 16);
        const data = cipherText.slice(16);
        const pbe = generateKey(secret, salt);
        const cipher = crypto_2.createDecipheriv('aes-256-cbc', pbe.key, pbe.iv);
        let dec = cipher.update(data);
        return Buffer.concat([dec, cipher.final()]);
    });
}
exports.decrypt = decrypt;
function md5(buffer) {
    const hash = MD5.array(buffer);
    return Buffer.from(hash);
}
function mergeBuffer(array1, array2) {
    const mergedArray = Buffer.alloc(array1.length + array2.length);
    mergedArray.set(array1);
    mergedArray.set(array2, array1.length);
    return mergedArray;
}
exports.mergeBuffer = mergeBuffer;
function generateKey(secret, salt) {
    const md5Hash = [];
    const data00 = mergeBuffer(secret, salt);
    md5Hash[0] = md5(data00);
    let result = md5Hash[0];
    for (let i = 1; i < 3; i += 1) {
        md5Hash[i] = md5(mergeBuffer(md5Hash[i - 1], data00));
        result = mergeBuffer(result, md5Hash[i]);
    }
    return {
        key: result.slice(0, 32),
        iv: result.slice(32, 48),
    };
}
