mirror of
https://github.com/Sunscreen-tech/Sunscreen.git
synced 2026-04-19 03:00:06 -04:00
Remove encoders WIP
This commit is contained in:
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"iostream": "cpp"
|
||||
"iostream": "cpp",
|
||||
"__locale": "cpp",
|
||||
"__string": "cpp",
|
||||
"regex": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp"
|
||||
}
|
||||
}
|
||||
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
@@ -112,9 +112,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
@@ -465,6 +465,12 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
@@ -555,6 +561,7 @@ dependencies = [
|
||||
name = "sunscreen_frontend_macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_json",
|
||||
@@ -571,7 +578,9 @@ dependencies = [
|
||||
"log",
|
||||
"petgraph",
|
||||
"seal",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sunscreen_backend",
|
||||
"sunscreen_circuit",
|
||||
"sunscreen_runtime",
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::bindgen::{
|
||||
/**
|
||||
* A type representing all errors that can occur in SEAL.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Error {
|
||||
/// No error
|
||||
Ok,
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use std::ffi::{c_void, CString};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use crate::bindgen;
|
||||
use crate::error::*;
|
||||
use crate::{bindgen, serialization::CompressionType, Context};
|
||||
|
||||
use serde::ser::Error;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
#[derive(Debug)]
|
||||
/**
|
||||
* Class to store a plaintext element. The data for the plaintext is
|
||||
* a polynomial with coefficients modulo the plaintext modulus. The degree
|
||||
@@ -35,7 +39,75 @@ pub struct Plaintext {
|
||||
unsafe impl Sync for Plaintext {}
|
||||
unsafe impl Send for Plaintext {}
|
||||
|
||||
impl Clone for Plaintext {
|
||||
fn clone(&self) -> Self {
|
||||
let mut copy = null_mut();
|
||||
|
||||
convert_seal_error(unsafe { bindgen::Plaintext_Create5(self.handle, &mut copy) })
|
||||
.expect("Internal error: Failed to copy plaintext.");
|
||||
|
||||
Self { handle: copy }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Plaintext {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut num_bytes: i64 = 0;
|
||||
|
||||
convert_seal_error(unsafe {
|
||||
bindgen::Plaintext_SaveSize(self.handle, CompressionType::ZStd as u8, &mut num_bytes)
|
||||
})
|
||||
.map_err(|e| {
|
||||
S::Error::custom(format!("Failed to get secret key serialized size: {}", e))
|
||||
})?;
|
||||
|
||||
let mut data: Vec<u8> = Vec::with_capacity(num_bytes as usize);
|
||||
let mut bytes_written: i64 = 0;
|
||||
|
||||
convert_seal_error(unsafe {
|
||||
let data_ptr = data.as_mut_ptr();
|
||||
|
||||
bindgen::Plaintext_Save(
|
||||
self.handle,
|
||||
data_ptr,
|
||||
num_bytes as u64,
|
||||
CompressionType::ZStd as u8,
|
||||
&mut bytes_written,
|
||||
)
|
||||
})
|
||||
.map_err(|e| S::Error::custom(format!("Failed to get secret key bytes: {}", e)))?;
|
||||
|
||||
unsafe { data.set_len(bytes_written as usize) };
|
||||
|
||||
serializer.serialize_bytes(&data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Plaintext {
|
||||
/**
|
||||
* Deserializes a byte stream into a plaintext. This requires a context, which is why
|
||||
* Plaintext doesn't `impl Deserialize`.
|
||||
*/
|
||||
pub fn from_bytes(&mut self, context: Context, data: &[u8]) -> Result<()> {
|
||||
let mut bytes_read = 0;
|
||||
|
||||
convert_seal_error(unsafe {
|
||||
// While the interface marks data as mut, SEAL doesn't actually modify it, so we're okay.
|
||||
bindgen::Plaintext_Load(
|
||||
self.handle,
|
||||
context.get_handle(),
|
||||
data.as_ptr() as *mut u8,
|
||||
data.len() as u64,
|
||||
&mut bytes_read,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handle to the underlying SEAL object.
|
||||
*/
|
||||
@@ -92,6 +164,68 @@ impl Plaintext {
|
||||
|
||||
Ok(Self { handle })
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the coefficient at the given location. Coefficients are ordered
|
||||
* from lowest to highest degree, with the first value being the constant
|
||||
* coefficient.
|
||||
*
|
||||
* # Panics
|
||||
* Panics if index is greater than len().
|
||||
*/
|
||||
pub fn get_coefficient(&self, index: usize) -> u64 {
|
||||
let mut coeff: u64 = 0;
|
||||
|
||||
if index > self.len() {
|
||||
panic!("Index {} out of bounds {}", index, self.len());
|
||||
}
|
||||
|
||||
convert_seal_error(unsafe {
|
||||
bindgen::Plaintext_CoeffAt(self.handle, index as u64, &mut coeff)
|
||||
})
|
||||
.expect("Fatal error in Plaintext::index().");
|
||||
|
||||
coeff
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coefficient at the given location. Coefficients are ordered
|
||||
* from lowest to highest degree, with the first value being the constant
|
||||
* coefficient.
|
||||
*
|
||||
* # Panics
|
||||
* Panics if index is greater than len().
|
||||
*/
|
||||
pub fn set_coefficient(&mut self, index: usize, value: u64) {
|
||||
if index > self.len() {
|
||||
panic!("Index {} out of bounds {}", index, self.len());
|
||||
}
|
||||
|
||||
convert_seal_error(unsafe {
|
||||
bindgen::Plaintext_SetCoeffAt(self.handle, index as u64, value)
|
||||
})
|
||||
.expect("Fatal error in Plaintext::index().");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of coefficients this plaintext can hold.
|
||||
*/
|
||||
pub fn resize(&mut self, count: usize) {
|
||||
convert_seal_error(unsafe { bindgen::Plaintext_Reserve(self.handle, count as u64) })
|
||||
.expect("Fatal error in Plaintext::index().");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of coefficients this plaintext can hold.
|
||||
*/
|
||||
pub fn len(&self) -> usize {
|
||||
let mut size: u64 = 0;
|
||||
|
||||
convert_seal_error(unsafe { bindgen::Plaintext_Capacity(self.handle, &mut size) })
|
||||
.expect("Fatal error in Plaintext::index().");
|
||||
|
||||
size as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Plaintext {
|
||||
@@ -186,4 +320,13 @@ mod tests {
|
||||
|
||||
std::mem::drop(plaintext);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plaintext_coefficients_in_increasing_order() {
|
||||
let plaintext = Plaintext::from_hex_string("1234x^2 + 4321").unwrap();
|
||||
|
||||
assert_eq!(plaintext.get_coefficient(0), 0x4321);
|
||||
assert_eq!(plaintext.get_coefficient(1), 0);
|
||||
assert_eq!(plaintext.get_coefficient(2), 0x1234);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ proc-macro = true
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = "2.34.0"
|
||||
proc-macro2 = "1.0.32"
|
||||
quote = "1.0.10"
|
||||
syn = { version = "1.0.81", features = ["derive", "full", "fold"] }
|
||||
|
||||
@@ -12,4 +12,8 @@ sunscreen_backend = { path = "../sunscreen_backend" }
|
||||
sunscreen_circuit = { path = "../sunscreen_circuit" }
|
||||
sunscreen_runtime = { path = "../sunscreen_runtime" }
|
||||
seal = { path = "../seal" }
|
||||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
semver = "1.0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0.72"
|
||||
@@ -18,6 +18,17 @@ pub enum Error {
|
||||
* Attempted to compile the given circuit with the wrong scheme.
|
||||
*/
|
||||
IncorrectScheme,
|
||||
|
||||
/**
|
||||
* An internal error occurred in the SEAL library.
|
||||
*/
|
||||
SealError(seal::Error),
|
||||
}
|
||||
|
||||
impl From<seal::Error> for Error {
|
||||
fn from(err: seal::Error) -> Self {
|
||||
Self::SealError(err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -171,6 +171,24 @@ thread_local! {
|
||||
pub static CURRENT_CTX: RefCell<Option<&'static mut Context>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the specified closure, injecting the current circuit context.
|
||||
*/
|
||||
pub fn with_ctx<F, R>(f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut Context) -> R,
|
||||
{
|
||||
CURRENT_CTX.with(|ctx| {
|
||||
let mut option = ctx.borrow_mut();
|
||||
let ctx = option
|
||||
.as_mut()
|
||||
.expect("Called Ciphertext::new() outside of a context.");
|
||||
|
||||
f(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
impl Context {
|
||||
/**
|
||||
* Creates a new empty frontend intermediate representation context with the given scheme.
|
||||
|
||||
@@ -1,31 +1,9 @@
|
||||
use std::ops::{Add, Mul, Shl, Shr};
|
||||
|
||||
use petgraph::stable_graph::NodeIndex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use seal::Plaintext as SealPlaintext;
|
||||
|
||||
use crate::{Context, Literal, CURRENT_CTX};
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
struct U64LiteralRef {}
|
||||
|
||||
impl FheType for U64LiteralRef {}
|
||||
impl BfvType for U64LiteralRef {}
|
||||
|
||||
impl U64LiteralRef {
|
||||
pub fn new(val: u64) -> NodeIndex {
|
||||
with_ctx(|ctx| ctx.add_literal(Literal::U64(val)))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Denotes the given rust type is an encoding in an FHE scheme
|
||||
*/
|
||||
pub trait FheType {}
|
||||
|
||||
/**
|
||||
* Denotes the given type is valid under the [SchemeType::BFV](crate::SchemeType::Bfv).
|
||||
*/
|
||||
pub trait BfvType: FheType {}
|
||||
use crate::{Context, CURRENT_CTX, Params, Result, types::{CircuitNode, FheType, BfvType, U64LiteralRef, TryIntoPlaintext}};
|
||||
use sunscreen_runtime::{InnerPlaintext, Plaintext};
|
||||
|
||||
impl CircuitNode<Unsigned> {
|
||||
/**
|
||||
@@ -36,55 +14,13 @@ impl CircuitNode<Unsigned> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/**
|
||||
* A type that wraps an FheType during graph construction
|
||||
*/
|
||||
pub struct CircuitNode<T: FheType> {
|
||||
/**
|
||||
* The node's index
|
||||
*/
|
||||
pub id: NodeIndex,
|
||||
|
||||
_phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: FheType> CircuitNode<T> {
|
||||
/**
|
||||
* Creates a new circuit node with the given node index.
|
||||
*/
|
||||
pub fn new(id: NodeIndex) -> Self {
|
||||
Self {
|
||||
id,
|
||||
_phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CircuitNode denoted as an input to a circuit graph.
|
||||
*/
|
||||
pub fn input() -> Self {
|
||||
with_ctx(|ctx| Self::new(ctx.add_input()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Denote this node as an output by appending an output circuit node.
|
||||
*/
|
||||
pub fn output(&self) -> Self {
|
||||
with_ctx(|ctx| Self::new(ctx.add_output(self.id)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/**
|
||||
* Represents a single unsigned integer encrypted as a ciphertext. Suitable for use
|
||||
* as an input or output for a Sunscreen circuit.
|
||||
*/
|
||||
pub struct Unsigned {
|
||||
/**
|
||||
* The internal graph node id of this input or output.
|
||||
*/
|
||||
pub id: NodeIndex,
|
||||
val: u64,
|
||||
}
|
||||
|
||||
impl FheType for Unsigned {}
|
||||
@@ -141,3 +77,38 @@ where
|
||||
f(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
impl TryIntoPlaintext for Unsigned {
|
||||
fn try_into_plaintext(&self, params: &Params) -> Result<Plaintext> {
|
||||
let mut seal_plaintext = SealPlaintext::new()?;
|
||||
let bits = std::mem::size_of::<u64>() * 8;
|
||||
|
||||
seal_plaintext.resize(bits);
|
||||
|
||||
for i in 0..bits {
|
||||
let bit_value = (self.val & 0x1 << i) >> i;
|
||||
seal_plaintext.set_coefficient(i, bit_value);
|
||||
}
|
||||
|
||||
Ok(Plaintext::new(InnerPlaintext::Seal(seal_plaintext), params.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Unsigned {
|
||||
fn from(val: u64) -> Self {
|
||||
Self { val }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests
|
||||
{
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_convert_u64_to_unsigned() {
|
||||
let foo: Unsigned = 64u64.into();
|
||||
|
||||
assert_eq!(foo.val, 64);
|
||||
}
|
||||
}
|
||||
176
sunscreen_frontend_types/src/types/mod.rs
Normal file
176
sunscreen_frontend_types/src/types/mod.rs
Normal file
@@ -0,0 +1,176 @@
|
||||
mod integer;
|
||||
|
||||
use crate::{Literal, with_ctx, Params, Result};
|
||||
|
||||
use petgraph::stable_graph::NodeIndex;
|
||||
use sunscreen_runtime::Plaintext;
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, de::{self, Visitor}, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub use integer::Unsigned;
|
||||
|
||||
/**
|
||||
* Denotes the given rust type is an encoding in an FHE scheme
|
||||
*/
|
||||
pub trait FheType {}
|
||||
|
||||
/**
|
||||
* Denotes the given type is valid under the [SchemeType::BFV](crate::SchemeType::Bfv).
|
||||
*/
|
||||
pub trait BfvType: FheType {}
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
/**
|
||||
* A reference to a u64 literal in a circuit graph.
|
||||
*/
|
||||
pub struct U64LiteralRef {}
|
||||
|
||||
impl FheType for U64LiteralRef {}
|
||||
impl BfvType for U64LiteralRef {}
|
||||
|
||||
impl U64LiteralRef {
|
||||
/**
|
||||
* Creates a reference to the given literal. If the given literal already exists in the current
|
||||
* graph, a reference to the existing literal is returned.
|
||||
*/
|
||||
pub fn new(val: u64) -> NodeIndex {
|
||||
with_ctx(|ctx| ctx.add_literal(Literal::U64(val)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/**
|
||||
* A type that wraps an FheType during graph construction
|
||||
*/
|
||||
pub struct CircuitNode<T: FheType> {
|
||||
/**
|
||||
* The node's index
|
||||
*/
|
||||
pub id: NodeIndex,
|
||||
|
||||
_phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: FheType> CircuitNode<T> {
|
||||
/**
|
||||
* Creates a new circuit node with the given node index.
|
||||
*/
|
||||
pub fn new(id: NodeIndex) -> Self {
|
||||
Self {
|
||||
id,
|
||||
_phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CircuitNode denoted as an input to a circuit graph.
|
||||
*/
|
||||
pub fn input() -> Self {
|
||||
with_ctx(|ctx| Self::new(ctx.add_input()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Denote this node as an output by appending an output circuit node.
|
||||
*/
|
||||
pub fn output(&self) -> Self {
|
||||
with_ctx(|ctx| Self::new(ctx.add_output(self.id)))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This trait denotes one may attempt to turn this type into a plaintext.
|
||||
*/
|
||||
pub trait TryIntoPlaintext {
|
||||
/**
|
||||
* Attempts to turn this type into a [`Plaintext`].
|
||||
*/
|
||||
fn try_into_plaintext(&self, params: &Params) -> Result<Plaintext>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A type which represents the fully qualified name and version of a datatype.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeName {
|
||||
/**
|
||||
* The fully qualified name of the type (including crate name)
|
||||
*/
|
||||
pub name: String,
|
||||
|
||||
/**
|
||||
* The semantic version of this type.
|
||||
*/
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl Serialize for TypeName {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let type_string = format!("{},{}", self.name, self.version);
|
||||
|
||||
serializer.serialize_str(&type_string)
|
||||
}
|
||||
}
|
||||
|
||||
struct TypeNameVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for TypeNameVisitor {
|
||||
type Value = String;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "A string of the form foo::bar::Baz,1.2.3")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> std::result::Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
if s.split(",").count() != 2 {
|
||||
Err(de::Error::invalid_value(de::Unexpected::Str(s), &self))
|
||||
} else {
|
||||
Ok(s.to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'de> Deserialize<'de> for TypeName {
|
||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let type_string = deserializer.deserialize_string(TypeNameVisitor)?;
|
||||
|
||||
let mut splits = type_string.split(",");
|
||||
|
||||
let typename = splits.next().unwrap();
|
||||
let version = Version::parse(splits.next().unwrap()).map_err(|e| {
|
||||
de::Error::custom(format!("Failed to parse version: {}", e))
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
name: typename.to_owned(),
|
||||
version
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_serialize_deserialize_typename() {
|
||||
let typename = TypeName {
|
||||
name: "foo::Bar".to_owned(),
|
||||
version: Version::new(42, 24, 6),
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&typename).unwrap();
|
||||
let deserialized: TypeName = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(deserialized.name, typename.name);
|
||||
assert_eq!(deserialized.version, typename.version);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,11 @@ pub enum Error {
|
||||
* When attempting to run a circuit, the wrong number of ciphertexts were provided.
|
||||
*/
|
||||
IncorrectCiphertextCount,
|
||||
|
||||
/**
|
||||
* An argument is incompatible with the parameters in the runtime.
|
||||
*/
|
||||
ParameterMismatch,
|
||||
}
|
||||
|
||||
impl From<sunscreen_circuit::Error> for Error {
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use seal::{
|
||||
BFVEvaluator, BfvEncryptionParametersBuilder, Ciphertext, Context as SealContext, Decryptor,
|
||||
Encryptor, Evaluator, GaloisKeys, KeyGenerator, Modulus, Plaintext, PublicKey,
|
||||
Encryptor, Evaluator, GaloisKeys, KeyGenerator, Modulus, Plaintext as SealPlaintext, PublicKey,
|
||||
RelinearizationKeys, SecretKey, SecurityLevel,
|
||||
};
|
||||
|
||||
@@ -62,6 +62,11 @@ pub enum Runtime {
|
||||
* This runtime is for the BFV scheme.
|
||||
*/
|
||||
Bfv {
|
||||
/**
|
||||
* The parameters used to construct the scheme used in this runtime.
|
||||
*/
|
||||
params: Params,
|
||||
|
||||
/**
|
||||
* The context associated with the BFV scheme. Created by [`RuntimeBuilder`].
|
||||
*/
|
||||
@@ -154,13 +159,21 @@ impl Runtime {
|
||||
|
||||
/**
|
||||
* Encrypts the given plaintext using the given public key.
|
||||
*
|
||||
* Returns [`Error::ParameterMismatch`] if the plaintext is incompatible with this runtime's
|
||||
* scheme.
|
||||
*/
|
||||
pub fn encrypt(&self, p: &Plaintext, public_key: &PublicKey) -> Result<Ciphertext> {
|
||||
let ciphertext = match self {
|
||||
Self::Bfv { context, .. } => {
|
||||
let encryptor = Encryptor::with_public_key(&context, public_key)?;
|
||||
match &p.inner {
|
||||
InnerPlaintext::Seal(p) => {
|
||||
let encryptor = Encryptor::with_public_key(&context, public_key)?;
|
||||
|
||||
encryptor.encrypt(&p)?
|
||||
encryptor.encrypt(&p)?
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -172,10 +185,15 @@ impl Runtime {
|
||||
*/
|
||||
pub fn decrypt(&self, c: &Ciphertext, secret_key: &SecretKey) -> Result<Plaintext> {
|
||||
let plaintext = match self {
|
||||
Self::Bfv { context, .. } => {
|
||||
Self::Bfv { context, params } => {
|
||||
let decryptor = Decryptor::new(&context, secret_key)?;
|
||||
|
||||
decryptor.decrypt(&c)?
|
||||
let plaintext = decryptor.decrypt(&c)?;
|
||||
|
||||
Plaintext {
|
||||
params: params.clone(),
|
||||
inner: InnerPlaintext::Seal(plaintext)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,6 +201,39 @@ impl Runtime {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
/**
|
||||
* The underlying backend implementation of a plaintext (e.g. SEAL's [`Plaintext`](seal::Plaintext)).
|
||||
*/
|
||||
pub enum InnerPlaintext {
|
||||
/**
|
||||
* This plaintext wraps a SEAL [`Plaintext`](seal::Plaintext).
|
||||
*/
|
||||
Seal(SealPlaintext),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
/**
|
||||
* Represents an encoded plaintext suitable for use in the underlying scheme.
|
||||
*/
|
||||
pub struct Plaintext {
|
||||
params: Params,
|
||||
|
||||
inner: InnerPlaintext,
|
||||
}
|
||||
|
||||
impl Plaintext {
|
||||
/**
|
||||
* Creates a new plaintext. Moves the given [`InnerPlaintext`] and [`Params`].
|
||||
*/
|
||||
pub fn new(inner: InnerPlaintext, params: Params) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
params
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to construct a runtime.
|
||||
*/
|
||||
@@ -220,7 +271,7 @@ impl RuntimeBuilder {
|
||||
|
||||
let context = SealContext::new(&bfv_params, true, self.params.security_level)?;
|
||||
|
||||
Ok(Runtime::Bfv { context })
|
||||
Ok(Runtime::Bfv { context, params: self.params })
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user