mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-23 11:14:19 +01:00
Add basic structure for crypto extension
This commit is contained in:
63
Cargo.lock
generated
63
Cargo.lock
generated
@@ -140,6 +140,12 @@ version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
@@ -204,6 +210,19 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -455,6 +474,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
@@ -1590,6 +1615,7 @@ dependencies = [
|
||||
"julian_day_converter",
|
||||
"libc",
|
||||
"libloading",
|
||||
"limbo_crypto",
|
||||
"limbo_ext",
|
||||
"limbo_macros",
|
||||
"limbo_percentile",
|
||||
@@ -1621,6 +1647,16 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_crypto"
|
||||
version = "0.0.14"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"limbo_ext",
|
||||
"mimalloc",
|
||||
"ring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_ext"
|
||||
version = "0.0.14"
|
||||
@@ -2538,6 +2574,21 @@ dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.15",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rstest"
|
||||
version = "0.18.2"
|
||||
@@ -2761,6 +2812,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "sqlite3-parser"
|
||||
version = "0.13.0"
|
||||
@@ -3130,6 +3187,12 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.4"
|
||||
|
||||
@@ -20,6 +20,7 @@ members = [
|
||||
"extensions/percentile",
|
||||
"extensions/vector",
|
||||
"extensions/time",
|
||||
"extensions/crypto",
|
||||
]
|
||||
exclude = ["perf/latency/limbo"]
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ name = "limbo_core"
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["fs", "json", "uuid", "vector", "io_uring", "time"]
|
||||
default = ["fs", "json", "uuid", "vector", "io_uring", "time", "crypto"]
|
||||
fs = []
|
||||
json = [
|
||||
"dep:jsonb",
|
||||
@@ -27,6 +27,7 @@ io_uring = ["dep:io-uring", "rustix/io_uring"]
|
||||
percentile = ["limbo_percentile/static"]
|
||||
regexp = ["limbo_regexp/static"]
|
||||
time = ["limbo_time/static"]
|
||||
crypto = ["limbo_crypto/static"]
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
io-uring = { version = "0.6.1", optional = true }
|
||||
@@ -67,6 +68,7 @@ limbo_vector = { path = "../extensions/vector", optional = true, features = ["st
|
||||
limbo_regexp = { path = "../extensions/regexp", optional = true, features = ["static"] }
|
||||
limbo_percentile = { path = "../extensions/percentile", optional = true, features = ["static"] }
|
||||
limbo_time = { path = "../extensions/time", optional = true, features = ["static"] }
|
||||
limbo_crypto = { path = "../extensions/crypto", optional = true, features = ["static"] }
|
||||
miette = "7.4.0"
|
||||
strum = "0.26"
|
||||
parking_lot = "0.12.3"
|
||||
|
||||
@@ -96,6 +96,10 @@ impl Database {
|
||||
if unsafe { !limbo_time::register_extension_static(&ext_api).is_ok() } {
|
||||
return Err("Failed to register time extension".to_string());
|
||||
}
|
||||
#[cfg(feature = "crypto")]
|
||||
if unsafe { !limbo_crypto::register_extension_static(&ext_api).is_ok() } {
|
||||
return Err("Failed to register crypto extension".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::fmt::Display;
|
||||
use std::{fmt::Display, mem};
|
||||
|
||||
/// Error type is of type ExtError which can be
|
||||
/// either a user defined error or an error code
|
||||
@@ -204,6 +204,13 @@ impl Blob {
|
||||
pub fn new(data: *const u8, size: u64) -> Self {
|
||||
Self { data, size }
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
if self.data.is_null() {
|
||||
return &[];
|
||||
}
|
||||
unsafe { std::slice::from_raw_parts(self.data, self.size as usize) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
@@ -303,6 +310,29 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
// Return ValueData as raw bytes
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = vec![];
|
||||
|
||||
unsafe {
|
||||
match self.value_type {
|
||||
ValueType::Integer => bytes.extend_from_slice(&self.value.int.to_le_bytes()),
|
||||
ValueType::Float => bytes.extend_from_slice(&self.value.float.to_le_bytes()),
|
||||
ValueType::Text => {
|
||||
let text = self.value.text.as_ref().expect("Invalid text pointer");
|
||||
bytes.extend_from_slice(text.as_str().as_bytes());
|
||||
}
|
||||
ValueType::Blob => {
|
||||
let blob = self.value.blob.as_ref().expect("Invalid blob pointer");
|
||||
bytes.extend_from_slice(blob.as_bytes());
|
||||
}
|
||||
ValueType::Error | ValueType::Null => {}
|
||||
}
|
||||
}
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
/// Creates a new integer Value from an i64
|
||||
pub fn from_integer(i: i64) -> Self {
|
||||
Self {
|
||||
|
||||
21
extensions/crypto/Cargo.toml
Normal file
21
extensions/crypto/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "limbo_crypto"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
|
||||
[features]
|
||||
static= [ "limbo_ext/static" ]
|
||||
|
||||
[dependencies]
|
||||
blake3 = "1.5.5"
|
||||
limbo_ext = { path = "../core", features = ["static"] }
|
||||
ring = "0.17.8"
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
mimalloc = { version = "*", default-features = false }
|
||||
55
extensions/crypto/src/crypto.rs
Normal file
55
extensions/crypto/src/crypto.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use crate::Error;
|
||||
use blake3::Hasher;
|
||||
use limbo_ext::{Value, ValueType};
|
||||
use ring::digest::{self, digest};
|
||||
|
||||
pub fn sha256(data: &Value) -> Result<Vec<u8>, Error> {
|
||||
match data.value_type() {
|
||||
ValueType::Error | ValueType::Null => Err(Error::InvalidType),
|
||||
_ => {
|
||||
let hash = digest(&digest::SHA256, &data.as_bytes());
|
||||
Ok(hash.as_ref().to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sha512(data: &Value) -> Result<Vec<u8>, Error> {
|
||||
match data.value_type() {
|
||||
ValueType::Error | ValueType::Null => Err(Error::InvalidType),
|
||||
_ => {
|
||||
let hash = digest(&digest::SHA512, &data.as_bytes());
|
||||
Ok(hash.as_ref().to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sha384(data: &Value) -> Result<Vec<u8>, Error> {
|
||||
match data.value_type() {
|
||||
ValueType::Error | ValueType::Null => Err(Error::InvalidType),
|
||||
_ => {
|
||||
let hash = digest(&digest::SHA384, &data.as_bytes());
|
||||
Ok(hash.as_ref().to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blake3(data: &Value) -> Result<Vec<u8>, Error> {
|
||||
match data.value_type() {
|
||||
ValueType::Error | ValueType::Null => Err(Error::InvalidType),
|
||||
_ => {
|
||||
let mut hasher = Hasher::new();
|
||||
hasher.update(data.as_bytes().as_ref());
|
||||
Ok(hasher.finalize().as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sha1(data: &Value) -> Result<Vec<u8>, Error> {
|
||||
match data.value_type() {
|
||||
ValueType::Error | ValueType::Null => Err(Error::InvalidType),
|
||||
_ => {
|
||||
let hash = digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &data.as_bytes());
|
||||
Ok(hash.as_ref().to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
78
extensions/crypto/src/lib.rs
Normal file
78
extensions/crypto/src/lib.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use crypto::{blake3, sha1, sha256, sha384, sha512};
|
||||
use limbo_ext::{register_extension, scalar, ResultCode, Value};
|
||||
|
||||
mod crypto;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Error {
|
||||
InvalidType,
|
||||
}
|
||||
|
||||
#[scalar(name = "crypto_sha256", alias = "crypto_sha256")]
|
||||
fn crypto_sha256(args: &[Value]) -> Value {
|
||||
if args.len() != 1 {
|
||||
return Value::error(ResultCode::Error);
|
||||
}
|
||||
|
||||
let Ok(hash) = sha256(&args[0]) else {
|
||||
return Value::error(ResultCode::Error);
|
||||
};
|
||||
|
||||
Value::from_blob(hash)
|
||||
}
|
||||
|
||||
#[scalar(name = "crypto_sha512", alias = "crypto_sha512")]
|
||||
fn crypto_sha512(args: &[Value]) -> Value {
|
||||
if args.len() != 1 {
|
||||
return Value::error(ResultCode::Error);
|
||||
}
|
||||
|
||||
let Ok(hash) = sha512(&args[0]) else {
|
||||
return Value::error(ResultCode::Error);
|
||||
};
|
||||
|
||||
Value::from_blob(hash)
|
||||
}
|
||||
|
||||
#[scalar(name = "crypto_sha384", alias = "crypto_sha384")]
|
||||
fn crypto_sha384(args: &[Value]) -> Value {
|
||||
if args.len() != 1 {
|
||||
return Value::error(ResultCode::Error);
|
||||
}
|
||||
|
||||
let Ok(hash) = sha384(&args[0]) else {
|
||||
return Value::error(ResultCode::Error);
|
||||
};
|
||||
|
||||
Value::from_blob(hash)
|
||||
}
|
||||
|
||||
#[scalar(name = "crypto_blake3", alias = "crypto_blake3")]
|
||||
fn crypto_blake3(args: &[Value]) -> Value {
|
||||
if args.len() != 1 {
|
||||
return Value::error(ResultCode::Error);
|
||||
}
|
||||
|
||||
let Ok(hash) = blake3(&args[0]) else {
|
||||
return Value::error(ResultCode::Error);
|
||||
};
|
||||
|
||||
Value::from_blob(hash)
|
||||
}
|
||||
|
||||
#[scalar(name = "crypto_sha1", alias = "crypto_sha1")]
|
||||
fn crypto_sha1(args: &[Value]) -> Value {
|
||||
if args.len() != 1 {
|
||||
return Value::error(ResultCode::Error);
|
||||
}
|
||||
|
||||
let Ok(hash) = sha1(&args[0]) else {
|
||||
return Value::error(ResultCode::Error);
|
||||
};
|
||||
|
||||
Value::from_blob(hash)
|
||||
}
|
||||
|
||||
register_extension! {
|
||||
scalars: { crypto_sha256, crypto_sha512, crypto_sha384, crypto_blake3, crypto_sha1 },
|
||||
}
|
||||
@@ -255,7 +255,6 @@ def test_aggregates(pipe):
|
||||
pipe, "SELECT percentile_disc(value, 0.55) from test;", validate_percentile_disc
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
pipe = init_limbo()
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user