import { generate_date_seq, get_random_char_seq } from "./utils.js";
/**
* @module Encryption
*/
/**
* Encodes binary data to base64 string
* @param {Uint8Array} data - Binary data to encode
* @returns {string} Base64 encoded string
*/
export function base64Encode(data) {
return btoa(String.fromCharCode.apply(null, new Uint8Array(data)));
}
/**
* Decodes base64 string to binary data
* @param {string} data - Base64 string to decode
* @returns {Uint8Array} Decoded binary data
*/
export function base64Decode(data) {
return Uint8Array.from(atob(data), (c) => c.charCodeAt(0));
}
// Initialization Vector (IV)
const IV = new TextEncoder().encode("dcek9wb8frty1pnm");
/**
* Generates an AES key based on date sequence
* @param {Date} [date=null] - Optional date to use for key generation
* @returns {Promise<CryptoKey>} Generated AES-CBC key
*/
export async function generate_key(date = null) {
const dateSeq = generate_date_seq(date);
const keyData = new TextEncoder().encode("qa8y" + dateSeq + "ty1pn");
return window.crypto.subtle.importKey("raw", keyData, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
}
/**
* Generates an encrypted local name for request headers
* @param {Date} [date=null] - Optional date to use for name generation
* @returns {Promise<string>} Base64 encoded encrypted local name
*/
export async function generate_local_name(date = null) {
const randomCharSeq = get_random_char_seq(4);
const dateSeq = generate_date_seq(date);
const randomSuffix = get_random_char_seq(5);
const nameBytes = new TextEncoder().encode(randomCharSeq + dateSeq + randomSuffix);
const encryptedBytes = await encrypt(nameBytes);
return base64Encode(encryptedBytes);
}
/**
* Encrypts data using AES-CBC
* @param {Uint8Array} data - Data to encrypt
* @returns {Promise<Uint8Array>} Encrypted data
*/
export async function encrypt(data) {
const key = await generate_key();
const encrypted = await window.crypto.subtle.encrypt({ name: "AES-CBC", iv: IV }, key, data);
return new Uint8Array(encrypted);
}
/**
* Decrypts data using AES-CBC
* @param {Uint8Array} data - Data to decrypt
* @returns {Promise<Uint8Array>} Decrypted data
*/
export async function decrypt(data) {
const key = await generate_key();
const decrypted = await window.crypto.subtle.decrypt({ name: "AES-CBC", iv: IV }, key, data);
return new Uint8Array(decrypted);
}
/**
* Deserializes an encrypted base64 payload
* @param {string} payload - Base64 encoded encrypted payload
* @returns {Promise<object>} Decrypted and parsed JSON object
*/
export async function deserialize_payload(payload) {
const pbytes = base64Decode(payload);
const raw = await decrypt(pbytes);
return JSON.parse(new TextDecoder().decode(raw));
}
/**
* Serializes and encrypts a payload object
* @param {object} payload - Object to serialize and encrypt
* @returns {Promise<string>} Base64 encoded encrypted payload
*/
export async function serialize_payload(payload) {
const raw = new TextEncoder().encode(JSON.stringify(payload));
const pbytes = await encrypt(raw);
return base64Encode(pbytes);
}