"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeBlock = exports.encodeBlock = exports.defaultOptions = void 0;
const crypto_1 = __importStar(require("crypto"));
const threads_core_1 = require("@textile/threads-core");
// NonceBytes is the length of GCM nonce.
const nonceBytes = 12;
// TagBytes is the length of the GCM tag component.
const tagBytes = 16;
// KeyBytes is the length of GCM key.
const keyBytes = 32;
exports.defaultOptions = {
    codec: 'dag-cbor',
    algo: 'sha2-256',
    cipher: 'aes-256-gcm',
};
/**
 * EncodeBlock returns a node by encrypting the block's raw bytes with key.
 * @param block The IPLD block to encrypt and encode.
 * @param key A random key of 32 bytes tto use for encryption.
 * @param opts Options to control encoding and encryption.
 * Defaults to CBOR encoding with the SHA256 hash function, and AES GCM 256-bit encryption.
 */
function encodeBlock(block, key, opts = exports.defaultOptions) {
    // Encode block as IPLD
    const data = block.encodeUnsafe();
    // Create key components to match Go version
    const sk = key.slice(0, keyBytes);
    const iv = crypto_1.randomBytes(nonceBytes);
    const cipher = crypto_1.default.createCipheriv(opts.cipher || 'aes-256-gcm', sk, iv);
    let encrypted = cipher.update(data);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    const tag = cipher.getAuthTag();
    const payload = Buffer.concat([iv, encrypted, tag]);
    return threads_core_1.Block.encoder(payload, opts.codec, opts.algo);
}
exports.encodeBlock = encodeBlock;
/**
 * DecodeBlock uses key to perform AES-256 GCM decryption on ciphertext.
 * @param block Ciphertext as Block.
 * @param key Encryption key.
 * @param opts Additional decoding options.
 */
function decodeBlock(block, key, opts = exports.defaultOptions) {
    // Start with Block node wrapping raw encrypted bytes
    const raw = block.decodeUnsafe();
    // Extract the tag from the payload
    const tag = raw.slice(raw.length - tagBytes);
    const cipher = raw.slice(nonceBytes, raw.length - tagBytes);
    const sk = key.slice(0, keyBytes);
    const iv = raw.slice(0, nonceBytes);
    const decipher = crypto_1.default.createDecipheriv(opts.cipher || 'aes-256-gcm', sk, iv);
    decipher.setAuthTag(tag);
    const decrypted = decipher.update(cipher);
    return threads_core_1.Block.decoder(decrypted, opts.codec, opts.algo);
}
exports.decodeBlock = decodeBlock;
//# sourceMappingURL=coding.js.map