Skip to content

Commit

Permalink
feat(hlapi): add strings
Browse files Browse the repository at this point in the history
  • Loading branch information
tmontaigu committed Dec 19, 2024
1 parent d6e4585 commit 20b34c3
Show file tree
Hide file tree
Showing 23 changed files with 1,902 additions and 70 deletions.
21 changes: 1 addition & 20 deletions tfhe/src/high_level_api/integers/unsigned/tests/cpu.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::conformance::ListSizeConstraint;
use crate::high_level_api::prelude::*;
use crate::high_level_api::tests::{setup_cpu, setup_default_cpu};
use crate::high_level_api::{generate_keys, set_server_key, ConfigBuilder, FheUint8};
use crate::integer::U256;
use crate::safe_serialization::{DeserializationConfig, SerializationConfig};
Expand All @@ -15,26 +16,6 @@ use crate::{
};
use rand::prelude::*;

fn setup_cpu(params: Option<impl Into<PBSParameters>>) -> ClientKey {
let config = params
.map_or_else(ConfigBuilder::default, |p| {
ConfigBuilder::with_custom_parameters(p.into())
})
.build();

let client_key = ClientKey::generate(config);
let csks = crate::CompressedServerKey::new(&client_key);
let server_key = csks.decompress();

set_server_key(server_key);

client_key
}

fn setup_default_cpu() -> ClientKey {
setup_cpu(Option::<ClassicPBSParameters>::None)
}

#[test]
fn test_integer_compressed_can_be_serialized() {
let config = ConfigBuilder::default().build();
Expand Down
5 changes: 5 additions & 0 deletions tfhe/src/high_level_api/keys/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ impl ServerKey {
self.key.pbs_key()
}

#[cfg(feature = "strings")]
pub(in crate::high_level_api) fn string_key(&self) -> crate::strings::ServerKeyRef<'_> {
crate::strings::ServerKeyRef::new(self.key.pbs_key())
}

pub(in crate::high_level_api) fn cpk_casting_key(
&self,
) -> Option<crate::integer::key_switching_key::KeySwitchingKeyView> {
Expand Down
8 changes: 7 additions & 1 deletion tfhe/src/high_level_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ export_concrete_array_types!(

pub use crate::integer::parameters::CompactCiphertextListConformanceParams;
pub use crate::safe_serialization::{DeserializationConfig, SerializationConfig};
#[cfg(feature = "strings")]
pub use crate::strings::ciphertext::ClearString;

#[cfg(feature = "zk-pok")]
pub use compact_list::ProvenCompactCiphertextList;
pub use compact_list::{
Expand All @@ -95,7 +98,8 @@ pub use compact_list::{
pub use compressed_ciphertext_list::{
CompressedCiphertextList, CompressedCiphertextListBuilder, HlCompressible, HlExpandable,
};

#[cfg(feature = "strings")]
pub use strings::ascii::{EncryptableString, FheAsciiString, FheStringIsEmpty, FheStringLen};
pub use tag::Tag;
pub use traits::FheId;

Expand All @@ -106,6 +110,8 @@ mod errors;
mod global_state;
mod integers;
mod keys;
#[cfg(feature = "strings")]
mod strings;
mod traits;
mod utils;

Expand Down
3 changes: 3 additions & 0 deletions tfhe/src/high_level_api/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ pub use crate::high_level_api::traits::{

pub use crate::conformance::ParameterSetConformant;
pub use crate::core_crypto::prelude::{CastFrom, CastInto};

#[cfg(feature = "strings")]
pub use crate::high_level_api::strings::traits::*;
260 changes: 260 additions & 0 deletions tfhe/src/high_level_api/strings/ascii/comp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
use crate::high_level_api::global_state::with_internal_keys;
use crate::high_level_api::keys::InternalServerKey;
use crate::high_level_api::strings::ascii::FheAsciiString;
use crate::prelude::{FheEq, FheEqIgnoreCase, FheOrd};
use crate::strings::ciphertext::ClearString;
use crate::FheBool;

impl FheEq<&Self> for FheAsciiString {
fn eq(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.eq(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings eq");
}
})
}

fn ne(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.ne(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings ne");
}
})
}
}

impl FheEq<&ClearString> for FheAsciiString {
fn eq(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().eq(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings eq");
}
})
}

fn ne(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().ne(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings ne");
}
})
}
}

impl FheOrd<&Self> for FheAsciiString {
fn lt(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.lt(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings lt");
}
})
}

fn le(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.le(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings le");
}
})
}

fn gt(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.gt(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings gt");
}
})
}

fn ge(&self, other: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.ge(&self.inner.on_cpu(), (&*other.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings ge");
}
})
}
}

impl FheOrd<&ClearString> for FheAsciiString {
fn lt(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().lt(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings lt");
}
})
}

fn le(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().le(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings le");
}
})
}

fn gt(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().gt(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings gt");
}
})
}

fn ge(&self, other: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key.string_key().ge(&self.inner.on_cpu(), other.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings ge");
}
})
}
}

impl FheEqIgnoreCase for FheAsciiString {
/// checks if the strings are equal, ignoring the case
///
/// Returns a [FheBool] that encrypts `true` if the substring was found.
///
/// # Example
///
/// ```rust
/// use tfhe::prelude::*;
/// use tfhe::{
/// generate_keys, set_server_key, ConfigBuilder, FheAsciiString, FheStringIsEmpty,
/// FheStringLen,
/// };
///
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
/// set_server_key(server_key);
///
/// let string1 = FheAsciiString::try_encrypt("tfhe-RS", &client_key).unwrap();
/// let string2 = FheAsciiString::try_encrypt("TFHE-rs", &client_key).unwrap();
/// let is_eq = string1.eq_ignore_case(&string2);
///
/// assert!(is_eq.decrypt(&client_key));
/// ```
fn eq_ignore_case(&self, rhs: &Self) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.eq_ignore_case(&self.inner.on_cpu(), (&*rhs.inner.on_cpu()).into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings eq_ignore_case");
}
})
}
}

impl FheEqIgnoreCase<ClearString> for FheAsciiString {
/// checks if the strings are equal, ignoring the case
///
/// Returns a [FheBool] that encrypts `true` if the substring was found.
///
/// # Example
///
/// ```rust
/// use tfhe::prelude::*;
/// use tfhe::{
/// generate_keys, set_server_key, ClearString, ConfigBuilder, FheAsciiString,
/// FheStringIsEmpty, FheStringLen,
/// };
///
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
/// set_server_key(server_key);
///
/// let string1 = FheAsciiString::try_encrypt("tfhe-RS", &client_key).unwrap();
/// let string2 = ClearString::new("TFHE-rs".into());
/// let is_eq = string1.eq_ignore_case(&string2);
///
/// assert!(is_eq.decrypt(&client_key));
/// ```
fn eq_ignore_case(&self, rhs: &ClearString) -> FheBool {
with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = cpu_key
.string_key()
.eq_ignore_case(&self.inner.on_cpu(), rhs.into());
FheBool::new(inner, cpu_key.tag.clone())
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("gpu does not support strings eq_ignore_case");
}
})
}
}
Loading

0 comments on commit 20b34c3

Please sign in to comment.