Skip to main content

Encryption/Decryption

Sentinel: Symmetric Encryption (AES)

To encrypt data using sentinels, follow these steps:

  1. Generate a Random Initialization Vector (IV):
    • An IV is a random value used with the encryption key to ensure that identical plaintexts produce different ciphertexts.
  2. Encryption Process:
    • Encrypt the plaintext using the AES algorithm with CBC mode and PKCS7 padding.
    • Combine the ciphertext, IV, sentinel ID, and an HMAC hash (sum) to create the final encrypted string.

Example Code

Here is an example implementation using CryptoJS for AES encryption:

import CryptoJS  from "crypto-js";

public static encrypt = (text: string, sentinel: SentinelOutput): string => {
// Generate a random IV
const iv = CryptoJS.lib.WordArray.random(128 / 8);

// Encrypt the text using AES with CBC mode and PKCS7 padding
const ciphertext = CryptoJS.AES.encrypt(text, CryptoJS.enc.Utf8.parse(sentinel.cipher), {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();

// Compute the HMAC SHA-512 hash for integrity verification
const sum = CryptoJS.SHA512(ciphertext + iv.toString() + sentinel.cipher).toString();

// Concatenate ciphertext, IV, sentinel ID, and hash to form the final encrypted string
return `${ciphertext}.${iv.toString()}.${sentinel.id}.${sum}`;
};

Sentinel: Decryption

To decrypt the data, you need to extract the ciphertext, IV, sentinel ID, and hash from the encrypted string. Verify the hash to ensure data integrity, then decrypt the ciphertext using the same IV and sentinel key.

Example Code

const decrypt = (encryptedText: string, sentinel: SentinelOutput): string => {
// Split the encrypted text into its components
const parts = encryptedText.split('.');
const ciphertext = parts[0];
const iv = CryptoJS.enc.Hex.parse(parts[1]);
const id = parts[2];
const sum = parts[3];

// Verify the integrity of the data using the hash
const computedSum = CryptoJS.SHA512(ciphertext + iv.toString() + sentinel.cipher).toString();
if (computedSum !== sum) {
throw new Error('Data integrity check failed');
}

// Decrypt the ciphertext using AES with CBC mode and PKCS7 padding
const decrypted = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse(sentinel.cipher), {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});

return decrypted.toString(CryptoJS.enc.Utf8);
};

Anonymous Sentinel: Asymmetric Encryption with Kyber

Example banner

To encrypt data using a Kyber-based anonymous sentinel, follow these steps:

  1. Generate a Random Initialization Vector (IV):
    • An IV is a random value used with the encryption key to ensure that identical plaintexts produce different ciphertexts.
  2. Encryption Process:
    • Generate a Kyber cipher and an AES-256 key.
    • Encrypt the plaintext using the AES-256 algorithm with CBC mode and PKCS7 padding.
    • Combine the Kyber cipher, ciphertext, IV, anonymous sentinel ID, and an HMAC hash (sum) to create the final encrypted string.

Example Code

static asym_encrypt(text, sentinel) {
// Generate a random IV
const iv = CryptoJS.lib.WordArray.random(128 / 8);

// Encrypt the text using Kyber
const c_ss = kyber.Encrypt1024(Array.from(Buffer.from(sentinel.public_key, 'hex')));
const cipher = Buffer.from(c_ss[0]);
const ss1 = c_ss[1];
const secret_cipher = cipher.toString('hex');

// Symmetric encryption using shared secret (AES256 key)
const ciphertext = AnonymousSentinelEncryption.text_encryption(text, ss1.toString('hex'), iv);

// Compute the HMAC SHA-512 hash for integrity verification
const sum = CryptoJS.SHA512(ciphertext + iv.toString() + ss1.toString('hex')).toString();

// Concatenate components to form the final encrypted string
return `ano.${secret_cipher}.${ciphertext}.${iv.toString()}.${sentinel.id}.${sum}`;
}

static text_encryption(text, key, iv) {
return CryptoJS.AES.encrypt(text, CryptoJS.enc.Hex.parse(key), {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
}

Anonymous Sentinel: Decryption

To decrypt the data, you need to:

  • Extract the Kyber cipher, ciphertext, IV, sentinel ID, and hash from the encrypted string.
  • Generate the AES-256 key from the Kyber cipher and the secret key.
  • Verify the hash to ensure data integrity, then decrypt the ciphertext using the same IV and sentinel key.

Example Code

static async asym_decrypt_with_key_chain(content, sentinel) {
// Split the encrypted content into its components
const explode = content.split('.');

// Decrypt the shared secret (AES256 key) using Kyber
const ss2 = kyber.Decrypt1024(
Array.from(Buffer.from(explode[1], 'hex')),
Array.from(Buffer.from(sentinel.secret_key, 'hex'))
);

// Verify the integrity of the data using the hash
const check_sum = CryptoJS.SHA512(
explode[2] + explode[3] + ss2.toString('hex')
).toString();

if (check_sum !== explode[5]) throw new Error('Bad checksum');

// Decrypt the ciphertext using AES-256 with CBC mode and PKCS7 padding
const decrypted = CryptoJS.AES.decrypt(explode[2], CryptoJS.enc.Hex.parse(ss2.toString('hex')), {
iv: CryptoJS.enc.Hex.parse(explode[3]),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});

return decrypted.toString(CryptoJS.enc.Utf8);
}

Encryption/Decryption Made Easy with the SDK

The SDK simplifies the process of encrypting and decrypting data, both symmetrically and asymmetrically. Here's how you can easily perform these operations using the provided methods.

Symmetric Encryption

Encrypting Data

To encrypt data symmetrically using AES-256, you only need to call the encrypt method with the plaintext and an object containing the access token and API URL.

const to_encrypt = "Sensitive data to encrypt";
const encrypted = Lagertha.encrypt(to_encrypt, { access_token: "eydzv54vrev...", env: "<lagertha_api_url>" });
console.log('Encrypted:', encrypted);

Decrypting Data

To decrypt the previously encrypted data, simply call the decrypt method with the encrypted string.

const decrypted = Lagertha.decrypt(encrypted, { access_token: "eydzv54vrev...", env: "<lagertha_api_url>" });
console.log('Decrypted:', decrypted);

Asymmetric Encryption

Encrypting Data

For asymmetric encryption using an anonymous sentinel, you can use the anonymous_encrypt method. This method requires the plaintext, the anonymous sentinel object, and the API URL.

const to_encrypt = "Sensitive data to encrypt";
const anonymous_sentinel = {
id: "123e4567-e89b-12d3-a456-426614174000",
public_key: "publicKeyHexString",
sum: "sha256hashofpublickey"
};

const encrypted = Lagertha.anonymous_encrypt(to_encrypt, anonymous_sentinel, "<lagertha_api_url>");
console.log('Encrypted:', encrypted);

Decrypting Data

To decrypt the data encrypted with the anonymous sentinel, use the anonymous_decryption method. This requires the encrypted string and an object containing the access token and API URL.

const decrypted = Lagertha.anonymous_decryption(encrypted, { access_token: "eydzv54vrev...", env: "<lagertha_api_url>" });
console.log('Decrypted:', decrypted);