lulu 0.0.721

A mini lua runtime
Documentation
use super::bytes::LuluByteArray;
use crate::ops::std::create_std_module;
use mlua::prelude::*;

use aes_gcm::{
  Aes256Gcm, Key, Nonce,
  aead::{Aead, KeyInit},
};
use rand::RngCore;

pub fn into_module() {
  create_std_module("crypto")
    .add_function("random_key", |_, size: Option<usize>| {
      let size = size.unwrap_or(32);
      if size != 32 {
        return Err(LuaError::external("AES-256 key must be 32 bytes"));
      }

      let mut key_bytes = [0u8; 32];
      rand::thread_rng().fill_bytes(&mut key_bytes);
      Ok(LuluByteArray {
        bytes: key_bytes.to_vec(),
      })
    })
    .add_function("random_nonce", |_, size: Option<usize>| {
      let size = size.unwrap_or(12);
      if size != 12 {
        return Err(LuaError::external("AES-GCM nonce must be 12 bytes"));
      }

      let mut nonce_bytes = [0u8; 12];
      rand::thread_rng().fill_bytes(&mut nonce_bytes);
      Ok(LuluByteArray {
        bytes: nonce_bytes.to_vec(),
      })
    })
    .add_function(
      "encrypt",
      |_, (key_ud, nonce_ud, data_ud): (LuaAnyUserData, LuaAnyUserData, LuaAnyUserData)| {
        let key_bytes = key_ud.borrow::<LuluByteArray>()?;
        if key_bytes.bytes.len() != 32 {
          return Err(LuaError::external("AES-256 key must be 32 bytes"));
        }
        let nonce_bytes = nonce_ud.borrow::<LuluByteArray>()?;
        if nonce_bytes.bytes.len() != 12 {
          return Err(LuaError::external("AES-GCM nonce must be 12 bytes"));
        }
        let data_bytes = data_ud.borrow::<LuluByteArray>()?;

        let key = Key::<Aes256Gcm>::from_slice(&key_bytes.bytes);
        let nonce = Nonce::from_slice(&nonce_bytes.bytes);

        let cipher = Aes256Gcm::new(key);
        let encrypted = cipher
          .encrypt(nonce, data_bytes.bytes.as_slice())
          .map_err(|e| LuaError::external(e.to_string()))?;

        Ok(LuluByteArray { bytes: encrypted })
      },
    )
    .add_function(
      "decrypt",
      |_, (key_ud, nonce_ud, ct_ud): (LuaAnyUserData, LuaAnyUserData, LuaAnyUserData)| {
        let key_bytes = key_ud.borrow::<LuluByteArray>()?;
        if key_bytes.bytes.len() != 32 {
          return Err(LuaError::external("AES-256 key must be 32 bytes"));
        }
        let nonce_bytes = nonce_ud.borrow::<LuluByteArray>()?;
        if nonce_bytes.bytes.len() != 12 {
          return Err(LuaError::external("AES-GCM nonce must be 12 bytes"));
        }
        let ct_bytes = ct_ud.borrow::<LuluByteArray>()?;

        let key = Key::<Aes256Gcm>::from_slice(&key_bytes.bytes);
        let nonce = Nonce::from_slice(&nonce_bytes.bytes);

        let cipher = Aes256Gcm::new(key);
        let decrypted = cipher
          .decrypt(nonce, ct_bytes.bytes.as_slice())
          .map_err(|e| LuaError::external(e.to_string()))?;

        Ok(LuluByteArray { bytes: decrypted })
      },
    )
    .into();
}