diff --git a/Cargo.toml b/Cargo.toml index 6cc6aa6..1cfb67a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,9 @@ members = [ "common/macros", "ffi/ffi_common", "ffi/ffi_macros", -"ffi/ffi_vcl", +"ffi/ffi_c/ffi_c_vcl", +"ffi/ffi_java/ffi_java_vcl", +"ffi/ffi_c/ffi_c_crypto", +"ffi/ffi_java/ffi_java_crypto", "protos", ] diff --git a/README.md b/README.md index cc23175..d93fbfe 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ cargo run 在本项目的根目录(即`WeDPR-Lab-Core`目录)中,运行如下命令。 ```bash -cargo doc +cargo doc --no-deps ``` 以上命令将根据代码中的注释,在`target/doc`子目录中,生成的SDK接口文档。 diff --git a/common/macros/Cargo.toml b/common/macros/Cargo.toml index 2b90b4f..31ab8f5 100644 --- a/common/macros/Cargo.toml +++ b/common/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wedpr_macros" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" diff --git a/common/utils/Cargo.toml b/common/utils/Cargo.toml index 73b4680..5c9f66a 100644 --- a/common/utils/Cargo.toml +++ b/common/utils/Cargo.toml @@ -1,10 +1,13 @@ [package] name = "wedpr_utils" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +base64 = "0.10.1" failure = "0.1" +hex = "0.3.0" +wedpr_macros = { path = "../macros/"} diff --git a/crypto/src/coder/base_x.rs b/common/utils/src/coder/base_x.rs similarity index 94% rename from crypto/src/coder/base_x.rs rename to common/utils/src/coder/base_x.rs index 9aea284..f553294 100644 --- a/crypto/src/coder/base_x.rs +++ b/common/utils/src/coder/base_x.rs @@ -4,8 +4,7 @@ extern crate base64; -use crate::coder::Coder; -use wedpr_utils::error::WedprError; +use crate::{coder::Coder, error::WedprError}; #[derive(Default, Debug, Clone)] pub struct WedprBase64 {} diff --git a/common/utils/src/coder/basic.rs b/common/utils/src/coder/basic.rs new file mode 100644 index 0000000..30df212 --- /dev/null +++ b/common/utils/src/coder/basic.rs @@ -0,0 +1,41 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! Basic encoding and decoding functions. + +extern crate hex; + +use crate::{coder::Coder, error::WedprError}; + +#[derive(Default, Debug, Clone)] +pub struct WedprHex {} + +/// Implements Hex as a Coder instance. +impl Coder for WedprHex { + fn encode>(&self, input: &T) -> String { + hex::encode(input) + } + + fn decode(&self, input: &str) -> Result, WedprError> { + match hex::decode(input) { + Ok(v) => return Ok(v), + Err(_) => { + wedpr_println!("hex decoding failed, input was: {}", input); + return Err(WedprError::DecodeError); + }, + }; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_hex() { + let hex = WedprHex::default(); + let str = "5c74d17c6a"; + let bytes = hex.decode(&str).unwrap(); + let recovered_str = hex.encode(&bytes); + assert_eq!(str, recovered_str); + } +} diff --git a/crypto/src/coder/mod.rs b/common/utils/src/coder/mod.rs similarity index 87% rename from crypto/src/coder/mod.rs rename to common/utils/src/coder/mod.rs index 176d4cd..aa00b7e 100644 --- a/crypto/src/coder/mod.rs +++ b/common/utils/src/coder/mod.rs @@ -3,8 +3,9 @@ //! Data encoding and decoding functions. pub mod base_x; +pub mod basic; -use wedpr_utils::error::WedprError; +use crate::error::WedprError; /// Trait of a replaceable coder algorithm. pub trait Coder { diff --git a/common/utils/src/lib.rs b/common/utils/src/lib.rs index f444778..55299d0 100644 --- a/common/utils/src/lib.rs +++ b/common/utils/src/lib.rs @@ -4,5 +4,8 @@ #[macro_use] extern crate failure; +#[macro_use] +extern crate wedpr_macros; +pub mod coder; pub mod error; diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 6bfaeae..2728fdd 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "wedpr_crypto" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -base64 = "0.10.1" bulletproofs = "1.0.4" curve25519-dalek = { version = "1", features = ["serde"] } +ecies = "0.1.4" lazy_static = "0.2" merlin = "1" rand = "0.6" -secp256k1 = { version = "0.17.2", features = ["recovery"] } +secp256k1 = { version = "0.19.0", features = ["recovery", "rand"] } sha3 = "0.8" wedpr_macros = { path = "../common/macros/"} wedpr_protos = { path = "../protos/" } diff --git a/crypto/src/constant.rs b/crypto/src/constant.rs index 221b7c5..a8d4d0e 100644 --- a/crypto/src/constant.rs +++ b/crypto/src/constant.rs @@ -9,11 +9,12 @@ use curve25519_dalek::{ }; extern crate secp256k1; use crate::{ - coder::base_x::WedprBase64, hash::keccak256::WedprKeccak256, + ecies::secp256k1::WedprSecp256k1Ecies, hash::keccak256::WedprKeccak256, signature::secp256k1::WedprSecp256k1Recover, }; use secp256k1::{All, Secp256k1, VerifyOnly}; use sha3::Sha3_512; +use wedpr_utils::coder::base_x::WedprBase64; lazy_static! { /// A base point used by various crypto algorithms. @@ -31,6 +32,7 @@ lazy_static! { /// Shared coder algorithm reference for quick implementation replacement. /// Other code should use this reference, and not directly use a specific implementation. + // You may change WedprBase64 to other coder implementation such as WedprHex. pub static ref CODER: WedprBase64 = WedprBase64::default(); /// Shared signature algorithm reference for quick implementation replacement. @@ -41,6 +43,10 @@ lazy_static! { /// Shared hash algorithm reference for quick implementation replacement. /// Other code should use this reference, and not directly use a specific implementation. pub static ref HASH: WedprKeccak256 = WedprKeccak256::default(); + + /// Shared ECIES algorithm reference for quick implementation replacement. + /// Other code should use this reference, and not directly use a specific implementation. + pub static ref ECIES: WedprSecp256k1Ecies = WedprSecp256k1Ecies::default(); } /// Serialized data size of a point. @@ -48,9 +54,13 @@ pub const RISTRETTO_POINT_SIZE_IN_BYTES: usize = 32; /// Constants only used by tests. pub mod tests { - // secp256k1 test key pair + // Test key pair for secp256k1 algorithms. pub const SECP256K1_TEST_SECRET_KEY: &str = "EMGwfgpqDQVUsVO7jxUniSNYxTPjGcbbf6eikaAIKog="; pub const SECP256K1_TEST_PUBLIC_KEY: &str = "ApBrmk0PHxPp4ElvnhlmwEiAklVdDbX+MicqML591eC2"; + + // Test string for a base64 encoded message. + pub const BASE64_ENCODED_TEST_MESSAGE: &str = + "g6sLGLyLvnkOSvBcQdKNSPx8m4XmAogueNMmE6V0Ico="; } diff --git a/crypto/src/ecies/mod.rs b/crypto/src/ecies/mod.rs new file mode 100644 index 0000000..6a42b9f --- /dev/null +++ b/crypto/src/ecies/mod.rs @@ -0,0 +1,27 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! ECIES (Elliptic Curve Integrated Encryption Scheme) functions. +//! ECIES is a public-key authenticated encryption scheme, which allows +//! using a public key to encrypt a message of any length and provide integrity +//! check. + +use wedpr_utils::error::WedprError; + +pub mod secp256k1; + +/// Trait of a replaceable ECIES algorithm. +pub trait Ecies { + /// Encrypts a message by ECIES with a public key. + fn encrypt>( + &self, + public_key: &T, + message: &T, + ) -> Result, WedprError>; + + /// Decrypts a ciphertext by ECIES with a private key. + fn decrypt>( + &self, + private_key: &T, + ciphertext: &T, + ) -> Result, WedprError>; +} diff --git a/crypto/src/ecies/secp256k1.rs b/crypto/src/ecies/secp256k1.rs new file mode 100644 index 0000000..9dbf455 --- /dev/null +++ b/crypto/src/ecies/secp256k1.rs @@ -0,0 +1,77 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! ECIES functions on Secp256k1 curve. + +extern crate ecies; + +use wedpr_utils::error::WedprError; + +use crate::ecies::Ecies; + +#[derive(Default, Debug, Clone)] +pub struct WedprSecp256k1Ecies {} + +/// Implements a ECIES instance on Secp256k1 curve. +impl Ecies for WedprSecp256k1Ecies { + fn encrypt>( + &self, + public_key: &T, + message: &T, + ) -> Result, WedprError> + { + match ecies::encrypt(public_key.as_ref(), message.as_ref()) { + Ok(v) => Ok(v.to_vec()), + Err(_) => { + wedpr_println!("secp256k1 ECIES encrypt failed"); + return Err(WedprError::FormatError); + }, + } + } + + fn decrypt>( + &self, + private_key: &T, + ciphertext: &T, + ) -> Result, WedprError> + { + match ecies::decrypt(private_key.as_ref(), ciphertext.as_ref()) { + Ok(v) => Ok(v.to_vec()), + Err(_) => { + wedpr_println!("secp256k1 ECIES decrypt failed"); + return Err(WedprError::FormatError); + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + constant::tests::{ + BASE64_ENCODED_TEST_MESSAGE, SECP256K1_TEST_PUBLIC_KEY, + SECP256K1_TEST_SECRET_KEY, + }, + utils::{bytes_to_string, string_to_bytes}, + }; + + #[test] + fn test_secp256k1_ecies() { + let secp256k1_ecies = WedprSecp256k1Ecies::default(); + + let encoded_msg = BASE64_ENCODED_TEST_MESSAGE; + let ciphertext = secp256k1_ecies + .encrypt( + &string_to_bytes(SECP256K1_TEST_PUBLIC_KEY).unwrap(), + &string_to_bytes(encoded_msg).unwrap(), + ) + .unwrap(); + let decrypted_msg = secp256k1_ecies + .decrypt( + &string_to_bytes(SECP256K1_TEST_SECRET_KEY).unwrap(), + &ciphertext, + ) + .unwrap(); + assert_eq!(bytes_to_string(&decrypted_msg), encoded_msg); + } +} diff --git a/crypto/src/hash/keccak256.rs b/crypto/src/hash/keccak256.rs index e39f2b3..d66954c 100644 --- a/crypto/src/hash/keccak256.rs +++ b/crypto/src/hash/keccak256.rs @@ -12,24 +12,29 @@ pub struct WedprKeccak256 {} /// Implements FISCO-BCOS-compatible Keccak256 as a Hash instance. impl Hash for WedprKeccak256 { - fn hash(&self, msg: &str) -> Vec { - let mut mes = Keccak256::default(); - mes.input(msg); - mes.result().to_vec() + fn hash>(&self, input: &T) -> Vec { + let mut hash_algorithm = Keccak256::default(); + hash_algorithm.input(input); + hash_algorithm.result().to_vec() } } #[cfg(test)] mod tests { use super::*; - use crate::utils::bytes_to_string; + use crate::{ + constant::tests::BASE64_ENCODED_TEST_MESSAGE, + utils::{bytes_to_string, string_to_bytes}, + }; #[test] fn test_keccak256() { let keccak256 = WedprKeccak256::default(); - let msg = "WeDPR"; - let computed_hash = bytes_to_string(&keccak256.hash(msg)); - let expected_hash = "g6sLGLyLvnkOSvBcQdKNSPx8m4XmAogueNMmE6V0Ico="; - assert_eq!(expected_hash, computed_hash); + let msg = BASE64_ENCODED_TEST_MESSAGE; + let expected_hash = "5S04Vv6HBCWG6xNARqwPb294Hz/3BlaFVwKvAJByd9Q="; + assert_eq!( + expected_hash, + bytes_to_string(&keccak256.hash(&string_to_bytes(&msg).unwrap())) + ); } } diff --git a/crypto/src/hash/mod.rs b/crypto/src/hash/mod.rs index 3760990..1f7c1f1 100644 --- a/crypto/src/hash/mod.rs +++ b/crypto/src/hash/mod.rs @@ -6,6 +6,7 @@ pub mod keccak256; /// Trait of a replaceable hash algorithm. pub trait Hash { - /// Generates a fixed length hash bytes vector from any string. - fn hash(&self, msg: &str) -> Vec; + /// Generates a fixed length hash bytes vector from a bytes array of any + /// length. + fn hash>(&self, input: &T) -> Vec; } diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index cd1fc47..3640eaf 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -7,8 +7,8 @@ extern crate wedpr_macros; #[macro_use] extern crate lazy_static; -pub mod coder; pub mod constant; +pub mod ecies; pub mod hash; pub mod signature; pub mod utils; diff --git a/crypto/src/signature/mod.rs b/crypto/src/signature/mod.rs index f08752f..170fc35 100644 --- a/crypto/src/signature/mod.rs +++ b/crypto/src/signature/mod.rs @@ -9,16 +9,21 @@ pub mod secp256k1; /// Trait of a replaceable signature algorithm. pub trait Signature { /// Signs a message hash with the private key. - fn sign( + fn sign>( &self, - private_key: &str, - msg_hash_str: &str, - ) -> Result; + private_key: &T, + msg_hash: &T, + ) -> Result, WedprError>; + /// Verifies a message hash with the public key. - fn verify( + fn verify>( &self, - public_key: &str, - msg_hash_str: &str, - signature: &str, + public_key: &T, + msg_hash: &T, + signature: &T, ) -> bool; + + /// Generates a new key pair for signature algorithm. + // TODO: Replace output list with a struct or protobuf. + fn generate_keypair(&self) -> (Vec, Vec); } diff --git a/crypto/src/signature/secp256k1.rs b/crypto/src/signature/secp256k1.rs index 1287906..b6e0010 100644 --- a/crypto/src/signature/secp256k1.rs +++ b/crypto/src/signature/secp256k1.rs @@ -12,7 +12,6 @@ use self::secp256k1::{ use crate::{ constant::{SECP256K1_ALL, SECP256K1_VERIFY}, signature::Signature, - utils::{bytes_to_string, string_to_bytes}, }; #[derive(Default, Debug, Clone)] @@ -27,54 +26,65 @@ pub const FISCO_BCOS_SIGNATURE_END_INDEX: usize = /// sig\[0..64\): signature for the message hash. /// sig\[64\]: recovery id. impl Signature for WedprSecp256k1Recover { - fn sign( + fn sign>( &self, - private_key: &str, - msg_hash_str: &str, - ) -> Result + private_key: &T, + msg_hash: &T, + ) -> Result, WedprError> { - let msg_hash = string_to_bytes(msg_hash_str)?; - let sk_str_bytes = string_to_bytes(private_key)?; - let secret_key = match SecretKey::from_slice(&sk_str_bytes) { + let secret_key = match SecretKey::from_slice(&private_key.as_ref()) { Ok(v) => v, Err(_) => { - wedpr_println!("Getting private key failed"); + wedpr_println!("Parsing private key failed"); return Err(WedprError::FormatError); }, }; - let message_send = Message::from_slice(&msg_hash).expect("32 bytes"); - let sig = SECP256K1_ALL.sign_recoverable(&message_send, &secret_key); - let (recid, signature_bytes) = &sig.serialize_compact(); - let mut vec_sig = signature_bytes.to_vec(); - vec_sig.push(recid.to_i32() as u8); - Ok(bytes_to_string(&vec_sig)) + // Message hash length for Secp256k1 signature should be 32 bytes. + let msg_hash_obj = match Message::from_slice(&msg_hash.as_ref()) { + Ok(v) => v, + Err(_) => { + wedpr_println!("Parsing message hash failed"); + return Err(WedprError::FormatError); + }, + }; + let signature_obj = + SECP256K1_ALL.sign_recoverable(&msg_hash_obj, &secret_key); + let (recid, signature_bytes) = &signature_obj.serialize_compact(); + // Append recovery id to the end of signature bytes. + let mut signature_output = signature_bytes.to_vec(); + signature_output.push(recid.to_i32() as u8); + Ok(signature_output) } - fn verify( + fn verify>( &self, - public_key: &str, - msg_hash_str: &str, - signature: &str, + public_key: &T, + msg_hash: &T, + signature: &T, ) -> bool { - let msg_hash = string_to_bytes!(msg_hash_str); - - let message_receive = Message::from_slice(&msg_hash).expect("32 bytes"); - let pk_str_bytes = string_to_bytes!(&public_key); - let pub_str_get = match PublicKey::from_slice(&pk_str_bytes) { + // Message hash length for Secp256k1 signature should be 32 bytes. + let msg_hash_obj = match Message::from_slice(&msg_hash.as_ref()) { Ok(v) => v, Err(_) => { - wedpr_println!("Parsing public key to failed"); + wedpr_println!("Parsing message hash failed"); return false; }, }; - let sig_result_hex = string_to_bytes!(signature); - if sig_result_hex.len() != FISCO_BCOS_SIGNATURE_DATA_LENGTH { - wedpr_println!("Sigature length is not 65"); + let inputted_pub_key = match PublicKey::from_slice(&public_key.as_ref()) + { + Ok(v) => v, + Err(_) => { + wedpr_println!("Parsing public key failed"); + return false; + }, + }; + if signature.as_ref().len() != FISCO_BCOS_SIGNATURE_DATA_LENGTH { + wedpr_println!("Signature length is not 65"); return false; }; let recid = match RecoveryId::from_i32( - sig_result_hex[FISCO_BCOS_SIGNATURE_END_INDEX] as i32, + signature.as_ref()[FISCO_BCOS_SIGNATURE_END_INDEX] as i32, ) { Ok(v) => v, Err(_) => { @@ -85,7 +95,8 @@ impl Signature for WedprSecp256k1Recover { // The last byte is recovery id, we only need to get the first 64 bytes // for signature data. - let signature_byte = &sig_result_hex[0..FISCO_BCOS_SIGNATURE_END_INDEX]; + let signature_byte = + &signature.as_ref()[0..FISCO_BCOS_SIGNATURE_END_INDEX]; let get_sign_final = match RecoverableSignature::from_compact(signature_byte, recid) { @@ -95,20 +106,36 @@ impl Signature for WedprSecp256k1Recover { return false; }, }; - let pk_recover_get = - match SECP256K1_VERIFY.recover(&message_receive, &get_sign_final) { + let recovered_public_key = + match SECP256K1_VERIFY.recover(&msg_hash_obj, &get_sign_final) { Ok(v) => v, Err(_) => { wedpr_println!("Signature recover failed"); return false; }, }; - if pub_str_get != pk_recover_get { - wedpr_println!("Signature recover failed"); + if inputted_pub_key != recovered_public_key { + wedpr_println!("Matching signature public key failed"); return false; } return true; } + + fn generate_keypair(&self) -> (Vec, Vec) { + let mut rng = rand::thread_rng(); + loop { + // "rand" feature of secp256k1 need to be enabled for this. + let (secret_key, public_key) = + SECP256K1_ALL.generate_keypair(&mut rng); + // Drop weak secret key. + if secret_key[0] > 15 { + return ( + public_key.serialize_uncompressed().to_vec(), + secret_key.as_ref().to_vec(), + ); + } + } + } } #[cfg(test)] @@ -120,7 +147,7 @@ mod tests { HASH, }, hash::Hash, - utils::bytes_to_string, + utils::string_to_bytes, }; #[test] @@ -129,17 +156,20 @@ mod tests { // The message hash (NOT the original message) is required for // generating a valid signature. - let msg = "WeDPR"; - let msg_hash_str = bytes_to_string(&HASH.hash(msg)); + let msg = "WeDPR".as_bytes(); + let msg_hash = HASH.hash(msg); let signature = secp256k1_recover - .sign(SECP256K1_TEST_SECRET_KEY, &msg_hash_str) + .sign( + &string_to_bytes(SECP256K1_TEST_SECRET_KEY).unwrap(), + &msg_hash, + ) .unwrap(); assert_eq!( true, secp256k1_recover.verify( - SECP256K1_TEST_PUBLIC_KEY, - &msg_hash_str, + &string_to_bytes(SECP256K1_TEST_PUBLIC_KEY).unwrap(), + &msg_hash, &signature ) ); diff --git a/crypto/src/utils.rs b/crypto/src/utils.rs index 792b3ad..f5f36be 100644 --- a/crypto/src/utils.rs +++ b/crypto/src/utils.rs @@ -1,21 +1,18 @@ // Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. //! Common utility functions. -use crate::constant::RISTRETTO_POINT_SIZE_IN_BYTES; +use crate::{ + constant::{CODER, HASH, RISTRETTO_POINT_SIZE_IN_BYTES}, + hash::Hash, +}; use bulletproofs::RangeProof; use curve25519_dalek::{ ristretto::{CompressedRistretto, RistrettoPoint}, scalar::Scalar, traits::MultiscalarMul, }; -use wedpr_utils::error::WedprError; - -use crate::{ - coder::Coder, - constant::{CODER, HASH}, - hash::Hash, -}; use std::convert::TryInto; +use wedpr_utils::{coder::Coder, error::WedprError}; /// Converts bytes to an encoded string. pub fn bytes_to_string>(input: &T) -> String { @@ -27,6 +24,27 @@ pub fn string_to_bytes(input: &str) -> Result, WedprError> { CODER.decode(input) } +/// Converts bytes to a UTF8 string. +pub fn bytes_to_utf8>( + input: &T, +) -> Result { + match String::from_utf8(input.as_ref().to_vec()) { + Ok(v) => Ok(v), + Err(_) => { + wedpr_println!( + "UTF8 encoding failed, input was: {}", + bytes_to_string(input) + ); + return Err(WedprError::DecodeError); + }, + } +} + +/// Converts a UTF8 string to a bytes vector. +pub fn utf8_to_bytes(input: &str) -> Vec { + String::from(input).into_bytes() +} + /// Converts Scalar to an encoded string. pub fn scalar_to_string(number: &Scalar) -> String { bytes_to_string(&number.to_bytes()) @@ -82,7 +100,7 @@ pub fn rangeproof_to_string(proof: &RangeProof) -> String { /// Scalar. pub fn hash_to_scalar(value: &str) -> Scalar { let mut array = [0; 32]; - array.clone_from_slice(&HASH.hash(value)); + array.clone_from_slice(&HASH.hash(value.as_bytes())); Scalar::from_bytes_mod_order(array) } @@ -142,6 +160,14 @@ mod tests { assert_eq!(str, recovered_str); } + #[test] + pub fn test_utf8_conversion() { + let str = "test"; + let bytes = utf8_to_bytes(&str); + let recovered_str = bytes_to_utf8(&bytes).unwrap(); + assert_eq!(str, recovered_str); + } + #[test] pub fn test_point_conversion() { let point = RistrettoPoint::default(); diff --git a/ffi/ffi_c/ffi_c_common/Cargo.toml b/ffi/ffi_c/ffi_c_common/Cargo.toml new file mode 100644 index 0000000..e84e002 --- /dev/null +++ b/ffi/ffi_c/ffi_c_common/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "wedpr_ffi_c_common" +version = "1.1.0" +authors = ["WeDPR "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2.60" + +# This is required to generate C/C++ header files. +[build-dependencies] +cbindgen = "0.9.0" \ No newline at end of file diff --git a/ffi/ffi_c/ffi_c_common/src/lib.rs b/ffi/ffi_c/ffi_c_common/src/lib.rs new file mode 100644 index 0000000..c8123ae --- /dev/null +++ b/ffi/ffi_c/ffi_c_common/src/lib.rs @@ -0,0 +1,70 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! Library of shared utilities for FFI targeting C/C++ +//! compatible architectures (including iOS). + +/// Patch code to fix the missing 'backtrace_*' related functions errors during +/// cross compilation. Do not modify them if you are not sure. +#[allow(non_camel_case_types)] +pub mod backtrace_patch { + extern crate libc; + + use self::libc::uintptr_t; + use std::os::raw::{c_char, c_int, c_void}; + + pub type backtrace_syminfo_callback = extern "C" fn( + data: *mut c_void, + pc: uintptr_t, + symname: *const c_char, + symval: uintptr_t, + symsize: uintptr_t, + ); + + pub type backtrace_full_callback = extern "C" fn( + data: *mut c_void, + pc: uintptr_t, + filename: *const c_char, + lineno: c_int, + function: *const c_char, + ) -> c_int; + + pub type backtrace_error_callback = + extern "C" fn(data: *mut c_void, msg: *const c_char, errnum: c_int); + + pub enum backtrace_state {} + + #[no_mangle] + pub extern "C" fn __rbt_backtrace_create_state( + _filename: *const c_char, + _threaded: c_int, + _error: backtrace_error_callback, + _data: *mut c_void, + ) -> *mut backtrace_state + { + 0 as *mut _ + } + + #[no_mangle] + pub extern "C" fn __rbt_backtrace_syminfo( + _state: *mut backtrace_state, + _addr: uintptr_t, + _cb: backtrace_syminfo_callback, + _error: backtrace_error_callback, + _data: *mut c_void, + ) -> c_int + { + 0 + } + + #[no_mangle] + pub extern "C" fn __rbt_backtrace_pcinfo( + _state: *mut backtrace_state, + _addr: uintptr_t, + _cb: backtrace_full_callback, + _error: backtrace_error_callback, + _data: *mut c_void, + ) -> c_int + { + 0 + } +} diff --git a/ffi/ffi_c/ffi_c_crypto/Cargo.toml b/ffi/ffi_c/ffi_c_crypto/Cargo.toml new file mode 100644 index 0000000..f63b5e1 --- /dev/null +++ b/ffi/ffi_c/ffi_c_crypto/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "wedpr_ffi_c_crypto" +version = "1.1.0" +authors = ["WeDPR "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "ffi_c_crypto" +crate-type = ["cdylib", "staticlib"] + +[dependencies] +libc = "0.2.60" +wedpr_crypto = { path = "../../../crypto/" } +wedpr_ffi_c_common = { path = "../ffi_c_common/" } +wedpr_ffi_common = { path = "../../ffi_common/" } +wedpr_ffi_macros = { path = "../../../ffi/ffi_macros/" } +wedpr_macros = { path = "../../../common/macros/" } +wedpr_utils = { path = "../../../common/utils" } +wedpr_protos = { path = "../../../protos/" } +protobuf = "2.10.1" + +# This is required to generate C/C++ header files. +[build-dependencies] +cbindgen = "0.9.0" diff --git a/ffi/ffi_c/ffi_c_crypto/README.md b/ffi/ffi_c/ffi_c_crypto/README.md new file mode 100644 index 0000000..cdb640b --- /dev/null +++ b/ffi/ffi_c/ffi_c_crypto/README.md @@ -0,0 +1,33 @@ +# ffi ios + +before compile + +- install openssl +- install xcode +- install ios toolchain + +```bash +rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios +``` + +open cross compile with openssl + +```bash +# for example, in your environment +export PATH="/usr/local/opt/openssl/bin:$PATH" +export LDFLAGS="-L/usr/local/opt/openssl/lib" +export CPPFLAGS="-I/usr/local/opt/openssl/include" +export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" +export PKG_CONFIG_ALLOW_CROSS=1 +``` + +generate .h + +```bash +cbindgen src/lib.rs -l c > wedpr_ios.h +``` + +```bash +# for aarch64 +cargo build --target=aarch64-apple-ios --release +``` \ No newline at end of file diff --git a/ffi/ffi_c/ffi_c_crypto/src/lib.rs b/ffi/ffi_c/ffi_c_crypto/src/lib.rs new file mode 100644 index 0000000..a6ae8d5 --- /dev/null +++ b/ffi/ffi_c/ffi_c_crypto/src/lib.rs @@ -0,0 +1,171 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! Library of macros and functions for FFI of crypto, targeting C/C++ +//! compatible architectures (including iOS). + +#[allow(unused_imports)] +#[macro_use] +extern crate wedpr_ffi_macros; +#[macro_use] +extern crate wedpr_macros; + +use wedpr_crypto::{ + constant::{ECIES, HASH, SIGNATURE}, + signature::Signature, +}; + +use protobuf::{self, Message}; + +use wedpr_ffi_common::utils::{c_char_pointer_to_string, FAILURE, SUCCESS}; + +use libc::c_char; +use std::{ffi::CString, panic, ptr}; +use wedpr_crypto::{ + ecies::Ecies, + hash::Hash, + utils::{bytes_to_string, string_to_bytes}, +}; +use wedpr_protos::generated::common; + +// C/C++ FFI: C-style interfaces will be generated. + +#[no_mangle] +/// C interface for 'wedpr_secp256k1_ecies_encrypt'. +// TODO: Add wedpr_secp256k1_ecies_encrypt_utf8 to allow non-encoded UTF8 input. +pub extern "C" fn wedpr_secp256k1_ecies_encrypt( + encoded_public_key: *mut c_char, + encoded_plaintext: *mut c_char, +) -> *mut c_char +{ + let result = panic::catch_unwind(|| { + let public_key = c_safe_c_char_pointer_to_bytes!(encoded_public_key); + let encoded_message = + c_safe_c_char_pointer_to_bytes!(encoded_plaintext); + + let encrypt_data = match ECIES.encrypt(&public_key, &encoded_message) { + Ok(v) => v, + Err(_) => { + wedpr_println!( + "ECIES encrypt failed, encoded_message={}, public_key={}", + bytes_to_string(&encoded_message), + bytes_to_string(&public_key) + ); + return ptr::null_mut(); + }, + }; + c_safe_bytes_to_c_char_pointer!(&encrypt_data) + }); + c_safe_return!(result) +} + +#[no_mangle] +/// C interface for 'wedpr_secp256k1_ecies_decrypt'. +pub extern "C" fn wedpr_secp256k1_ecies_decrypt( + encoded_private_key: *mut c_char, + encoded_ciphertext: *mut c_char, +) -> *mut c_char +{ + let result = panic::catch_unwind(|| { + let private_key = c_safe_c_char_pointer_to_bytes!(encoded_private_key); + let ciphertext = c_safe_c_char_pointer_to_bytes!(encoded_ciphertext); + + let decrypted_data = match ECIES.decrypt(&private_key, &ciphertext) { + Ok(v) => v, + Err(_) => { + wedpr_println!( + "ECIES decrypt failed, ciphertext={}", + bytes_to_string(&ciphertext) + ); + return ptr::null_mut(); + }, + }; + c_safe_bytes_to_c_char_pointer!(&decrypted_data) + }); + c_safe_return!(result) +} + +#[no_mangle] +/// C interface for 'wedpr_secp256k1_gen_key_pair'. +pub extern "C" fn wedpr_secp256k1_gen_key_pair() -> *mut c_char { + let result = panic::catch_unwind(|| { + let (pk, sk) = SIGNATURE.generate_keypair(); + let mut keypair = common::Keypair::new(); + keypair.set_private_key(bytes_to_string(&sk)); + keypair.set_public_key(bytes_to_string(&pk)); + let c_keypair = bytes_to_string( + &keypair + .write_to_bytes() + .expect("proto to bytes should not fail"), + ); + c_safe_string_to_c_char_pointer!(c_keypair) + }); + c_safe_return!(result) +} + +#[no_mangle] +/// C interface for 'wedpr_secp256k1_sign'. +pub extern "C" fn wedpr_secp256k1_sign( + encoded_private_key: *mut c_char, + encoded_message_hash: *mut c_char, +) -> *mut c_char +{ + let result = panic::catch_unwind(|| { + let private_key = c_safe_c_char_pointer_to_bytes!(encoded_private_key); + let message_hash = + c_safe_c_char_pointer_to_bytes!(encoded_message_hash); + + let signature = match SIGNATURE.sign(&private_key, &message_hash) { + Ok(v) => v, + Err(_) => { + return ptr::null_mut(); + }, + }; + c_safe_bytes_to_c_char_pointer!(&signature) + }); + c_safe_return!(result) +} + +#[no_mangle] +/// C interface for 'wedpr_secp256k1_verify'. +pub extern "C" fn wedpr_secp256k1_verify( + encoded_public_key: *mut c_char, + encoded_message_hash: *mut c_char, + encoded_signature: *mut c_char, +) -> i8 +{ + let result = panic::catch_unwind(|| { + let public_key = c_safe_c_char_pointer_to_bytes_with_error_value!( + encoded_public_key, + FAILURE + ); + let message_hash = c_safe_c_char_pointer_to_bytes_with_error_value!( + encoded_message_hash, + FAILURE + ); + let signature = c_safe_c_char_pointer_to_bytes_with_error_value!( + encoded_signature, + FAILURE + ); + + match SIGNATURE.verify(&public_key, &message_hash, &signature) { + true => SUCCESS, + false => FAILURE, + } + }); + c_safe_return_with_error_value!(result, FAILURE) +} + +#[no_mangle] +/// C interface for 'wedpr_keccak256_hash'. +// TODO: Add wedpr_keccak256_hash_utf8 to allow non-encoded UTF8 input. +pub extern "C" fn wedpr_keccak256_hash( + encoded_message: *mut c_char, +) -> *mut c_char { + let result = panic::catch_unwind(|| { + let message = c_safe_c_char_pointer_to_bytes!(encoded_message); + + let msg_hash = bytes_to_string(&HASH.hash(&message)); + c_safe_string_to_c_char_pointer!(msg_hash) + }); + c_safe_return!(result) +} diff --git a/ffi/ffi_c/ffi_c_vcl/Cargo.toml b/ffi/ffi_c/ffi_c_vcl/Cargo.toml new file mode 100644 index 0000000..e943859 --- /dev/null +++ b/ffi/ffi_c/ffi_c_vcl/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "wedpr_ffi_c_vcl" +version = "1.1.0" +authors = ["WeDPR "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "ffi_c_vcl" +crate-type = ["cdylib", "staticlib"] + +[dependencies] +libc = "0.2.60" +protobuf = "2.10.1" +verifiable_confidential_ledger = { path = "../../../solution/verifiable_confidential_ledger" } +wedpr_crypto = { path = "../../../crypto/" } +wedpr_ffi_c_common = { path = "../ffi_c_common/" } +wedpr_ffi_common = { path = "../../ffi_common/" } +wedpr_ffi_macros = { path = "../../../ffi/ffi_macros/" } +wedpr_protos = { path = "../../../protos/" } +wedpr_utils = { path = "../../../common/utils" } +wedpr_macros = { path = "../../../common/macros/" } + +# This is required to generate C/C++ header files. +[build-dependencies] +cbindgen = "0.9.0" diff --git a/ffi/ffi_c/ffi_c_vcl/src/lib.rs b/ffi/ffi_c/ffi_c_vcl/src/lib.rs new file mode 100644 index 0000000..49f4b85 --- /dev/null +++ b/ffi/ffi_c/ffi_c_vcl/src/lib.rs @@ -0,0 +1,257 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! Library of macros and functions for FFI of VCL solution, targeting C/C++ +//! compatible architectures (including iOS). + +#[allow(unused_imports)] +#[macro_use] +extern crate wedpr_ffi_macros; +#[macro_use] +extern crate wedpr_macros; + +use protobuf::{self, Message}; +use verifiable_confidential_ledger; +use wedpr_crypto::utils::{bytes_to_string, string_to_bytes}; +use wedpr_ffi_common::utils::{c_char_pointer_to_string, FAILURE, SUCCESS}; + +use wedpr_protos::generated::{ + vcl::{EncodedConfidentialCredit, EncodedOwnerSecret, VclResult}, + zkp::BalanceProof, +}; + +use libc::{c_char, c_ulong}; +use std::{ffi::CString, panic, ptr}; + +// C/C++ FFI: C-style interfaces will be generated. + +// Local macros and functions section. + +macro_rules! decode_credit { + ($encoded_credit:expr) => { + match verifiable_confidential_ledger::vcl::ConfidentialCredit::decode( + &$encoded_credit, + ) { + Ok(v) => v, + Err(_) => return FAILURE, + } + }; +} + +macro_rules! decode_secret { + ($encoded_secret:expr) => { + match verifiable_confidential_ledger::vcl::OwnerSecret::decode( + &$encoded_secret, + ) { + Ok(v) => v, + Err(_) => return ptr::null_mut(), + } + }; +} + +/// C interface for 'wedpr_vcl_make_credit'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_make_credit(value: c_ulong) -> *mut c_char { + let result = panic::catch_unwind(|| { + let (credit, secret) = + verifiable_confidential_ledger::vcl::make_credit(value as u64); + + let mut vcl_result = VclResult::new(); + vcl_result.set_credit(encodable_struct_to_string!(credit)); + vcl_result.set_secret(encodable_struct_to_string!(secret)); + c_safe_proto_to_c_char_pointer!(vcl_result) + }); + c_safe_return!(result) +} + +/// C interface for 'wedpr_vcl_prove_sum_balance'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_prove_sum_balance( + c1_secret_cstring: *mut c_char, + c2_secret_cstring: *mut c_char, + c3_secret_cstring: *mut c_char, +) -> *mut c_char +{ + let result = panic::catch_unwind(|| { + let c1_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c1_secret_cstring, + EncodedOwnerSecret + )); + let c2_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c2_secret_cstring, + EncodedOwnerSecret + )); + let c3_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c3_secret_cstring, + EncodedOwnerSecret + )); + + let proof = verifiable_confidential_ledger::vcl::prove_sum_balance( + &c1_secret, &c2_secret, &c3_secret, + ); + c_safe_proto_to_c_char_pointer!(proof) + }); + c_safe_return!(result) +} + +/// C interface for 'wedpr_vcl_verify_sum_balance'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_verify_sum_balance( + c1_credit_cstring: *mut c_char, + c2_credit_cstring: *mut c_char, + c3_credit_cstring: *mut c_char, + proof_cstring: *mut c_char, +) -> i8 +{ + let result = panic::catch_unwind(|| { + let proof = c_safe_c_char_pointer_to_proto_with_error_value!( + proof_cstring, + BalanceProof, + FAILURE + ); + let c1_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c1_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + let c2_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c2_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + let c3_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c3_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + + match verifiable_confidential_ledger::vcl::verify_sum_balance( + &c1_credit, &c2_credit, &c3_credit, &proof, + ) { + true => SUCCESS, + false => FAILURE, + } + }); + c_safe_return_with_error_value!(result, FAILURE) +} + +/// C interface for 'wedpr_vcl_prove_product_balance'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_prove_product_balance( + c1_secret_cstring: *mut c_char, + c2_secret_cstring: *mut c_char, + c3_secret_cstring: *mut c_char, +) -> *mut c_char +{ + let result = panic::catch_unwind(|| { + let c1_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c1_secret_cstring, + EncodedOwnerSecret + )); + let c2_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c2_secret_cstring, + EncodedOwnerSecret + )); + let c3_secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + c3_secret_cstring, + EncodedOwnerSecret + )); + + let proof = verifiable_confidential_ledger::vcl::prove_product_balance( + &c1_secret, &c2_secret, &c3_secret, + ); + c_safe_proto_to_c_char_pointer!(proof) + }); + c_safe_return!(result) +} + +/// C interface for 'wedpr_vcl_verify_product_balance'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_verify_product_balance( + c1_credit_cstring: *mut c_char, + c2_credit_cstring: *mut c_char, + c3_credit_cstring: *mut c_char, + proof_cstring: *mut c_char, +) -> i8 +{ + let result = panic::catch_unwind(|| { + let proof = c_safe_c_char_pointer_to_proto_with_error_value!( + proof_cstring, + BalanceProof, + FAILURE + ); + let c1_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c1_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + let c2_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c2_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + let c3_credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + c3_credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + + match verifiable_confidential_ledger::vcl::verify_product_balance( + &c1_credit, &c2_credit, &c3_credit, &proof, + ) { + true => SUCCESS, + false => FAILURE, + } + }); + c_safe_return_with_error_value!(result, FAILURE) +} + +/// C interface for 'wedpr_vcl_prove_range'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_prove_range( + secret_cstring: *mut c_char, +) -> *mut c_char { + let result = panic::catch_unwind(|| { + let secret = decode_secret!(c_safe_c_char_pointer_to_proto!( + secret_cstring, + EncodedOwnerSecret + )); + + let proof = verifiable_confidential_ledger::vcl::prove_range(&secret); + c_safe_string_to_c_char_pointer!(proof) + }); + c_safe_return!(result) +} + +/// C interface for 'wedpr_vcl_verify_range'. +#[no_mangle] +pub extern "C" fn wedpr_vcl_verify_range( + credit_cstring: *mut c_char, + proof_cstring: *mut c_char, +) -> i8 +{ + let result = panic::catch_unwind(|| { + let proof = c_safe_c_char_pointer_to_string_with_error_value!( + proof_cstring, + FAILURE + ); + let credit = + decode_credit!(c_safe_c_char_pointer_to_proto_with_error_value!( + credit_cstring, + EncodedConfidentialCredit, + FAILURE + )); + + match verifiable_confidential_ledger::vcl::verify_range(&credit, &proof) + { + true => SUCCESS, + false => FAILURE, + } + }); + c_safe_return_with_error_value!(result, FAILURE) +} diff --git a/ffi/ffi_common/Cargo.toml b/ffi/ffi_common/Cargo.toml index 5fba932..f2435fc 100644 --- a/ffi/ffi_common/Cargo.toml +++ b/ffi/ffi_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wedpr_ffi_common" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" @@ -8,6 +8,7 @@ edition = "2018" [dependencies] jni = "0.13.0" +libc = "0.2.60" wedpr_crypto = { path = "../../crypto" } wedpr_ffi_macros = { path = "../ffi_macros/" } wedpr_macros = { path = "../../common/macros/" } diff --git a/ffi/ffi_common/src/utils.rs b/ffi/ffi_common/src/utils.rs index ed98d68..6581540 100644 --- a/ffi/ffi_common/src/utils.rs +++ b/ffi/ffi_common/src/utils.rs @@ -11,6 +11,10 @@ use jni::{ JNIEnv, }; +// From Rust to C/C++. +use libc::c_char; +use std::ffi::CStr; + use wedpr_crypto::utils; use wedpr_utils::error::WedprError; @@ -100,3 +104,21 @@ pub fn java_jbytes_to_bytes( Err(_) => return Err(WedprError::FormatError), } } + +// C/C++ FFI functions. + +/// Default success status return code for C/C++ functions. +pub const SUCCESS: i8 = 0; +/// Default failure status return code for C/C++ functions. +pub const FAILURE: i8 = -1; + +/// Converts C char pointer to Rust string. +pub fn c_char_pointer_to_string( + param: *const c_char, +) -> Result { + let cstr_param = unsafe { CStr::from_ptr(param) }; + match cstr_param.to_str() { + Ok(v) => Ok(v.to_owned()), + Err(_) => Err(WedprError::FormatError), + } +} diff --git a/ffi/ffi_java/ffi_java_crypto/Cargo.toml b/ffi/ffi_java/ffi_java_crypto/Cargo.toml new file mode 100644 index 0000000..a0743d5 --- /dev/null +++ b/ffi/ffi_java/ffi_java_crypto/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "wedpr_ffi_java_crypto" +version = "1.1.0" +authors = ["WeDPR "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "ffi_java_crypto" +crate-type = ["cdylib", "staticlib"] + +[dependencies] +jni = "0.13.0" +wedpr_crypto = { path = "../../../crypto/" } +wedpr_ffi_common = { path = "../../ffi_common/" } +wedpr_ffi_macros = { path = "../../../ffi/ffi_macros/" } +wedpr_macros = { path = "../../../common/macros/" } +wedpr_utils = { path = "../../../common/utils" } + +[target.'cfg(target_os = "android")'.dependencies] +jni = { version = "0.13.1", default-features = false } +openssl-sys = { version = "0.9.55", features = ["vendored"] } diff --git a/ffi/ffi_java/ffi_java_crypto/README.md b/ffi/ffi_java/ffi_java_crypto/README.md new file mode 100644 index 0000000..0257b57 --- /dev/null +++ b/ffi/ffi_java/ffi_java_crypto/README.md @@ -0,0 +1,104 @@ +# how to cross compile with openssl + +for android, my ndk version is 23 + +zshrc + +```bash +# for android, you need download openssl in local path +export LDFLAGS="-L~/Downloads/openssl.1.0.2k_for_android_ios/android/openssl-arm64-v8a/lib" +export CPPFLAGS="-I~/Downloads/openssl.1.0.2k_for_android_ios/android/openssl-arm64-v8a/include" +export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" +export PKG_CONFIG_ALLOW_CROSS=1 +export OPENSSL_STATIC=1 +``` + +toolchain + +```bash + +rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android +``` + +explain + +```bash +rustup target add armv7-linux-androideabi # for arm +rustup target add i686-linux-android # for x86 +rustup target add aarch64-linux-android # for arm64 +rustup target add x86_64-linux-android # for x86_64 +rustup target add x86_64-unknown-linux-gnu # for linux-x86-64 +rustup target add x86_64-apple-darwin # for darwin (macOS) +rustup target add x86_64-pc-windows-gnu # for win32-x86-64-gnu +rustup target add x86_64-pc-windows-msvc # for win32-x86-64-msvc +``` + +rust link args + +```bash +# some old android version need this option +export RUSTFLAGS="-C link-arg=-Wl,--hash-style=both" +``` + +```bash +cargo ndk --target i686-linux-android --android-platform 21 -- build --release +# aarch64-linux-android +# armv7-linux-androideabi +# i686-linux-android +# target 21 is android 5.0, work fine in old oppo, 26 is too high run in old version +``` + +```bash +export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk/21.3.6528147 + +/Users/asher/Library/Android/sdk/ndk/21.3.6528147cd +``` + +```bash +``` + +```java +public class NativeInterface { + public static native CryptoResult secp256k1EciesEncrypt(String pubKey, String plaintext); + + public static native CryptoResult secp256k1EciesDecrypt(String priKey, String ciphertext); + + public static native CryptoResult secp256k1GenKeyPair(); + + public static native CryptoResult keccak256Hash(String message); + + public static native CryptoResult secp256k1Sign(String priKey, String messageHash); + + public static native CryptoResult secp256k1Verify(String pubKey, String message, String signature); +} +``` + +```java +package com.webank.wedpr.crypto; +import com.webank.wedpr.common.WedprException; +import com.webank.wedpr.common.WedprResult; + +public class CryptoResult extends WedprResult { + public String signature; + public String publicKey; + public String privateKey; + public String hash; + public boolean booleanResult; + public String encryptedData; + public String decryptedData; +} +``` + +```java +package com.webank.wedpr.common; + +/** Base result class used by WeDPR Java SDK. */ +public class WedprResult { + public String wedprErrorMessage; + + /** Checks whether any error occurred. */ + public boolean hasError() { + return wedprErrorMessage != null; + } +} +``` \ No newline at end of file diff --git a/ffi/ffi_java/ffi_java_crypto/src/lib.rs b/ffi/ffi_java/ffi_java_crypto/src/lib.rs new file mode 100644 index 0000000..90ddb7f --- /dev/null +++ b/ffi/ffi_java/ffi_java_crypto/src/lib.rs @@ -0,0 +1,243 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +//! Library of macros and functions for FFI of crypto, targeting Java-compatible +//! architectures (including Android). + +extern crate jni; +#[allow(unused_imports)] +#[macro_use] +extern crate wedpr_ffi_macros; +#[allow(unused_imports)] +#[macro_use] +extern crate wedpr_macros; + +use wedpr_crypto::{ + constant::{ECIES, HASH, SIGNATURE}, + signature::Signature, +}; + +use wedpr_ffi_common::utils::{ + java_jstring_to_bytes, java_new_jobject, + java_set_error_field_and_extract_jobject, +}; + +use jni::{ + objects::{JClass, JObject, JString, JValue}, + sys::jobject, + JNIEnv, +}; + +use wedpr_crypto::{ecies::Ecies, hash::Hash, utils::bytes_to_string}; + +// Java FFI: Java interfaces will be generated under +// package name 'com.webank.wedpr.crypto'. + +// Result class name is 'com.webank.wedpr.crypto.CryptoResult'. +const RESULT_CRYPTO_CLASS_NAME: &str = "com/webank/wedpr/crypto/CryptoResult"; + +fn get_result_jobject<'a>(_env: &'a JNIEnv) -> JObject<'a> { + java_new_jobject(_env, RESULT_CRYPTO_CLASS_NAME) +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->secp256k1EciesEncrypt'. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_secp256k1EciesEncrypt( + _env: JNIEnv, + _class: JClass, + public_key_jstring: JString, + message_hash_jstring: JString, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let public_key = + java_safe_jstring_to_bytes!(_env, result_jobject, public_key_jstring); + let encoded_message = + java_safe_jstring_to_bytes!(_env, result_jobject, message_hash_jstring); + + let encrypted_data = match ECIES.encrypt(&public_key, &encoded_message) { + Ok(v) => v, + Err(_) => { + return java_set_error_field_and_extract_jobject( + &_env, + &result_jobject, + &format!( + "ECIES encrypt failed, encoded_message={}, public_key={}", + bytes_to_string(&encoded_message), + bytes_to_string(&public_key) + ), + ) + }, + }; + + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&encrypted_data), + "encryptedData" + ); + result_jobject.into_inner() +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->secp256k1EciesDecrypt'. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_secp256k1EciesDecrypt( + _env: JNIEnv, + _class: JClass, + private_key_jstring: JString, + ciphertext_jstring: JString, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let private_key = + java_safe_jstring_to_bytes!(_env, result_jobject, private_key_jstring); + let ciphertext = + java_safe_jstring_to_bytes!(_env, result_jobject, ciphertext_jstring); + + let decrypted_data = match ECIES.decrypt(&private_key, &ciphertext) { + Ok(v) => v, + Err(_) => { + return java_set_error_field_and_extract_jobject( + &_env, + &result_jobject, + &format!( + "ECIES decrypt failed, ciphertext={}", + bytes_to_string(&ciphertext) + ), + ) + }, + }; + + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&decrypted_data), + "decryptedData" + ); + result_jobject.into_inner() +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->secp256k1GenKeyPair'. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_secp256k1GenKeyPair( + _env: JNIEnv, + _class: JClass, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let (pk, sk) = SIGNATURE.generate_keypair(); + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&pk), + "publicKey" + ); + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&sk), + "privateKey" + ); + result_jobject.into_inner() +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->secp256k1Sign'. +// TODO: Add secp256k1SignUtf8 to allow non-encoded UTF8 input. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_secp256k1Sign( + _env: JNIEnv, + _class: JClass, + private_key_jstring: JString, + msg_hash_jstring: JString, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let private_key = + java_safe_jstring_to_bytes!(_env, result_jobject, private_key_jstring); + let msg_hash = + java_safe_jstring_to_bytes!(_env, result_jobject, msg_hash_jstring); + + let signature = match SIGNATURE.sign(&private_key, &msg_hash) { + Ok(v) => v, + Err(_) => { + return java_set_error_field_and_extract_jobject( + &_env, + &result_jobject, + &format!( + "secp256k1 sign failed, msg_hash={}", + bytes_to_string(&msg_hash) + ), + ) + }, + }; + + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&signature), + "signature" + ); + result_jobject.into_inner() +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->secp256k1Verify'. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_secp256k1Verify( + _env: JNIEnv, + _class: JClass, + public_key_jstring: JString, + msg_hash_jstring: JString, + signature_jstring: JString, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let public_key = + java_safe_jstring_to_bytes!(_env, result_jobject, public_key_jstring); + let msg_hash = + java_safe_jstring_to_bytes!(_env, result_jobject, msg_hash_jstring); + let signature = + java_safe_jstring_to_bytes!(_env, result_jobject, signature_jstring); + + let result = SIGNATURE.verify(&public_key, &msg_hash, &signature); + + java_safe_set_boolean_field!(_env, result_jobject, result, "booleanResult"); + result_jobject.into_inner() +} + +#[no_mangle] +/// Java interface for +/// 'com.webank.wedpr.crypto.NativeInterface->keccak256Hash'. +// TODO: Add keccak256HashUtf8 to allow non-encoded UTF8 input. +pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_keccak256Hash( + _env: JNIEnv, + _class: JClass, + encoded_message_jstring: JString, +) -> jobject +{ + let result_jobject = get_result_jobject(&_env); + + let encoded_message_bytes = java_safe_jstring_to_bytes!( + _env, + result_jobject, + encoded_message_jstring + ); + + let hash = HASH.hash(&encoded_message_bytes); + + java_safe_set_string_field!( + _env, + result_jobject, + bytes_to_string(&hash), + "hash" + ); + result_jobject.into_inner() +} diff --git a/ffi/ffi_java/ffi_java_vcl/Cargo.toml b/ffi/ffi_java/ffi_java_vcl/Cargo.toml new file mode 100644 index 0000000..f5bb044 --- /dev/null +++ b/ffi/ffi_java/ffi_java_vcl/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "wedpr_ffi_java_vcl" +version = "1.1.0" +authors = ["WeDPR "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "ffi_java_vcl" +crate-type = ["cdylib", "staticlib"] + +[dependencies] +jni = "0.13.0" +protobuf = "2.10.1" +verifiable_confidential_ledger = { path = "../../../solution/verifiable_confidential_ledger" } +wedpr_crypto = { path = "../../../crypto/" } +wedpr_ffi_common = { path = "../../ffi_common/" } +wedpr_ffi_macros = { path = "../../../ffi/ffi_macros/" } +wedpr_protos = { path = "../../../protos/" } +wedpr_utils = { path = "../../../common/utils" } + +[build-dependencies] +cbindgen = "0.9.0" + +[target.'cfg(target_os = "android")'.dependencies] +jni = { version = "0.13.1", default-features = false } diff --git a/ffi/ffi_vcl/src/lib.rs b/ffi/ffi_java/ffi_java_vcl/src/lib.rs similarity index 94% rename from ffi/ffi_vcl/src/lib.rs rename to ffi/ffi_java/ffi_java_vcl/src/lib.rs index cfd986f..d018cb0 100644 --- a/ffi/ffi_vcl/src/lib.rs +++ b/ffi/ffi_java/ffi_java_vcl/src/lib.rs @@ -1,6 +1,7 @@ // Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. -//! Library of macros and functions for FFI of VCL solution. +//! Library of macros and functions for FFI of VCL solution, targeting +//! Java-compatible architectures (including Android). extern crate jni; @@ -14,19 +15,22 @@ use jni::{ }; use protobuf::{self, Message}; use verifiable_confidential_ledger; -use wedpr_crypto::utils as common_utils; -use wedpr_ffi_common::utils; +use wedpr_crypto::utils::bytes_to_string; +use wedpr_ffi_common::utils::{ + java_jstring_to_bytes, java_jstring_to_string, java_new_jobject, + java_set_error_field_and_extract_jobject, +}; use wedpr_protos::generated::{ vcl::{EncodedConfidentialCredit, EncodedOwnerSecret}, zkp::BalanceProof, }; -// Java FFI: Java interface files will be generated under +// Java FFI: Java interfaces will be generated under // package name 'com.webank.wedpr.vcl'. // Result class name is 'com.webank.wedpr.vcl.VclResult'. -const RESULT_JAVA_CLASS_NAME: &str = "Lcom/webank/wedpr/vcl/VclResult;"; +const RESULT_JAVA_CLASS_NAME: &str = "com/webank/wedpr/vcl/VclResult"; // Local macros and functions section. @@ -37,7 +41,7 @@ macro_rules! decode_secret { ) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -57,7 +61,7 @@ macro_rules! decode_credit { ) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -71,7 +75,7 @@ macro_rules! decode_credit { } fn get_result_jobject<'a>(_env: &'a JNIEnv) -> JObject<'a> { - utils::java_new_jobject(_env, RESULT_JAVA_CLASS_NAME) + java_new_jobject(_env, RESULT_JAVA_CLASS_NAME) } // Java interface section. @@ -403,5 +407,3 @@ pub extern "system" fn Java_com_webank_wedpr_vcl_NativeInterface_verifyRange( ); result_jobject.into_inner() } - -// TODO: Add more FFI sections for more programming languages. diff --git a/ffi/ffi_macros/Cargo.toml b/ffi/ffi_macros/Cargo.toml index 1f8ae41..647d472 100644 --- a/ffi/ffi_macros/Cargo.toml +++ b/ffi/ffi_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wedpr_ffi_macros" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" diff --git a/ffi/ffi_macros/src/lib.rs b/ffi/ffi_macros/src/lib.rs index 54f6176..4f1d948 100644 --- a/ffi/ffi_macros/src/lib.rs +++ b/ffi/ffi_macros/src/lib.rs @@ -10,10 +10,10 @@ #[macro_export] macro_rules! java_safe_jstring_to_bytes { ($_env:expr, $result_jobject:expr, $java_string:expr) => { - match utils::java_jstring_to_bytes(&$_env, $java_string) { + match java_jstring_to_bytes(&$_env, $java_string) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -30,10 +30,10 @@ macro_rules! java_safe_jstring_to_bytes { #[macro_export] macro_rules! java_safe_jbytes_to_bytes { ($_env:expr, $result_jobject:expr, $java_bytes:expr) => { - match utils::java_jbytes_to_bytes(&$_env, $java_bytes) { + match java_jbytes_to_bytes(&$_env, $java_bytes) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -50,10 +50,10 @@ macro_rules! java_safe_jbytes_to_bytes { #[macro_export] macro_rules! java_safe_jstring_to_string { ($_env:expr, $result_jobject:expr, $java_string:expr) => { - match utils::java_jstring_to_string(&$_env, $java_string) { + match java_jstring_to_string(&$_env, $java_string) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -73,7 +73,7 @@ macro_rules! java_safe_string_to_jstring { JObject::from(match $_env.new_string($rust_string) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -107,7 +107,7 @@ macro_rules! java_safe_bytes_to_pb { match protobuf::parse_from_bytes::<$pb_type>(&$rust_bytes) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -128,7 +128,7 @@ macro_rules! java_safe_pb_to_bytes { match $rust_pb.write_to_bytes() { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -161,7 +161,7 @@ macro_rules! java_safe_set_field { ) { Ok(v) => v, Err(_) => { - return utils::java_set_error_field_and_extract_jobject( + return java_set_error_field_and_extract_jobject( &$_env, &$result_jobject, &format!( @@ -252,7 +252,7 @@ macro_rules! java_safe_set_bytes_field { java_safe_set_string_field!( $_env, $result_jobject, - common_utils::bytes_to_string(&$rust_bytes), + bytes_to_string(&$rust_bytes), $field_name ) }; @@ -271,3 +271,167 @@ macro_rules! java_safe_set_encoded_pb_field { ) }; } + +// C/C++ FFI macros. + +/// Converts C char pointer to Rust string, and returns a specified error value +/// if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_string_with_error_value { + ($c_char_pointer:expr, $error_value:expr) => { + match c_char_pointer_to_string($c_char_pointer) { + Ok(v) => v, + Err(_) => { + wedpr_println!( + "C char pointer to string failed, pointer_name={}", + stringify!($c_char_pointer) + ); + return $error_value; + }, + } + }; +} + +/// Converts C char pointer to Rust string, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_string { + ($c_char_pointer:expr) => { + c_safe_c_char_pointer_to_string_with_error_value!( + $c_char_pointer, + ptr::null_mut() + ) + }; +} + +/// Converts C char pointer to Rust bytes, and returns a specified error value +/// if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_bytes_with_error_value { + ($c_char_pointer:expr, $error_value:expr) => { + match string_to_bytes( + &c_safe_c_char_pointer_to_string_with_error_value!( + $c_char_pointer, + $error_value + ), + ) { + Ok(v) => v, + Err(_) => return $error_value, + } + }; +} + +/// Converts C char pointer to Rust bytes, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_bytes { + ($c_char_pointer:expr) => { + c_safe_c_char_pointer_to_bytes_with_error_value!( + $c_char_pointer, + ptr::null_mut() + ) + }; +} + +/// Converts C char pointer to Rust proto, and returns a specified error value +/// if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_proto_with_error_value { + ($c_char_pointer:expr, $pb_type:ty, $error_value:expr) => { + match protobuf::parse_from_bytes::<$pb_type>( + &c_safe_c_char_pointer_to_bytes_with_error_value!( + $c_char_pointer, + $error_value + ), + ) { + Ok(v) => v, + Err(_) => return $error_value, + } + }; +} + +/// Converts C char pointer to Rust proto, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_c_char_pointer_to_proto { + ($c_char_pointer:expr, $pb_type:ty) => { + c_safe_c_char_pointer_to_proto_with_error_value!( + $c_char_pointer, + $pb_type, + ptr::null_mut() + ) + }; +} + +/// Converts Rust string to C char pointer, and returns a specified error value +/// if failed. +#[macro_export] +macro_rules! c_safe_string_to_c_char_pointer_with_error_value { + ($rust_string:expr, $error_value:expr) => { + match CString::new($rust_string) { + Ok(v) => v.into_raw(), + Err(_) => return $error_value, + } + }; +} + +/// Converts Rust string to C char pointer, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_string_to_c_char_pointer { + ($rust_string:expr) => { + c_safe_string_to_c_char_pointer_with_error_value!( + $rust_string, + ptr::null_mut() + ) + }; +} + +/// Converts Rust bytes to C char pointer, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_bytes_to_c_char_pointer { + ($rust_string:expr) => { + c_safe_string_to_c_char_pointer!(bytes_to_string($rust_string)) + }; +} + +/// Converts Rust protobuf to C char pointer, and returns NULL if failed. +#[macro_export] +macro_rules! c_safe_proto_to_c_char_pointer { + ($rust_proto:expr) => { + c_safe_bytes_to_c_char_pointer!(&match $rust_proto.write_to_bytes() { + Ok(v) => v, + Err(_) => return ptr::null_mut(), + }) + }; +} + +/// Converts encodable Rust struct to Rust string, which a implemented encode +/// function. +#[macro_export] +macro_rules! encodable_struct_to_string { + ($rust_struct:expr) => { + bytes_to_string( + &$rust_struct + .encode() + .write_to_bytes() + .expect("struct to bytes should not fail"), + ) + }; +} + +/// Returns C data, and returns a specified error value if any exception +/// occurred. +#[macro_export] +macro_rules! c_safe_return_with_error_value { + ($result:expr, $error_value:expr) => { + match $result { + Ok(v) => v, + Err(_) => $error_value, + } + }; +} + +/// Returns C data, and returns NULL if any exception occurred. +#[macro_export] +macro_rules! c_safe_return { + ($result:expr) => { + c_safe_return_with_error_value!($result, ptr::null_mut()) + }; +} diff --git a/ffi/ffi_vcl/Cargo.toml b/ffi/ffi_vcl/Cargo.toml deleted file mode 100644 index d2ec161..0000000 --- a/ffi/ffi_vcl/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "wedpr_ffi_vcl" -version = "0.1.0" -authors = ["HaoXuan40404 <444649358@qq.com>"] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -name = "ffi_vcl" -crate-type = ["cdylib"] - -[dependencies] -jni = "0.13.0" -protobuf = "2.10.1" -verifiable_confidential_ledger = { path = "../../solution/verifiable_confidential_ledger" } -wedpr_crypto = { path = "../../crypto/" } -wedpr_ffi_common = { path = "../ffi_common/" } -wedpr_ffi_macros = { path = "../../ffi/ffi_macros/" } -wedpr_protos = { path = "../../protos/" } -wedpr_utils = { path = "../../common/utils" } - -[build-dependencies] -cbindgen = "0.9.0" diff --git a/protos/Cargo.toml b/protos/Cargo.toml index 1d3265d..00eeafb 100644 --- a/protos/Cargo.toml +++ b/protos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wedpr_protos" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018" diff --git a/protos/crypto/common.proto b/protos/crypto/common.proto new file mode 100644 index 0000000..d31f293 --- /dev/null +++ b/protos/crypto/common.proto @@ -0,0 +1,12 @@ +// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. + +syntax = "proto3"; + +package com.webank.wedpr.crypto.proto; +option java_package = "com.webank.wedpr.crypto.proto"; +option java_multiple_files = true; + +message Keypair { + string public_key = 1; + string private_key = 2; +} \ No newline at end of file diff --git a/protos/solution/vcl/vcl.proto b/protos/solution/vcl/vcl.proto index ad16e2e..be4cfb5 100644 --- a/protos/solution/vcl/vcl.proto +++ b/protos/solution/vcl/vcl.proto @@ -15,4 +15,11 @@ message EncodedOwnerSecret { // Encoded data to represent a confidential credit used by VCL solution. message EncodedConfidentialCredit { string point = 1; +} + +// Return data to FFI C interface +message VclResult { + string credit = 1; + string secret = 2; + string proof = 3; } \ No newline at end of file diff --git a/protos/src/generated/common.rs b/protos/src/generated/common.rs new file mode 100644 index 0000000..ed1ba25 --- /dev/null +++ b/protos/src/generated/common.rs @@ -0,0 +1,280 @@ +// This file is generated by rust-protobuf 2.17.0. Do not edit +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![rustfmt::skip] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_imports)] +#![allow(unused_results)] +//! Generated file from `crypto/common.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_17_0; + +#[derive(PartialEq, Clone, Default)] +pub struct Keypair { + // message fields + pub public_key: ::std::string::String, + pub private_key: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a Keypair { + fn default() -> &'a Keypair { + ::default_instance() + } +} + +impl Keypair { + pub fn new() -> Keypair { + ::std::default::Default::default() + } + + // string public_key = 1; + + pub fn get_public_key(&self) -> &str { + &self.public_key + } + pub fn clear_public_key(&mut self) { + self.public_key.clear(); + } + + // Param is passed by value, moved + pub fn set_public_key(&mut self, v: ::std::string::String) { + self.public_key = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_public_key(&mut self) -> &mut ::std::string::String { + &mut self.public_key + } + + // Take field + pub fn take_public_key(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.public_key, ::std::string::String::new()) + } + + // string private_key = 2; + + pub fn get_private_key(&self) -> &str { + &self.private_key + } + pub fn clear_private_key(&mut self) { + self.private_key.clear(); + } + + // Param is passed by value, moved + pub fn set_private_key(&mut self, v: ::std::string::String) { + self.private_key = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_private_key(&mut self) -> &mut ::std::string::String { + &mut self.private_key + } + + // Take field + pub fn take_private_key(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.private_key, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for Keypair { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from( + &mut self, + is: &mut ::protobuf::CodedInputStream<'_>, + ) -> ::protobuf::ProtobufResult<()> + { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into( + wire_type, + is, + &mut self.public_key, + )?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into( + wire_type, + is, + &mut self.private_key, + )?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group( + field_number, + wire_type, + is, + self.mut_unknown_fields(), + )?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.public_key.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.public_key); + } + if !self.private_key.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.private_key); + } + my_size += + ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes( + &self, + os: &mut ::protobuf::CodedOutputStream<'_>, + ) -> ::protobuf::ProtobufResult<()> + { + if !self.public_key.is_empty() { + os.write_string(1, &self.public_key)?; + } + if !self.private_key.is_empty() { + os.write_string(2, &self.private_key)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any( + self: ::std::boxed::Box, + ) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> Keypair { + Keypair::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2< + ::protobuf::reflect::MessageDescriptor, + > = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push( + ::protobuf::reflect::accessor::make_simple_field_accessor::< + _, + ::protobuf::types::ProtobufTypeString, + >( + "public_key", + |m: &Keypair| &m.public_key, + |m: &mut Keypair| &mut m.public_key, + ), + ); + fields.push( + ::protobuf::reflect::accessor::make_simple_field_accessor::< + _, + ::protobuf::types::ProtobufTypeString, + >( + "private_key", + |m: &Keypair| &m.private_key, + |m: &mut Keypair| &mut m.private_key, + ), + ); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "Keypair", + fields, + file_descriptor_proto(), + ) + }) + } + + fn default_instance() -> &'static Keypair { + static instance: ::protobuf::rt::LazyV2 = + ::protobuf::rt::LazyV2::INIT; + instance.get(Keypair::new) + } +} + +impl ::protobuf::Clear for Keypair { + fn clear(&mut self) { + self.public_key.clear(); + self.private_key.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for Keypair { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for Keypair { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x13crypto/common.proto\x12\x1dcom.webank.wedpr.crypto.proto\"I\n\x07K\ + eypair\x12\x1d\n\npublic_key\x18\x01\x20\x01(\tR\tpublicKey\x12\x1f\n\ + \x0bprivate_key\x18\x02\x20\x01(\tR\nprivateKeyB!\n\x1dcom.webank.wedpr.\ + crypto.protoP\x01b\x06proto3\ +"; + +static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2< + ::protobuf::descriptor::FileDescriptorProto, +> = ::protobuf::rt::LazyV2::INIT; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto( +) -> &'static ::protobuf::descriptor::FileDescriptorProto { + file_descriptor_proto_lazy.get(|| parse_descriptor_proto()) +} diff --git a/protos/src/generated/mod.rs b/protos/src/generated/mod.rs index 26302bb..df9f365 100644 --- a/protos/src/generated/mod.rs +++ b/protos/src/generated/mod.rs @@ -1,4 +1,5 @@ // Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. +pub mod common; pub mod vcl; pub mod zkp; diff --git a/protos/src/generated/vcl.rs b/protos/src/generated/vcl.rs index 451dd65..a4f6bee 100644 --- a/protos/src/generated/vcl.rs +++ b/protos/src/generated/vcl.rs @@ -1,5 +1,3 @@ -// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. - // This file is generated by rust-protobuf 2.17.0. Do not edit // @generated @@ -443,12 +441,301 @@ impl ::protobuf::reflect::ProtobufValue for EncodedConfidentialCredit { } } +#[derive(PartialEq, Clone, Default)] +pub struct VclResult { + // message fields + pub credit: ::std::string::String, + pub secret: ::std::string::String, + pub proof: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a VclResult { + fn default() -> &'a VclResult { + ::default_instance() + } +} + +impl VclResult { + pub fn new() -> VclResult { + ::std::default::Default::default() + } + + // string credit = 1; + + pub fn get_credit(&self) -> &str { + &self.credit + } + pub fn clear_credit(&mut self) { + self.credit.clear(); + } + + // Param is passed by value, moved + pub fn set_credit(&mut self, v: ::std::string::String) { + self.credit = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_credit(&mut self) -> &mut ::std::string::String { + &mut self.credit + } + + // Take field + pub fn take_credit(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.credit, ::std::string::String::new()) + } + + // string secret = 2; + + pub fn get_secret(&self) -> &str { + &self.secret + } + pub fn clear_secret(&mut self) { + self.secret.clear(); + } + + // Param is passed by value, moved + pub fn set_secret(&mut self, v: ::std::string::String) { + self.secret = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_secret(&mut self) -> &mut ::std::string::String { + &mut self.secret + } + + // Take field + pub fn take_secret(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.secret, ::std::string::String::new()) + } + + // string proof = 3; + + pub fn get_proof(&self) -> &str { + &self.proof + } + pub fn clear_proof(&mut self) { + self.proof.clear(); + } + + // Param is passed by value, moved + pub fn set_proof(&mut self, v: ::std::string::String) { + self.proof = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_proof(&mut self) -> &mut ::std::string::String { + &mut self.proof + } + + // Take field + pub fn take_proof(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.proof, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for VclResult { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from( + &mut self, + is: &mut ::protobuf::CodedInputStream<'_>, + ) -> ::protobuf::ProtobufResult<()> + { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into( + wire_type, + is, + &mut self.credit, + )?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into( + wire_type, + is, + &mut self.secret, + )?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into( + wire_type, + is, + &mut self.proof, + )?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group( + field_number, + wire_type, + is, + self.mut_unknown_fields(), + )?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.credit.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.credit); + } + if !self.secret.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.secret); + } + if !self.proof.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.proof); + } + my_size += + ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes( + &self, + os: &mut ::protobuf::CodedOutputStream<'_>, + ) -> ::protobuf::ProtobufResult<()> + { + if !self.credit.is_empty() { + os.write_string(1, &self.credit)?; + } + if !self.secret.is_empty() { + os.write_string(2, &self.secret)?; + } + if !self.proof.is_empty() { + os.write_string(3, &self.proof)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any( + self: ::std::boxed::Box, + ) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> VclResult { + VclResult::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2< + ::protobuf::reflect::MessageDescriptor, + > = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push( + ::protobuf::reflect::accessor::make_simple_field_accessor::< + _, + ::protobuf::types::ProtobufTypeString, + >( + "credit", + |m: &VclResult| &m.credit, + |m: &mut VclResult| &mut m.credit, + ), + ); + fields.push( + ::protobuf::reflect::accessor::make_simple_field_accessor::< + _, + ::protobuf::types::ProtobufTypeString, + >( + "secret", + |m: &VclResult| &m.secret, + |m: &mut VclResult| &mut m.secret, + ), + ); + fields.push( + ::protobuf::reflect::accessor::make_simple_field_accessor::< + _, + ::protobuf::types::ProtobufTypeString, + >( + "proof", + |m: &VclResult| &m.proof, + |m: &mut VclResult| &mut m.proof, + ), + ); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "VclResult", + fields, + file_descriptor_proto(), + ) + }) + } + + fn default_instance() -> &'static VclResult { + static instance: ::protobuf::rt::LazyV2 = + ::protobuf::rt::LazyV2::INIT; + instance.get(VclResult::new) + } +} + +impl ::protobuf::Clear for VclResult { + fn clear(&mut self) { + self.credit.clear(); + self.secret.clear(); + self.proof.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for VclResult { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for VclResult { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\x16solution/vcl/vcl.proto\x12\x1acom.webank.wedpr.vcl.proto\"`\n\x12E\ ncodedOwnerSecret\x12!\n\x0ccredit_value\x18\x01\x20\x01(\x03R\x0bcredit\ Value\x12'\n\x0fsecret_blinding\x18\x02\x20\x01(\tR\x0esecretBlinding\"1\ \n\x19EncodedConfidentialCredit\x12\x14\n\x05point\x18\x01\x20\x01(\tR\ - \x05pointB\x1e\n\x1acom.webank.wedpr.vcl.protoP\x01b\x06proto3\ + \x05point\"Q\n\tVclResult\x12\x16\n\x06credit\x18\x01\x20\x01(\tR\x06cre\ + dit\x12\x16\n\x06secret\x18\x02\x20\x01(\tR\x06secret\x12\x14\n\x05proof\ + \x18\x03\x20\x01(\tR\x05proofB\x1e\n\x1acom.webank.wedpr.vcl.protoP\x01b\ + \x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2< diff --git a/protos/src/generated/zkp.rs b/protos/src/generated/zkp.rs index 09b430f..69eaf61 100644 --- a/protos/src/generated/zkp.rs +++ b/protos/src/generated/zkp.rs @@ -1,5 +1,3 @@ -// Copyright 2020 WeDPR Lab Project Authors. Licensed under Apache-2.0. - // This file is generated by rust-protobuf 2.17.0. Do not edit // @generated diff --git a/protos/src/main.rs b/protos/src/main.rs index 06d8db2..8f52318 100644 --- a/protos/src/main.rs +++ b/protos/src/main.rs @@ -27,7 +27,7 @@ fn generate_proto_for_all() { .includes(&["."]) // List all used proto files here. // You can remove any proto files that are not used by your project. - .inputs(&["crypto/zkp.proto", "solution/vcl/vcl.proto"]) + .inputs(&["crypto/zkp.proto", "crypto/common.proto","solution/vcl/vcl.proto"]) .customize(Customize { ..Default::default() }) diff --git a/solution/verifiable_confidential_ledger/Cargo.toml b/solution/verifiable_confidential_ledger/Cargo.toml index c6d1e38..d6e3e0e 100644 --- a/solution/verifiable_confidential_ledger/Cargo.toml +++ b/solution/verifiable_confidential_ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "verifiable_confidential_ledger" -version = "1.0.0" +version = "1.1.0" authors = ["WeDPR "] edition = "2018"