When encrypting strings, you can add padding to hide the actual length of strings. The null character (b'\0') is used as the padding. Here is an example:
# Cargo.toml[dependencies]tfhe = { version ="0.11.0", features = ["integer","strings"] }
use tfhe::{ConfigBuilder, generate_keys, set_server_key, FheAsciiString, FheStringLen, ClearString};use tfhe::prelude::*;use tfhe::safe_serialization::safe_serialize;fnmain() {let config =ConfigBuilder::default().build();let (cks, sks) =generate_keys(config);set_server_key(sks);let r =FheAsciiString::try_encrypt("café is french for coffee", &cks);// As the input string is not strictly ASCII, it is not compatibleassert!(r.is_err());let string =FheAsciiString::try_encrypt("tfhe-rs", &cks).unwrap();// This adds 3 chars of padding to the chars of the input stringlet padded_string =FheAsciiString::try_encrypt_with_padding("tfhe-rs", 3, &cks).unwrap();// This makes it so the string has 10 chars (adds padding or truncates input as necessary)let other_string =FheAsciiString::try_encrypt_with_fixed_sized("tfhe", 10, &cks).unwrap();letmut buffer1 =vec![];safe_serialize(&padded_string, &mut buffer1, 1<<30).unwrap();letmut buffer2 =vec![];safe_serialize(&other_string, &mut buffer2, 1<<30).unwrap();// The two strings created with padding, have the same// memory/disk footprint, even though the lengths are not the sameassert_eq!(buffer1.len(), buffer2.len());// When a string has no padding, its length is known in clearlet len = string.len();assert!(matches!(len, FheStringLen::NoPadding(7)));// When a string has padding, its length is only known as an encrypted valueletFheStringLen::Padding(encrypted_len) = padded_string.len() else {panic!("Expected len to be encrypted"); };let padded_string_len:u16= encrypted_len.decrypt(&cks);assert_eq!(padded_string_len, 7); // Note padding chars are not counted// The enum resulting of a len() / is_empty() call can be transformed // to a FheUint16 using `into_ciphertext`assert!(string.len().into_ciphertext().is_trivial());assert!(!padded_string.len().into_ciphertext().is_trivial());let other_string_len:u16= other_string.len().into_ciphertext().decrypt(&cks);assert_eq!(other_string_len, 4);// Padded and un-padded strings are equal if the content isassert!(padded_string.eq(&string).decrypt(&cks));let prefix =ClearString::new("tfhe".to_string());let (stripped_string, has_been_stripped) = string.strip_prefix(&prefix);// Notice that stripping, makes the string as being considered as padded// as it is not possible to homomorphically remove charsletFheStringLen::Padding(encrypted_len) = stripped_string.len() else {panic!("Expected len to be encrypted"); };let stripped_string_len:u16= encrypted_len.decrypt(&cks);assert_eq!(stripped_string_len, 3);let decrypted = stripped_string.decrypt(&cks);assert_eq!(decrypted, "-rs");assert!(has_been_stripped.decrypt(&cks));}