"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.aesCbcEncryptBase64 = aesCbcEncryptBase64;
exports.aesCbcDecryptBase64 = aesCbcDecryptBase64;
exports.aesCbcEncryptBase64Hex = aesCbcEncryptBase64Hex;
exports.aesCbcDecryptBase64ToHex = aesCbcDecryptBase64ToHex;
const crypto = __importStar(require("crypto"));
const logger_1 = require("./logger");
const IV_MAC_PREFIX = '01010101010101010101';
/**
 * PKCS7 填充
 * @param data 需要填充的数据
 * @param blockSize 块大小，默认 16
 * @returns 填充后的数据
 */
function pkcs7Pad(data, blockSize = 16) {
    const padLen = blockSize - (data.length % blockSize);
    const padding = Buffer.alloc(padLen, padLen);
    return Buffer.concat([data, padding]);
}
/**
 * PKCS7 去填充
 * @param data 需要去填充的数据
 * @returns 去填充后的数据
 */
function pkcs7Unpad(data) {
    if (data.length === 0) {
        return data;
    }
    const padLen = data[data.length - 1];
    if (padLen < 1 || padLen > 16) {
        return data;
    }
    return data.slice(0, data.length - padLen);
}
/**
 * 将 hex 字符串转换为 Buffer
 * @param hex hex 字符串
 * @returns Buffer
 */
function hexToBuffer(hex) {
    return Buffer.from(hex, 'hex');
}
/**
 * AES CBC 模式加密，返回 base64 字符串
 * @param plainText 明文（UTF-8 字符串）
 * @param keyHex 密钥（hex 字符串，32 或 64 位）
 * @param ivHex IV（hex 字符串）
 * @returns base64 编码的密文
 */
function aesCbcEncryptBase64(plainText, keyHex, ivHex) {
    const key = hexToBuffer(keyHex);
    const iv = hexToBuffer(IV_MAC_PREFIX + ivHex);
    if (key.length !== 16 && key.length !== 32) {
        throw new Error('Key length must be 16 or 32 bytes (hex: 32 or 64 chars)');
    }
    // 根据密钥长度选择算法
    const algorithm = key.length === 16 ? 'aes-128-cbc' : 'aes-256-cbc';
    // 将明文转换为 UTF-8 字节并填充
    const data = pkcs7Pad(Buffer.from(plainText, 'utf-8'), 16);
    // 创建加密器
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    // 加密：update 处理所有数据，final 应该返回空（因为数据已经是完整块）
    // 但 Node.js 的 crypto 模块在某些情况下 final() 会返回额外数据，需要特殊处理
    const encrypted = cipher.update(data);
    const final = cipher.final();
    // 如果 final 返回了数据且 update 已处理完整数据，只使用 update 的结果（与 Python 行为一致）
    const result = final.length > 0 && encrypted.length === data.length
        ? encrypted
        : Buffer.concat([encrypted, final]);
    // 返回 base64 编码
    return result.toString('base64');
}
/**
 * AES CBC 模式解密，从 base64 字符串解密
 * @param cipherB64 base64 编码的密文
 * @param keyHex 密钥（hex 字符串，32 或 64 位）
 * @param ivHex IV（hex 字符串）
 * @returns 解密后的 UTF-8 字符串
 */
function aesCbcDecryptBase64(cipherB64, keyHex, ivHex) {
    const key = hexToBuffer(keyHex);
    const iv = hexToBuffer(IV_MAC_PREFIX + ivHex);
    if (key.length !== 16 && key.length !== 32) {
        throw new Error('Key length must be 16 or 32 bytes (hex: 32 or 64 chars)');
    }
    // 根据密钥长度选择算法
    const algorithm = key.length === 16 ? 'aes-128-cbc' : 'aes-256-cbc';
    // 解码 base64
    const cipherBytes = Buffer.from(cipherB64, 'base64');
    // 创建解密器
    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    // 解密
    const decrypted = Buffer.concat([
        decipher.update(cipherBytes),
        decipher.final(),
    ]);
    // 去填充并转换为 UTF-8 字符串
    const unpadded = pkcs7Unpad(decrypted);
    return unpadded.toString('utf-8');
}
/**
 * AES CBC 模式加密 hex 字符串，返回 base64
 * @param plainHex 明文的 hex 字符串（如 'FE00210120'）
 * @param keyHex 密钥（hex 字符串，32 或 64 位）
 * @param ivHex IV（hex 字符串）
 * @returns base64 编码的密文
 */
function aesCbcEncryptBase64Hex(plainHex, keyHex, ivHex) {
    const key = hexToBuffer(keyHex);
    const iv = hexToBuffer(IV_MAC_PREFIX + ivHex);
    if (key.length !== 16 && key.length !== 32) {
        throw new Error('Key length must be 16 or 32 bytes (hex: 32 or 64 chars)');
    }
    // 根据密钥长度选择算法
    const algorithm = 'aes-128-cbc';
    // 将 hex 字符串转换为 Buffer 并填充
    const data = pkcs7Pad(hexToBuffer(plainHex), 16);
    // 创建加密器
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    // 禁用自动填充，因为我们已经手动进行了 PKCS7 填充
    cipher.setAutoPadding(false);
    // 加密：update 处理所有数据，final 应该返回空（因为数据已经是完整块）
    // 但 Node.js 的 crypto 模块在某些情况下 final() 会返回额外数据，需要特殊处理
    const encrypted = cipher.update(data);
    const final = cipher.final();
    // 如果 final 返回了数据且 update 已处理完整数据，只使用 update 的结果（与 Python 行为一致）
    const result = final.length > 0 && encrypted.length === data.length
        ? encrypted
        : Buffer.concat([encrypted, final]);
    // 返回 base64 编码
    return result.toString('base64');
}
/**
 * AES CBC 模式解密，从 base64 解密为 hex 字符串
 * @param cipherB64 base64 编码的密文
 * @param keyHex 密钥（hex 字符串，32 或 64 位）
 * @param ivHex IV（hex 字符串）
 * @returns 解密后的 hex 字符串（大写）
 */
/**
 * AES CBC 模式解密，从 base64 解密为 hex 字符串
 * @param cipherB64 base64 编码的密文
 * @param keyHex 密钥（hex 字符串，32 或 64 位）
 * @param ivHex IV（hex 字符串）
 * @returns 解密后的 hex 字符串（大写）
 */
function aesCbcDecryptBase64ToHex(cipherB64, keyHex, ivHex) {
    logger_1.logger.debug('解密前' + cipherB64, 'zh:aes');
    const key = hexToBuffer(keyHex);
    const iv = hexToBuffer(IV_MAC_PREFIX + ivHex);
    if (key.length !== 16 && key.length !== 32) {
        throw new Error('Key length must be 16 or 32 bytes (hex: 32 or 64 chars)');
    }
    // 根据密钥长度选择算法
    const algorithm = key.length === 16 ? 'aes-128-cbc' : 'aes-256-cbc';
    // 解码 base64
    const cipherBytes = Buffer.from(cipherB64, 'base64');
    // 创建解密器
    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    // 禁用自动填充，因为我们要手动处理 PKCS7 填充
    decipher.setAutoPadding(false);
    // 解密
    const decrypted = Buffer.concat([
        decipher.update(cipherBytes),
        decipher.final(),
    ]);
    // 去填充并转换为 hex 字符串（大写）
    const unpadded = pkcs7Unpad(decrypted);
    const res = unpadded.toString('hex').toUpperCase();
    logger_1.logger.debug('解密后:' + res, 'zh:aes');
    return res;
}
//# sourceMappingURL=aes.js.map