From 6856108c3ff2fdaf254c6415585199cbbd84aa7c Mon Sep 17 00:00:00 2001 From: Masato Imai Date: Fri, 22 Jul 2022 15:20:08 +0900 Subject: [PATCH] add encrypted calc in gpsl --- client.gpsl | 30 +++++++------ src/common/finite_field.rs | 2 +- src/elliptic_curve/encryption.rs | 21 ++++++++- src/gpsl/external_function.rs | 75 +++++++++++++++++++++++++++++++- src/gpsl/variable.rs | 2 + src/gpsl/vm/gpsl.rs | 52 ++++++++++++++++++---- src/main.rs | 59 +++++++++++++++++++++++++ 7 files changed, 215 insertions(+), 26 deletions(-) diff --git a/client.gpsl b/client.gpsl index 9e1b4ac..63f3aa2 100644 --- a/client.gpsl +++ b/client.gpsl @@ -1,20 +1,24 @@ -#[server(ip = "172.25.5.104:8080")] -fn add(a: num, b: num) { + +#[server(ip = "localhost:8080")] +fn encrypt_add(a: eep, b: eep) { + print("a: "); + println(a); + print("b: "); + println(b); return a + b; } -#[server(ip = "172.25.5.189:8080")] -fn mul(a: num, b: num) { - return a * b; -} fn main() { - println(add(1, 2)); - println(mul(2, 2)); - let i: num; - for (i = 0; i < 2000; i += 1) { - println(mul(i, i)); - } -} + let enc_a: eep; + let enc_b: eep; + enc_a = encrypt(10); + enc_b = encrypt(4); + + let enc_res: eep; + enc_res = encrypt_add(enc_a, enc_b); + + println(decrypt(enc_res)); +} diff --git a/src/common/finite_field.rs b/src/common/finite_field.rs index 12513d8..c5b8318 100644 --- a/src/common/finite_field.rs +++ b/src/common/finite_field.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use super::math::{mod_inv, plus_mod}; -#[derive(PartialEq, PartialOrd, Debug, Copy, Clone, Deserialize, Serialize)] +#[derive(PartialEq, Debug, Copy, Clone, PartialOrd, Deserialize, Serialize)] pub struct FiniteFieldElement { pub value: U512, pub p: U512, diff --git a/src/elliptic_curve/encryption.rs b/src/elliptic_curve/encryption.rs index 551d322..7c1d5c2 100644 --- a/src/elliptic_curve/encryption.rs +++ b/src/elliptic_curve/encryption.rs @@ -1,4 +1,5 @@ use std::{ + fmt::Display, ops::{Add, Sub}, sync::mpsc, thread, @@ -15,7 +16,7 @@ use rand_chacha::{ use super::elliptic_curve::{EllipticCurve, EllipticCurvePoint}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Encryption { pub ellictic_curve: EllipticCurve, pub base_point: EllipticCurvePoint, @@ -29,6 +30,24 @@ pub struct EncryptedEllipticCurvePoint { pub rp: EllipticCurvePoint, } +impl EncryptedEllipticCurvePoint { + pub fn default() -> Self { + Self { + data: EllipticCurvePoint::Infinity, + rp: EllipticCurvePoint::Infinity, + } + } +} + +impl Display for EncryptedEllipticCurvePoint { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.data { + EllipticCurvePoint::Infinity => write!(f, "Infinity"), + EllipticCurvePoint::Point { x, y, .. } => write!(f, "{:x}{:x}", x.value, y.value), + } + } +} + impl Add for EncryptedEllipticCurvePoint { type Output = Self; diff --git a/src/gpsl/external_function.rs b/src/gpsl/external_function.rs index 370f964..88a9396 100644 --- a/src/gpsl/external_function.rs +++ b/src/gpsl/external_function.rs @@ -1,6 +1,10 @@ +use primitive_types::U512; use serde::{Deserialize, Serialize}; -use crate::gpsl::{permission::Permission, variable::Variable}; +use crate::{ + elliptic_curve::{elliptic_curve::EllipticCurvePoint, encryption::Encryption}, + gpsl::{permission::Permission, variable::Variable}, +}; #[derive(PartialEq, Debug, Serialize, Deserialize)] pub enum ExternalFuncStatus { @@ -16,20 +20,84 @@ pub struct ExternalFuncReturn { pub value: Option, } +#[derive(Debug, Serialize, Deserialize)] +pub struct ExternalFunctionCallData { + pub encryption: Encryption, + pub private_key: Option, + pub public_key: Option, +} + #[allow(dead_code)] pub const STD_FUNC: fn( String, Vec, Vec, Vec, -) -> ExternalFuncReturn = |name, args, accept, reject| { + ExternalFunctionCallData, +) -> ExternalFuncReturn = |name, args, accept, reject, data| { let name = name.as_str(); match name { + "encrypt" => { + let encryption = data.encryption; + let plain = match args[0] { + Variable::Number { value } => U512::from(value), + _ => panic!("encrypt: first argument must be a number"), + }; + let ec = encryption.plain_to_ec_point(plain); + let eep = encryption.encrypt(ec, data.public_key.unwrap(), None); + ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(Variable::PureEncrypted { value: eep }), + } + } + "decrypt" => { + let encryption = data.encryption; + let eep = match args[0] { + Variable::PureEncrypted { value } => value, + _ => panic!("decrypt: first argument must be a pure encrypted point"), + }; + let plain = Encryption::decrypt(eep, data.private_key.unwrap()); + let plain = encryption.ec_point_to_plain(plain); + ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(Variable::Number { + value: plain.as_u64() as i64, + }), + } + } + "to_u512" => { + if args.len() != 1 { + return ExternalFuncReturn { + status: ExternalFuncStatus::ERROR, + value: None, + }; + } + let arg = args[0].clone(); + match arg { + Variable::Number { value } => { + return ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(Variable::U512 { + value: value.into(), + }), + }; + } + _ => { + return ExternalFuncReturn { + status: ExternalFuncStatus::ERROR, + value: None, + }; + } + } + } "println" => { if accept.contains(&Permission::StdIo) && !reject.contains(&Permission::StdIo) { match &args[0] { Variable::Text { value } => println!("{}", value), Variable::Number { value } => println!("{}", value), + Variable::U512 { value } => println!("{:x}", value), + Variable::PureEncrypted { value } => println!("{}", value), + Variable::PairedEncrypted { value } => println!("{:x}", value.value), _ => {} } ExternalFuncReturn { @@ -48,6 +116,9 @@ pub const STD_FUNC: fn( match &args[0] { Variable::Text { value } => print!("{}", value), Variable::Number { value } => print!("{}", value), + Variable::U512 { value } => print!("{:x}", value), + Variable::PureEncrypted { value } => print!("{}", value), + Variable::PairedEncrypted { value } => print!("{:x}", value.value), _ => {} } ExternalFuncReturn { diff --git a/src/gpsl/variable.rs b/src/gpsl/variable.rs index 24af70f..0d33f87 100644 --- a/src/gpsl/variable.rs +++ b/src/gpsl/variable.rs @@ -2,6 +2,7 @@ use crate::{ common::finite_field::FiniteFieldElement, elliptic_curve::encryption::EncryptedEllipticCurvePoint, }; +use primitive_types::U512; use serde::{Deserialize, Serialize}; #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] @@ -11,5 +12,6 @@ pub enum Variable { Return { value: Box }, PureEncrypted { value: EncryptedEllipticCurvePoint }, PairedEncrypted { value: FiniteFieldElement }, + U512 { value: U512 }, None {}, } diff --git a/src/gpsl/vm/gpsl.rs b/src/gpsl/vm/gpsl.rs index 8672cb5..b1d02ef 100644 --- a/src/gpsl/vm/gpsl.rs +++ b/src/gpsl/vm/gpsl.rs @@ -1,11 +1,14 @@ -use crate::elliptic_curve::encryption::EncryptedEllipticCurvePoint; -use crate::elliptic_curve::encryption::EncryptedEllipticCurvePoint; -use crate::gpsl::external_function::{ExternalFuncReturn, ExternalFuncStatus}; +use crate::elliptic_curve::elliptic_curve::EllipticCurvePoint; +use crate::elliptic_curve::encryption::{EncryptedEllipticCurvePoint, Encryption}; +use crate::gpsl::external_function::{ + ExternalFuncReturn, ExternalFuncStatus, ExternalFunctionCallData, +}; use crate::gpsl::node::*; use crate::gpsl::permission::Permission; use crate::gpsl::source::Source; use crate::gpsl::variable::*; use log::*; +use primitive_types::U512; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, VecDeque}; use std::io::{BufRead, BufReader, Write}; @@ -26,11 +29,21 @@ pub struct GPSL { pub functions: Option>>, pub server_functions: Option>>>, pub servers: Option>>>, + pub encryption: Encryption, + pub private_key: Option, + pub public_key: Option, pub global_variables: Vec, pub source: Source, pub blocks: VecDeque, - pub external_func: - Vec, Vec, Vec) -> ExternalFuncReturn>, + pub external_func: Vec< + fn( + String, + Vec, + Vec, + Vec, + ExternalFunctionCallData, + ) -> ExternalFuncReturn, + >, } #[derive(Clone, Debug)] @@ -63,8 +76,17 @@ impl GPSL { functions: Option>>, server_functions: Option>>>, servers: Option>>>, + encryption: Encryption, + private_key: Option, + public_key: Option, external_func: Vec< - fn(String, Vec, Vec, Vec) -> ExternalFuncReturn, + fn( + String, + Vec, + Vec, + Vec, + ExternalFunctionCallData, + ) -> ExternalFuncReturn, >, ) -> GPSL { GPSL { @@ -72,6 +94,9 @@ impl GPSL { functions, server_functions, servers, + encryption, + private_key, + public_key, global_variables: vec![], blocks: VecDeque::new(), external_func, @@ -234,6 +259,11 @@ impl GPSL { args_value.clone(), block.accept.clone(), block.reject.clone(), + ExternalFunctionCallData { + encryption: self.encryption.clone(), + private_key: self.private_key, + public_key: self.public_key, + }, ); if res.status == ExternalFuncStatus::SUCCESS { return Ok(res.value); @@ -268,15 +298,15 @@ impl GPSL { let lhs = self.evaluate(lhs).expect("Cannot evaluate lhs."); let rhs = self.evaluate(rhs).expect("Cannot evaluate rhs."); - if let Some(lhs) = lhs { + if let Some(lhs) = lhs.clone() { if let Some(rhs) = rhs { match kind { - NodeKind::ADD => match GPSL::extract_number(lhs) { + NodeKind::ADD => match GPSL::extract_number(lhs.clone()) { Ok(lhs) => match GPSL::extract_number(rhs) { Ok(rhs) => Ok(Some(Variable::Number { value: lhs + rhs })), Err(err) => Err(err), }, - Err(err) => match GPSL::extract_eep(lhs) { + Err(_) => match GPSL::extract_eep(lhs) { Ok(lhs) => match GPSL::extract_eep(rhs) { Ok(rhs) => { Ok(Some(Variable::PureEncrypted { value: lhs + rhs })) @@ -532,6 +562,10 @@ impl GPSL { Variable::Text { value: String::default(), } + } else if var_type == "eep" { + Variable::PureEncrypted { + value: EncryptedEllipticCurvePoint::default(), + } } else { return Err(format!("{}: 未知の型です。", var_type)); }; diff --git a/src/main.rs b/src/main.rs index 5d1398c..19d09f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ mod common; mod elliptic_curve; mod gpsl; +use common::finite_field::FiniteFieldElement; +use elliptic_curve::elliptic_curve::EllipticCurve; +use elliptic_curve::encryption::Encryption; use gpsl::external_function::ExternalFuncReturn; use gpsl::external_function::ExternalFuncStatus; use gpsl::node::Node; @@ -8,6 +11,7 @@ use gpsl::node::NodeKind; use gpsl::vm::gpsl::ServerFunctionCall; use gpsl::{external_function::STD_FUNC, source::*, tokenizer::*, vm::gpsl::*}; use log::*; +use primitive_types::U512; use std::env; use std::io::BufRead; use std::io::BufReader; @@ -89,6 +93,52 @@ fn listen_tcp_server(port: u16) -> TcpStream { panic!("Cannot connect to client"); } +fn generate_encryption() -> Encryption { + let p = U512::from_str_radix( + "115792089237316195423570985008687907853269984665640564039457584007908834671663", + 10, + ) + .unwrap(); + + let secp256_k1_a = FiniteFieldElement::new(U512::from(0u8), p); + let secp256_k1_b = FiniteFieldElement::new(U512::from(7u8), p); + let secp256_k1_base_x = FiniteFieldElement::new( + U512::from_str_radix( + "55066263022277343669578718895168534326250603453777594175500187360389116729240", + 10, + ) + .unwrap(), + p, + ); + let secp256_k1_base_y = FiniteFieldElement::new( + U512::from_str_radix( + "32670510020758816978083085130507043184471273380659243275938904335757337482424", + 10, + ) + .unwrap(), + p, + ); + let secp256_k1_order = FiniteFieldElement::new( + U512::from_str_radix( + "115792089237316195423570985008687907852837564279074904382605163141518161494337", + 10, + ) + .unwrap(), + p, + ); + let ec = EllipticCurve { + a: secp256_k1_a, + b: secp256_k1_b, + }; + + Encryption { + ellictic_curve: ec, + base_point: ec.point(secp256_k1_base_x, secp256_k1_base_y), + order: secp256_k1_order, + plain_mapping: vec![], + } +} + fn main() { env::set_var("RUST_LOG", "info"); env_logger::init(); @@ -126,6 +176,9 @@ fn server(args: Args) { Some(functions), Some(HashMap::new()), Some(HashMap::new()), + generate_encryption(), + None, + None, vec![STD_FUNC], ); @@ -240,11 +293,17 @@ fn client(args: Args) { servers.insert(ip, Arc::new(Mutex::new(stream))); } + let encryption = generate_encryption(); + let private_key = Encryption::get_private_key(); + let mut gpsl = GPSL::new( source, Some(functions), Some(server_functions), Some(servers), + encryption.clone(), + Some(private_key), + Some(encryption.get_public_key(private_key)), vec![STD_FUNC], ); let res = gpsl.run("main".to_string(), HashMap::new());