diff --git a/client2.gpsl b/client2.gpsl index eb7ed2b..6cbc93a 100644 --- a/client2.gpsl +++ b/client2.gpsl @@ -1,15 +1,5 @@ fn main() { - let a = encrypt(16) - println("a: " + a) - let b = encrypt(60) - println("b: " + b) - let c = encrypt(48) - println("c: " + c) - let d = encrypt(2) - println("d: " + d) - let e = encrypt(24) - println("e: " + e) - let f = encrypt(15) - let r = a + b + c + d + e - f - println("(a + b + c + d + e - f) * 2 = " + decrypt(r * 2)) + let a = encrypt(3); + let b = encrypt2(2); + println(decrypt_pair(a * b)); } diff --git a/gpsl_conf b/gpsl_conf index c9cd335..d0b09fa 100644 Binary files a/gpsl_conf and b/gpsl_conf differ diff --git a/src/args.rs b/src/args.rs index 1da1535..d5421a6 100644 --- a/src/args.rs +++ b/src/args.rs @@ -17,4 +17,7 @@ pub struct Args { #[clap(short, long, takes_value = false)] pub compile: bool, + + #[clap(short, long, value_parser)] + pub curve: Option, } diff --git a/src/client.rs b/src/client.rs index 236215b..6b34ce2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -133,9 +133,17 @@ pub fn start_client(args: Args) { servers.insert(ip, Arc::new(Mutex::new(stream))); } - let encryption = Encryption::secp256k1(); + let encryption = if let Some(curve) = args.curve { + if curve == String::from("pairing") { + Encryption::pairing_friendly() + } else { + panic!("Unknown curve"); + } + } else { + Encryption::secp256k1() + }; - let config = Config::read_or_create(); + let config = Config::read_or_create(Some(encryption.clone())); let mut gpsl = GPSL::new( Some(functions), @@ -143,7 +151,9 @@ pub fn start_client(args: Args) { Some(servers), encryption.clone(), config.private_key, + config.private_key2, config.public_key, + config.public_key2, vec![STD_FUNC], ); let res = gpsl.run("main".to_string(), HashMap::new()); diff --git a/src/config.rs b/src/config.rs index 5d87b89..f90e7a9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,7 +14,9 @@ use crate::elliptic_curve::encryption::Encryption; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ConfigFile { pub private_key: Option, + pub private_key2: Option, pub public_key: Option, + pub public_key2: Option, } impl ConfigFile { @@ -29,6 +31,16 @@ impl ConfigFile { } }; + let private_key2 = { + if let Some(private_key2) = config.private_key2 { + let s = private_key2.to_string(); + let encode = base64::encode(&s); + Some(encode) + } else { + None + } + }; + let public_key = { if let Some(public_key) = config.public_key { let s = serde_json::to_string(&public_key).unwrap(); @@ -39,9 +51,21 @@ impl ConfigFile { } }; + let public_key2 = { + if let Some(public_key2) = config.public_key2 { + let s = serde_json::to_string(&public_key2).unwrap(); + let encode = base64::encode(&s); + Some(encode) + } else { + None + } + }; + Self { private_key, + private_key2, public_key, + public_key2, } } } @@ -49,19 +73,24 @@ impl ConfigFile { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Config { pub private_key: Option, + pub private_key2: Option, pub public_key: Option, + pub public_key2: Option, } impl Config { - pub fn read_or_create() -> Self { - let encryption = Encryption::secp256k1(); + pub fn read_or_create(encryption: Option) -> Self { + let encryption = encryption.unwrap_or(Encryption::secp256k1()); if Path::new("gpsl_conf").exists() { Config::from_file("gpsl_conf") } else { let private_key = Encryption::get_private_key(); + let private_key2 = Encryption::get_private_key(); let config = Config { private_key: Some(private_key), + private_key2: Some(private_key2), public_key: Some(encryption.get_public_key(private_key)), + public_key2: Some(encryption.get_public_key(private_key2)), }; let mut file = File::create("gpsl_conf").unwrap(); @@ -99,6 +128,16 @@ impl Config { } }; + let private_key2 = { + if let Some(private_key2) = config.private_key2 { + let decoded = base64::decode(&private_key2).unwrap(); + let s = std::str::from_utf8(&decoded).unwrap(); + Some(U512::from_str_radix(s, 10).unwrap()) + } else { + None + } + }; + let public_key = { if let Some(public_key) = config.public_key { let decoded = base64::decode(&public_key).unwrap(); @@ -110,9 +149,22 @@ impl Config { } }; + let public_key2 = { + if let Some(public_key2) = config.public_key2 { + let decoded = base64::decode(&public_key2).unwrap(); + let s = std::str::from_utf8(&decoded).unwrap(); + let r = EllipticCurvePoint::from_str(s).unwrap(); + Some(r) + } else { + None + } + }; + Config { private_key, + private_key2, public_key, + public_key2, } } } diff --git a/src/elliptic_curve/encryption.rs b/src/elliptic_curve/encryption.rs index 9e4913f..35fa8db 100644 --- a/src/elliptic_curve/encryption.rs +++ b/src/elliptic_curve/encryption.rs @@ -20,6 +20,8 @@ use super::elliptic_curve::{EllipticCurve, EllipticCurvePoint}; pub struct Encryption { pub ellictic_curve: EllipticCurve, pub base_point: EllipticCurvePoint, + pub base_point2: Option, + pub r: Option, pub order: FiniteFieldElement, pub plain_mapping: Vec, } @@ -94,6 +96,52 @@ impl Mul for EncryptedEllipticCurvePoint { } impl Encryption { + pub fn pair_multiply( + &self, + p: EncryptedEllipticCurvePoint, + q: EncryptedEllipticCurvePoint, + ) -> ( + FiniteFieldElement, + FiniteFieldElement, + FiniteFieldElement, + FiniteFieldElement, + ) { + let r = self.r.unwrap(); + let a = EllipticCurvePoint::weil(p.data, q.data, r); + let b = EllipticCurvePoint::weil(p.data, q.rp, r); + let c = EllipticCurvePoint::weil(p.rp, q.data, r); + let d = EllipticCurvePoint::weil(p.rp, q.rp, r); + + (a, b, c, d) + } + + pub fn decrypt_pair( + &self, + a: FiniteFieldElement, + b: FiniteFieldElement, + c: FiniteFieldElement, + d: FiniteFieldElement, + private_key: U512, + private_key2: U512, + ) -> U512 { + let f = + EllipticCurvePoint::weil(self.base_point, self.base_point2.unwrap(), self.r.unwrap()); + let dec = + a * d.pow(private_key * private_key2) / b.pow(private_key2) / c.pow(private_key) * f; + + let mut i = U512::one(); + let mut b = f; + while b != dec { + b = b * f; + i += U512::one(); + } + if i < U512::from(7u8) { + i + } else { + U512::zero() + } + } + pub fn secp256k1() -> Self { let p = U512::from_str_radix( "115792089237316195423570985008687907853269984665640564039457584007908834671663", @@ -135,11 +183,49 @@ impl Encryption { Self { ellictic_curve: ec, base_point: ec.point(secp256_k1_base_x, secp256_k1_base_y), + base_point2: None, + r: None, order: secp256_k1_order, plain_mapping: vec![], } } + pub fn pairing_friendly() -> Self { + let p = U512::from_str_radix("1009", 10).unwrap(); + let ec_a = FiniteFieldElement::new(U512::from(37u8), p); + let ec_b = FiniteFieldElement::new(U512::from_str_radix("0", 10).unwrap(), p); + let pp = { + let x = FiniteFieldElement::new(U512::from_str_radix("417", 10).unwrap(), p); + let y = FiniteFieldElement::new(U512::from_str_radix("952", 10).unwrap(), p); + EllipticCurvePoint::Point { + x, + y, + a: ec_a, + b: ec_b, + } + }; + let pd = { + let x = FiniteFieldElement::new(U512::from_str_radix("561", 10).unwrap(), p); + let y = FiniteFieldElement::new(U512::from_str_radix("153", 10).unwrap(), p); + EllipticCurvePoint::Point { + x, + y, + a: ec_a, + b: ec_b, + } + }; + let ec = EllipticCurve { a: ec_a, b: ec_b }; + + Self { + ellictic_curve: ec, + base_point: pp, + base_point2: Some(pd), + r: Some(U512::from(7u8)), + order: FiniteFieldElement::new(U512::from_str_radix("7", 10).unwrap(), p), + plain_mapping: vec![], + } + } + pub fn ec_point_to_plain(&self, point: EllipticCurvePoint) -> U512 { match point { EllipticCurvePoint::Infinity => return U512::from(0u8), @@ -219,6 +305,14 @@ impl Encryption { return self.base_point * m; } + pub fn plain_to_ec_point_sub(&self, m: U512) -> EllipticCurvePoint { + if m == U512::from(0u8) { + return EllipticCurvePoint::Infinity; + } + + return self.base_point2.unwrap() * m; + } + pub fn decrypt(ecc_p: EncryptedEllipticCurvePoint, private_key: U512) -> EllipticCurvePoint { let rq = ecc_p.rp * private_key; ecc_p.data + (-rq) diff --git a/src/gpsl/external_function.rs b/src/gpsl/external_function.rs index 7465ef8..02a616e 100644 --- a/src/gpsl/external_function.rs +++ b/src/gpsl/external_function.rs @@ -25,7 +25,9 @@ pub struct ExternalFuncReturn { pub struct ExternalFunctionCallData { pub encryption: Encryption, pub private_key: Option, + pub private_key2: Option, pub public_key: Option, + pub public_key2: Option, } #[allow(dead_code)] @@ -135,6 +137,20 @@ pub const STD_FUNC: fn( value: Some(Variable::PureEncrypted { value: eep }), } } + "encrypt2" => { + let encryption = data.encryption; + let plain = match args[0] { + Variable::Number { value } => U512::from(value), + Variable::U512 { value } => value, + _ => panic!("encrypt: first argument must be a number"), + }; + let ec = encryption.plain_to_ec_point_sub(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] { @@ -150,6 +166,27 @@ pub const STD_FUNC: fn( }), } } + "decrypt_pair" => { + let encryption = data.encryption; + let (a, b, c, d) = match args[0] { + Variable::PairedEncrypted { a, b, c, d } => (a, b, c, d), + _ => panic!("decrypt: first argument must be a pure encrypted point"), + }; + + let plain = encryption.decrypt_pair( + a, + b, + c, + d, + data.private_key.unwrap(), + data.private_key2.unwrap(), + ); + + ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(Variable::U512 { value: plain }), + } + } "to_num" => { let num = match args[0].clone() { Variable::Number { value } => value, @@ -219,7 +256,9 @@ pub const STD_FUNC: fn( Variable::Number { value } => println!("{}", value), Variable::U512 { value } => println!("{:x}", value), Variable::PureEncrypted { value } => println!("{}", value), - Variable::PairedEncrypted { value } => println!("{:x}", value.value), + Variable::PairedEncrypted { a, b, c, d } => { + println!("{:x}{:x}{:x}{:x}", a.value, b.value, c.value, d.value) + } Variable::Vec { value, gpsl_type } => { STD_FUNC( "print".to_string(), @@ -232,7 +271,9 @@ pub const STD_FUNC: fn( ExternalFunctionCallData { encryption: data.encryption.clone(), private_key: data.private_key.clone(), + private_key2: data.private_key2.clone(), public_key: data.public_key.clone(), + public_key2: data.public_key2.clone(), }, ); println!(""); @@ -257,7 +298,9 @@ pub const STD_FUNC: fn( Variable::Number { value } => print!("{}", value), Variable::U512 { value } => print!("{:x}", value), Variable::PureEncrypted { value } => print!("{}", value), - Variable::PairedEncrypted { value } => print!("{:x}", value.value), + Variable::PairedEncrypted { a, b, c, d } => { + print!("{:x}{:x}{:x}{:x}", a.value, b.value, c.value, d.value) + } Variable::Vec { value, .. } => { print!("["); let mut f = false; @@ -275,7 +318,9 @@ pub const STD_FUNC: fn( ExternalFunctionCallData { encryption: data.encryption.clone(), private_key: data.private_key, + private_key2: data.private_key2, public_key: data.public_key, + public_key2: data.public_key2, }, ); } diff --git a/src/gpsl/variable.rs b/src/gpsl/variable.rs index 7532a3b..373f234 100644 --- a/src/gpsl/variable.rs +++ b/src/gpsl/variable.rs @@ -22,7 +22,10 @@ pub enum Variable { value: EncryptedEllipticCurvePoint, }, PairedEncrypted { - value: FiniteFieldElement, + a: FiniteFieldElement, + b: FiniteFieldElement, + c: FiniteFieldElement, + d: FiniteFieldElement, }, U512 { value: U512, @@ -60,7 +63,10 @@ impl Variable { Variable::Text { value } => Some(value.clone()), Variable::Number { value } => Some(value.to_string()), Variable::PureEncrypted { value } => Some(value.to_string()), - Variable::PairedEncrypted { value } => Some(value.to_string()), + Variable::PairedEncrypted { a, b, c, d } => Some(format!( + "{:x}{:x}{:x}{:x}", + a.value, b.value, c.value, d.value + )), Variable::U512 { value } => Some(value.to_string()), Variable::Vec { value, .. } => { let mut result = String::new(); diff --git a/src/gpsl/vm/gpsl.rs b/src/gpsl/vm/gpsl.rs index 1beb09b..cca84c3 100644 --- a/src/gpsl/vm/gpsl.rs +++ b/src/gpsl/vm/gpsl.rs @@ -31,7 +31,9 @@ pub struct GPSL { pub servers: Option>>>, pub encryption: Encryption, pub private_key: Option, + pub private_key2: Option, pub public_key: Option, + pub public_key2: Option, pub global_variables: Vec, pub blocks: VecDeque, pub external_func: Vec< @@ -76,7 +78,9 @@ impl GPSL { servers: Option>>>, encryption: Encryption, private_key: Option, + private_key2: Option, public_key: Option, + public_key2: Option, external_func: Vec< fn( String, @@ -93,7 +97,9 @@ impl GPSL { servers, encryption, private_key, + private_key2, public_key, + public_key2, global_variables: vec![], blocks: VecDeque::new(), external_func, @@ -295,7 +301,9 @@ impl GPSL { ExternalFunctionCallData { encryption: self.encryption.clone(), private_key: self.private_key, + private_key2: self.private_key2, public_key: self.public_key, + public_key2: self.public_key2, }, ); if res.status == ExternalFuncStatus::SUCCESS { @@ -435,6 +443,10 @@ impl GPSL { Variable::U512 { value: rhs } => { Ok(Some(Variable::PureEncrypted { value: lhs * rhs })) } + Variable::PureEncrypted { value: rhs } => { + let (a, b, c, d) = self.encryption.pair_multiply(lhs, rhs); + Ok(Some(Variable::PairedEncrypted { a, b, c, d })) + } _ => Err("Cannot multiply non-number to ppe.".to_string()), }, _ => Err("Cannot multiply non-number.".to_string()), diff --git a/src/server.rs b/src/server.rs index f5f37c7..57c30d1 100644 --- a/src/server.rs +++ b/src/server.rs @@ -39,11 +39,23 @@ pub fn start_server(args: Args) { let functions: HashMap> = serde_json::from_str(&buf).unwrap(); debug!("Received: {:?}", functions); + let encryption = if let Some(curve) = args.curve.clone() { + if curve == "pairing".to_string() { + Encryption::pairing_friendly() + } else { + panic!("Unknown curve: {}", curve); + } + } else { + Encryption::secp256k1() + }; + let mut gpsl = GPSL::new( Some(functions), Some(HashMap::new()), Some(HashMap::new()), - Encryption::secp256k1(), + encryption, + None, + None, None, None, vec![STD_FUNC],