Add PRAGMA cipher to allow setting cipher algo

This commit is contained in:
Avinash Sajjanshetty
2025-08-25 02:17:53 +05:30
parent 279bcd0869
commit 328c5edf4d
5 changed files with 60 additions and 1 deletions

View File

@@ -41,6 +41,7 @@ pub mod numeric;
mod numeric;
use crate::incremental::view::ViewTransactionState;
use crate::storage::encryption::CipherMode;
use crate::translate::optimizer::optimize_plan;
use crate::translate::pragma::TURSO_CDC_DEFAULT_TABLE_NAME;
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
@@ -455,6 +456,7 @@ impl Database {
metrics: RefCell::new(ConnectionMetrics::new()),
is_nested_stmt: Cell::new(false),
encryption_key: RefCell::new(None),
encryption_cipher: RefCell::new(None),
});
let builtin_syms = self.builtin_syms.borrow();
// add built-in extensions symbols to the connection to prevent having to load each time
@@ -886,6 +888,7 @@ pub struct Connection {
/// Generally this is only true for ParseSchema.
is_nested_stmt: Cell<bool>,
encryption_key: RefCell<Option<EncryptionKey>>,
encryption_cipher: RefCell<Option<CipherMode>>,
}
impl Connection {
@@ -1961,6 +1964,15 @@ impl Connection {
let pager = self.pager.borrow();
pager.set_encryption_context(&key);
}
pub fn set_encryption_cipher(&self, cipher: CipherMode) {
tracing::trace!("setting encryption cipher for connection");
self.encryption_cipher.replace(Some(cipher));
}
pub fn get_encryption_cipher_mode(&self) -> Option<CipherMode> {
self.encryption_cipher.borrow().clone()
}
}
pub struct Statement {

View File

@@ -111,6 +111,10 @@ pub fn pragma_for(pragma: &PragmaName) -> Pragma {
PragmaFlags::Result0 | PragmaFlags::SchemaReq | PragmaFlags::NoColumns1,
&["hexkey"],
),
EncryptionCipher => Pragma::new(
PragmaFlags::Result0 | PragmaFlags::SchemaReq | PragmaFlags::NoColumns1,
&["cipher"],
),
}
}

View File

@@ -134,6 +134,30 @@ pub enum CipherMode {
Aegis256,
}
impl TryFrom<&str> for CipherMode {
type Error = LimboError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match s.to_lowercase().as_str() {
"aes256gcm" | "aes-256-gcm" | "aes_256_gcm" => Ok(CipherMode::Aes256Gcm),
"aegis256" | "aegis-256" | "aegis_256" => Ok(CipherMode::Aegis256),
_ => Err(LimboError::InvalidArgument(format!(
"Unknown cipher name: {}",
s
))),
}
}
}
impl std::fmt::Display for CipherMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CipherMode::Aes256Gcm => write!(f, "aes256gcm"),
CipherMode::Aegis256 => write!(f, "aegis256"),
}
}
}
impl CipherMode {
/// Every cipher requires a specific key size. For 256-bit algorithms, this is 32 bytes.
/// For 128-bit algorithms, it would be 16 bytes, etc.

View File

@@ -10,7 +10,7 @@ use turso_parser::ast::{PragmaName, QualifiedName};
use super::integrity_check::translate_integrity_check;
use crate::pragma::pragma_for;
use crate::schema::Schema;
use crate::storage::encryption::EncryptionKey;
use crate::storage::encryption::{CipherMode, EncryptionKey};
use crate::storage::pager::AutoVacuumMode;
use crate::storage::pager::Pager;
use crate::storage::sqlite3_ondisk::CacheSize;
@@ -318,6 +318,12 @@ fn update_pragma(
connection.set_encryption_key(key);
Ok((program, TransactionMode::None))
}
PragmaName::EncryptionCipher => {
let value = parse_string(&value)?;
let cipher = CipherMode::try_from(value.as_str())?;
connection.set_encryption_cipher(cipher);
Ok((program, TransactionMode::None))
}
}
}
@@ -589,6 +595,15 @@ fn query_pragma(
program.add_pragma_result_column(pragma.to_string());
Ok((program, TransactionMode::None))
}
PragmaName::EncryptionCipher => {
if let Some(cipher) = connection.get_encryption_cipher_mode() {
let register = program.alloc_register();
program.emit_string8(cipher.to_string(), register);
program.emit_result_row(register, 1);
program.add_pragma_result_column(pragma.to_string());
}
Ok((program, TransactionMode::None))
}
}
}

View File

@@ -1211,6 +1211,10 @@ pub enum PragmaName {
AutoVacuum,
/// `cache_size` pragma
CacheSize,
/// encryption cipher algorithm name for encrypted databases
#[strum(serialize = "cipher")]
#[cfg_attr(feature = "serde", serde(rename = "cipher"))]
EncryptionCipher,
/// List databases
DatabaseList,
/// Encoding - only support utf8