From 790209c646ed386f1a8baca4f014d7cf40d92052 Mon Sep 17 00:00:00 2001 From: mii Date: Sun, 29 May 2022 23:14:47 +0900 Subject: [PATCH] =?UTF-8?q?=E6=9A=97=E5=8F=B7=E5=8C=96=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 72 +++++++++++++++++++++++++--- Cargo.toml | 4 +- src/common/finite_field.rs | 19 ++++++-- src/elliptic_curve/elliptic_curve.rs | 35 +++++++++----- src/elliptic_curve/encryption.rs | 57 ++++++++++++++++++++-- src/main.rs | 37 ++++++++------ 6 files changed, 181 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bd6d90..86cadaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,8 @@ version = "0.1.0" dependencies = [ "bigdecimal", "primitive-types", + "rand 0.7.3", + "rand_chacha 0.3.1", ] [[package]] @@ -76,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -87,6 +89,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.6" @@ -95,7 +108,7 @@ checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -237,6 +250,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -244,8 +270,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -255,7 +291,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -264,7 +309,16 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom", + "getrandom 0.2.6", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -349,6 +403,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 72b3de2..15c0d0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" [dependencies] bigdecimal = "0.3.0" -primitive-types = "0.11.1" \ No newline at end of file +primitive-types = "0.11.1" +rand = {version = "0.7.3"} +rand_chacha = "*" \ No newline at end of file diff --git a/src/common/finite_field.rs b/src/common/finite_field.rs index 4e70ec4..a48fa73 100644 --- a/src/common/finite_field.rs +++ b/src/common/finite_field.rs @@ -1,9 +1,9 @@ -use std::{ops::{Add, Sub, Mul, AddAssign, SubAssign, Div}, fmt::Debug}; +use std::{ops::{Add, Sub, Mul, AddAssign, SubAssign, Div, Neg}, fmt::Debug}; use bigdecimal::{num_bigint::BigInt, Num}; use primitive_types::U512; -use super::math::mod_inv; +use super::math::{mod_inv, plus_mod}; #[derive(PartialEq, Debug, Copy, Clone)] pub struct FiniteFieldElement { @@ -107,13 +107,22 @@ impl Div for FiniteFieldElement { fn div(self, rhs: Self) -> Self::Output { let left = BigInt::from_str_radix(&format!("{}", rhs.value), 10).unwrap(); let right = BigInt::from_str_radix(&format!("{}", rhs.p), 10).unwrap(); - let mod_inv = mod_inv(left, right); - println!("mod_inv: {:?}", mod_inv); - let mod_inv = U512::from_str_radix(&format!("{}", mod_inv), 10).unwrap(); + let mod_inv = U512::from_str_radix(&format!("{}", mod_inv(left, right)), 10).unwrap(); self * FiniteFieldElement::new(mod_inv, rhs.p) } } +impl Neg for FiniteFieldElement { + type Output = Self; + + fn neg(self) -> Self::Output { + let value = -BigInt::from_str_radix(&format!("{}", self.value), 10).unwrap(); + let p = BigInt::from_str_radix(&format!("{}", self.p), 10).unwrap(); + let plus_mod = plus_mod(value, p); + FiniteFieldElement::new(U512::from_str_radix(&format!("{}", plus_mod), 10).unwrap(), self.p) + } +} + #[cfg(test)] mod tests { use primitive_types::U512; diff --git a/src/elliptic_curve/elliptic_curve.rs b/src/elliptic_curve/elliptic_curve.rs index 76afad6..9038e6a 100644 --- a/src/elliptic_curve/elliptic_curve.rs +++ b/src/elliptic_curve/elliptic_curve.rs @@ -1,4 +1,4 @@ -use std::ops::{Add, Mul}; +use std::ops::{Add, Mul, Neg}; use primitive_types::U512; @@ -38,6 +38,18 @@ impl EllipticCurvePoint { } } +impl Neg for EllipticCurvePoint { + type Output = Self; + + fn neg(self) -> Self::Output { + if let EllipticCurvePoint::Point { x, y, a, b } = self { + EllipticCurvePoint::Point { x, y: -y, a, b } + } else { + return self + } + } +} + impl Add for EllipticCurvePoint { type Output = Self; @@ -46,8 +58,6 @@ impl Add for EllipticCurvePoint { EllipticCurvePoint::Point { x: x1, y: y1, a, b } => { match rhs { EllipticCurvePoint::Point { x: x2, y: y2, a: a2, b: b2 } => { - println!("default plus"); - let p = x1.p; if a != a2 || b != b2 { panic!("Cannot add different curve point."); @@ -58,14 +68,11 @@ impl Add for EllipticCurvePoint { } let l = if x1 == x2 && y1 == y2 { - println!("twice"); let t = x1 * x1 * FiniteFieldElement::new(U512::from(3), p) + a; let u = y1 * FiniteFieldElement::new(U512::from(2), p); let a = t / u; - println!("t: {:?}\nu: {:?}\na: {:?}", t, u, a); a } else { - println!("plus"); (y2 - y1) / (x2 - x1) }; let x = l * l - x1 - x2; @@ -85,13 +92,17 @@ impl Mul for EllipticCurvePoint { type Output = Self; fn mul(self, rhs: U512) -> Self::Output { + let mut tmp = self; + let mut point = EllipticCurvePoint::Infinity; let mut n = rhs; - let mut r: EllipticCurvePoint = EllipticCurvePoint::Infinity; - while n > U512::from(0) { - r = r + self; - n = n - U512::from(1); - } + while n > U512::zero() { + if n & U512::one() == U512::one() { + point = point + tmp; + } - r + n = n >> 1; + tmp = tmp + tmp; + } + point } } diff --git a/src/elliptic_curve/encryption.rs b/src/elliptic_curve/encryption.rs index 57fc5ee..d28a4c1 100644 --- a/src/elliptic_curve/encryption.rs +++ b/src/elliptic_curve/encryption.rs @@ -1,6 +1,9 @@ -use primitive_types::U512; +use std::ops::Add; + +use primitive_types::{U512, U256}; use crate::common::finite_field::FiniteFieldElement; +use rand_chacha::{ChaCha20Rng, rand_core::{SeedableRng, RngCore}}; use super::elliptic_curve::{EllipticCurve, EllipticCurvePoint}; @@ -12,9 +15,25 @@ pub struct Encryption { pub plain_mapping: Vec } +#[derive(Debug)] +pub struct EncryptedEllipticCurvePoint { + pub data: EllipticCurvePoint, + pub rp: EllipticCurvePoint +} + +impl Add for EncryptedEllipticCurvePoint { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + data: self.data + rhs.data, + rp: self.rp + rhs.rp + } + } +} + impl Encryption { pub fn ec_point_to_plain(&self, point: EllipticCurvePoint) -> U512 { - println!("ec point to plain"); match point { EllipticCurvePoint::Infinity => { return U512::from(0u8) @@ -24,7 +43,6 @@ impl Encryption { let mut x = 0i64; - println!("get plain mapping"); for p in &self.plain_mapping { match p { EllipticCurvePoint::Point { x: px, y: py, a: _, b: _ } => { @@ -51,7 +69,6 @@ impl Encryption { self.plain_mapping[x as usize] }; - println!("calc mapping"); while x < i64::MAX && !(match tmp { EllipticCurvePoint::Point { x: tx, y: ty, a: _, b: _ } => match point { EllipticCurvePoint::Point { x: px, y: py, a: _, b: _ } => tx == px && ty == py, @@ -76,4 +93,36 @@ impl Encryption { return self.base_point * m; } + + pub fn decrypt(ecc_p: EncryptedEllipticCurvePoint, private_key: U512) -> EllipticCurvePoint { + let rq = ecc_p.rp * private_key; + ecc_p.data + (-rq) + } + + pub fn encrypt(&self, message: EllipticCurvePoint, public_key: EllipticCurvePoint, r: Option) -> EncryptedEllipticCurvePoint { + let ra = if let Some(ra) = r { + ra + } else { + Self::random() + }; + + EncryptedEllipticCurvePoint { data: message + public_key * ra, rp: self.base_point * ra } + } + + pub fn get_public_key(&self, private_key: U512) -> EllipticCurvePoint { + self.base_point * private_key + } + + pub fn get_private_key() -> U512 { + Self::random() + } + + pub fn random() -> U512 { + let mut csprng = ChaCha20Rng::from_entropy(); + + let mut data = [0u8; 32]; + csprng.fill_bytes(&mut data); + + U512::from(U256::from(data)) + } } diff --git a/src/main.rs b/src/main.rs index 114691e..de8a1f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,7 @@ fn main() { let secp256_k1_b = FiniteFieldElement::new(U512::from(1u8), p); let secp256_k1_base_x = FiniteFieldElement::new(U512::from_str_radix("0", 10).unwrap(), p); let secp256_k1_base_y = FiniteFieldElement::new(U512::from_str_radix("1", 10).unwrap(), p); - let secp256_k1_order = FiniteFieldElement::new(U512::from_str_radix("2", 10).unwrap(), p); + let secp256_k1_order = FiniteFieldElement::nimage.pngew(U512::from_str_radix("2", 10).unwrap(), p); */ let ec = EllipticCurve { a: secp256_k1_a, @@ -36,19 +36,26 @@ fn main() { plain_mapping: vec![] }; - //let twenty = encryption.plain_to_ec_point(U512::from(12u8)); - //let ten = encryption.plain_to_ec_point(U512::from(10u8)); - //let two = encryption.plain_to_ec_point(U512::from(2u8)); - //println!("{:?}", twenty); - //println!("{:?}", ten + two); - //println!("{:?}", encryption.ec_point_to_plain(ten)); - let p = encryption.base_point + encryption.base_point; - println!("{:?}", p); - println!("{}", p.check()); - println!("{}", encryption.base_point.check()); -/* - let t = encryption.base_point + encryption.base_point; - println!("{:?}", t); - println!("{:?}", encryption.base_point); + let private_key = Encryption::get_private_key(); + println!("private_key: {:?}", private_key); + let public_key = encryption.get_public_key(private_key); + println!("public_key: {:?}", public_key); + + let ten = encryption.plain_to_ec_point(U512::from(13u32)); + let e_ten = encryption.encrypt(ten, public_key, None); + + let two = encryption.plain_to_ec_point(U512::from(27000u32)); + let e_two = encryption.encrypt(two, public_key, None); + + println!("{:?}", encryption.ec_point_to_plain(Encryption::decrypt(e_ten + e_two, private_key))); + + /* + let twenty = encryption.plain_to_ec_point(U512::from(12u8)); + let ten = encryption.plain_to_ec_point(U512::from(10u8)); + let two = encryption.plain_to_ec_point(U512::from(2u8)); + println!("{:?}", twenty); + println!("{:?}", encryption.ec_point_to_plain(twenty)); + println!("{:?}", ten + two); + println!("{:?}", encryption.ec_point_to_plain(ten + two)); */ }