Skip to content

Commit

Permalink
add ecdh-psi wasm && jni interface
Browse files Browse the repository at this point in the history
  • Loading branch information
HaoXuan40404 committed Jul 27, 2023
1 parent 3120555 commit 40a2673
Show file tree
Hide file tree
Showing 12 changed files with 478 additions and 62 deletions.
219 changes: 180 additions & 39 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ members = [
"protos",
"third_party/fisco_bcos",
"third_party/fisco_bcos_java_sdk",
"third_party/ecdh_psi/psi_utils",
"third_party/ecdh_psi/ffi_java_ecdh_psi",
"third_party/ecdh_psi/ffi_wasm_ecdh_psi",
]
17 changes: 7 additions & 10 deletions crypto/signature/secp256k1/benches/secp256k1.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// Copyright 2021 WeDPR Lab Project Authors. Licensed under Apache-2.0.

use criterion::Criterion;
use wedpr_l_crypto_signature_secp256k1::{WedprSecp256k1Recover};
use wedpr_l_utils::traits::Signature;
use wedpr_l_utils::constant::tests::BASE64_ENCODED_TEST_MESSAGE;
use wedpr_l_crypto_signature_secp256k1::WedprSecp256k1Recover;
use wedpr_l_utils::{
constant::tests::BASE64_ENCODED_TEST_MESSAGE, traits::Signature,
};

#[macro_use]
extern crate criterion;

fn create_sign_helper(c: &mut Criterion, message_size: usize) {
let label =
format!("create_sign_helper, message_size = {}", message_size);
let label = format!("create_sign_helper, message_size = {}", message_size);
let secp256k1 = WedprSecp256k1Recover::default();
let (pk_b, sk_b) = secp256k1.generate_keypair();

Expand All @@ -26,20 +26,17 @@ fn create_sign_helper(c: &mut Criterion, message_size: usize) {
fn create_verify_helper(c: &mut Criterion, message_size: usize) {
let label =
format!("create_verify_helper, message_size = {}", message_size);
let label =
format!("create_sign_helper, message_size = {}", message_size);
let label = format!("create_sign_helper, message_size = {}", message_size);
let secp256k1 = WedprSecp256k1Recover::default();
let (pk_b, sk_b) = secp256k1.generate_keypair();

let message = BASE64_ENCODED_TEST_MESSAGE;

let sign_obj = secp256k1.sign(&sk_b, &message.to_vec()).unwrap();


c.bench_function(&label, move |b| {
b.iter(|| {
let _ = secp256k1
.recover_public_key(&message.to_vec(), &sign_obj);
let _ = secp256k1.recover_public_key(&message.to_vec(), &sign_obj);
})
});
}
Expand Down
23 changes: 11 additions & 12 deletions crypto/signature/secp256k1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ extern crate lazy_static;

extern crate secp256k1;
use secp256k1::{
ecdsa::{RecoverableSignature, RecoveryId},
rand::rngs::OsRng,
All, Message, PublicKey, Secp256k1, SecretKey, VerifyOnly,
};
use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
use wedpr_l_utils::{error::WedprError, traits::Signature};
use secp256k1::rand::rngs::OsRng;

lazy_static! {
// Shared secp256k1 instance initialized for verification function only.
Expand All @@ -22,7 +22,6 @@ lazy_static! {
static ref SECP256K1_ALL: Secp256k1<All> = Secp256k1::new();
}


/// Implements FISCO-BCOS-compatible Secp256k1 as a Signature instance.
#[derive(Default, Debug, Clone, Copy)]
pub struct WedprSecp256k1Recover {}
Expand Down Expand Up @@ -99,7 +98,6 @@ impl Signature for WedprSecp256k1Recover {

fn generate_keypair(&self) -> (Vec<u8>, Vec<u8>) {
loop {

let (secret_key, public_key) =
SECP256K1_ALL.generate_keypair(&mut OsRng);

Expand Down Expand Up @@ -155,14 +153,15 @@ impl WedprSecp256k1Recover {
return Err(WedprError::FormatError);
},
};
let recovered_public_key =
match SECP256K1_VERIFY.recover_ecdsa(&msg_hash_obj, &get_sign_final) {
Ok(v) => v,
Err(_) => {
wedpr_println!("Signature recover failed");
return Err(WedprError::FormatError);
},
};
let recovered_public_key = match SECP256K1_VERIFY
.recover_ecdsa(&msg_hash_obj, &get_sign_final)
{
Ok(v) => v,
Err(_) => {
wedpr_println!("Signature recover failed");
return Err(WedprError::FormatError);
},
};
return Ok(recovered_public_key.serialize_uncompressed().to_vec());
}

Expand Down
2 changes: 1 addition & 1 deletion protos/src/generated/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

pub mod common;
pub mod ot;
pub mod zkp;
pub mod zkp;
14 changes: 14 additions & 0 deletions third_party/ecdh_psi/ffi_java_ecdh_psi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "ffi_java_ecdh_psi"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
name = "ffi_java_ecdh_psi"
crate-type = [ "cdylib", "staticlib" ]

[dependencies]
jni = "0.13.0"
psi_utils = { path = "../psi_utils"}
95 changes: 95 additions & 0 deletions third_party/ecdh_psi/ffi_java_ecdh_psi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
extern crate jni;

use psi_utils::{
hash_to_curve, point_scalar_multi, random_scalar, scalar_inverse,
};

use jni::{objects::JClass, sys::jbyteArray, JNIEnv};

// 导出函数给JNI接口调用

#[no_mangle]
pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_randomScalar(
env: JNIEnv,
_class: JClass,
) -> jbyteArray {
// 调用原始函数
let result = random_scalar();

// 将 Vec<u8> 转换成 jbyteArray 并返回给Java层
match env.byte_array_from_slice(&result) {
Ok(array) => array,
Err(_) => env.new_byte_array(0).unwrap(), // 返回空的 jbyteArray
}
}

#[no_mangle]
pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_hashToCurve(
env: JNIEnv,
_class: JClass,
message: jbyteArray,
) -> jbyteArray {
// 将 jbyteArray 转换成 Vec<u8>
let message_bytes = match env.convert_byte_array(message) {
Ok(bytes) => bytes,
Err(_) => return env.new_byte_array(0).unwrap(), /* 返回空的 jbyteArray */
};

// 调用原始函数
let result = hash_to_curve(&message_bytes);

// 将 Vec<u8> 转换成 jbyteArray 并返回给Java层
match env.byte_array_from_slice(&result) {
Ok(array) => array,
Err(_) => env.new_byte_array(0).unwrap(), // 返回空的 jbyteArray
}
}

#[no_mangle]
pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_scalarInverse(
env: JNIEnv,
_class: JClass,
scalar: jbyteArray,
) -> jbyteArray {
// 将 jbyteArray 转换成 Vec<u8>
let scalar_bytes = match env.convert_byte_array(scalar) {
Ok(bytes) => bytes,
Err(_) => return env.new_byte_array(0).unwrap(), /* 返回空的 jbyteArray */
};

// 调用原始函数
let result = scalar_inverse(&scalar_bytes);

// 将 Vec<u8> 转换成 jbyteArray 并返回给Java层
match env.byte_array_from_slice(&result) {
Ok(array) => array,
Err(_) => env.new_byte_array(0).unwrap(), // 返回空的 jbyteArray
}
}

#[no_mangle]
pub extern "system" fn Java_com_webank_wedpr_crypto_NativeInterface_pointScalarMulti(
env: JNIEnv,
_class: JClass,
point: jbyteArray,
scalar: jbyteArray,
) -> jbyteArray {
// 将 jbyteArray 转换成 Vec<u8>
let point_bytes = match env.convert_byte_array(point) {
Ok(bytes) => bytes,
Err(_) => return env.new_byte_array(0).unwrap(), /* 返回空的 jbyteArray */
};
let scalar_bytes = match env.convert_byte_array(scalar) {
Ok(bytes) => bytes,
Err(_) => return env.new_byte_array(0).unwrap(), /* 返回空的 jbyteArray */
};

// 调用原始函数
let result = point_scalar_multi(&point_bytes, &scalar_bytes);

// 将 Vec<u8> 转换成 jbyteArray 并返回给Java层
match env.byte_array_from_slice(&result) {
Ok(array) => array,
Err(_) => env.new_byte_array(0).unwrap(), // 返回空的 jbyteArray
}
}
14 changes: 14 additions & 0 deletions third_party/ecdh_psi/ffi_wasm_ecdh_psi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "ffi_wasm_ecdh_psi"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "ffi_wasm_ecdh_psi"
crate-type = ["rlib", "cdylib"]

[dependencies]
wasm-bindgen = "0.2"
getrandom = { version = "0.2", features = ["js"] }
psi_utils = { path = "../psi_utils"}
17 changes: 17 additions & 0 deletions third_party/ecdh_psi/ffi_wasm_ecdh_psi/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 编译生成wasm

`wasm-pack build`命令可以使用不同的目标参数,用于生成不同平台和环境可用的 WebAssembly(Wasm)模块。以下是`wasm-pack`库当前版本(v0.10.0)中支持的目标选项:

1. `bundler`(默认):生成可以在现代浏览器和支持 ES6 模块的环境中使用的 Wasm 模块,打包为单个文件。

2. `web`:生成可以在现代浏览器中直接使用的 Wasm 模块,打包为单个文件。

3. `no-modules`:生成不依赖 ES6 模块的 Wasm 输出,适用于在没有模块系统的环境下使用。

4. `nodejs`:生成可以在 Node.js 环境中使用的 Wasm 模块,使用 CommonJS 模块进行导出。

5. `webworker`:生成用于 Web Worker 的 Wasm 模块,打包为单个文件。

6. `nodejs-esm`:生成可以在支持 ES6 模块的 Node.js 环境中使用的 Wasm 模块。

你可以根据你的需求,选择合适的构建目标,以便在不同的环境中正确地使用和部署生成的 Wasm 模块。使用对应的`--target`选项来选择特定的目标。例如:`wasm-pack build --target web`将生成支持现代浏览器的 Wasm 模块。
26 changes: 26 additions & 0 deletions third_party/ecdh_psi/ffi_wasm_ecdh_psi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
extern crate wasm_bindgen;

use psi_utils::{
hash_to_curve, point_scalar_multi, random_scalar, scalar_inverse,
};
use wasm_bindgen::prelude::wasm_bindgen;

#[wasm_bindgen]
pub fn wasm_scalar_inverse(scalar: &[u8]) -> Vec<u8> {
scalar_inverse(scalar)
}

#[wasm_bindgen]
pub fn wasm_point_scalar_multi(point: &[u8], scalar: &[u8]) -> Vec<u8> {
point_scalar_multi(point, scalar)
}

#[wasm_bindgen]
pub fn wasm_hash_to_curve(message: &[u8]) -> Vec<u8> {
hash_to_curve(message)
}

#[wasm_bindgen]
pub fn wasm_random_scalar() -> Vec<u8> {
random_scalar()
}
13 changes: 13 additions & 0 deletions third_party/ecdh_psi/psi_utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "psi_utils"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html


[dependencies]
sha2 = "0.10.7"
rand = "0.8.4"
rand_core = "0.6.3"
curve25519-dalek = { version = "4", features = [ "digest" , "rand_core"] }
97 changes: 97 additions & 0 deletions third_party/ecdh_psi/psi_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use sha2::Sha512;
// use sha2::Digest;
use rand::rngs::ThreadRng;
// use rand::RngCore;
use curve25519_dalek::{
edwards::{CompressedEdwardsY, EdwardsPoint},
Scalar,
};

const SCALAR_SIZE: usize = 32;
const POINT_SIZE: usize = 32;

pub fn random_scalar() -> Vec<u8> {
// 创建一个随机数生成器
let mut rng: ThreadRng = rand::thread_rng();

// 生成一个随机的 Scalar
let scalar = Scalar::random(&mut rng);

// 将 Scalar 转换成 &[u8]
scalar.to_bytes().to_vec()
}

pub fn hash_to_curve(message: &[u8]) -> Vec<u8> {
let hash_scalar = Scalar::hash_from_bytes::<Sha512>(message);
let hash_point = EdwardsPoint::mul_base(&hash_scalar);
return hash_point.compress().to_bytes().to_vec();
}

pub fn scalar_inverse(scalar: &[u8]) -> Vec<u8> {
// 检查输入切片是否具有正确的大小
if scalar.len() != SCALAR_SIZE {
return Vec::new(); // 如果大小不正确,返回空的 Vec<u8>
}

// 将输入 &[u8] 转换成 Scalar
let mut scalar_bytes = [0u8; SCALAR_SIZE];
scalar_bytes.copy_from_slice(scalar);
let scalar = Scalar::from_bytes_mod_order(scalar_bytes);
let inverse_scalar = scalar.invert();
return inverse_scalar.to_bytes().to_vec();
}

pub fn point_scalar_multi(point: &[u8], scalar: &[u8]) -> Vec<u8> {
// 检查输入切片是否具有正确的大小
if point.len() != POINT_SIZE || scalar.len() != SCALAR_SIZE {
return Vec::new(); // 如果大小不正确,返回空的 Vec<u8>
}

// 将输入 &[u8] 转换成 CompressedEdwardsY 表示的点
let mut point_bytes = [0u8; POINT_SIZE];
point_bytes.copy_from_slice(point);
let compressed_point = match CompressedEdwardsY(point_bytes).decompress() {
Some(point) => point,
None => return Vec::new(), // 解析点失败,返回空的 Vec<u8>
};

// 将输入 &[u8] 转换成 Scalar
let mut scalar_bytes = [0u8; SCALAR_SIZE];
scalar_bytes.copy_from_slice(scalar);
let scalar = Scalar::from_bytes_mod_order(scalar_bytes);

// 执行点乘操作
let result_point = compressed_point * scalar;

// 将结果转换成压缩格式的点
let compressed_result = result_point.compress();

// 将结果转换成 &[u8]
compressed_result.as_bytes().to_vec()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_flow() {
// 生成一个随机的标量
let random_scalar = random_scalar();
println!("Random Scalar: {:?}", random_scalar);

// 定义一个消息,对其进行哈希并生成哈希点
let message = "To really appreciate architecture, you may even need \
to commit a murder";
let hash_point = hash_to_curve(message.as_bytes());

// 定义一个标量并计算其逆元
let inverse_scalar = scalar_inverse(&random_scalar);

// 定义一个点和标量,并进行点乘操作
let point_mul_result = point_scalar_multi(&hash_point, &random_scalar);
let point_mul_result2 =
point_scalar_multi(&point_mul_result, &inverse_scalar);
assert_eq!(point_mul_result2, hash_point);
}
}

0 comments on commit 40a2673

Please sign in to comment.