use helpers::{gen_test_scalar_sk, test_gen_signals, PlumeVersion};
use k256::{elliptic_curve::sec1::ToEncodedPoint, NonZeroScalar, ProjectivePoint};
use plume_rustcrypto::{AffinePoint, PlumeSignature, PlumeSignatureV1Fields};
const G: ProjectivePoint = ProjectivePoint::GENERATOR;
const M: &[u8; 29] = b"An example app message string";
const C_V1: [u8; 32] =
hex_literal::hex!("c6a7fc2c926ddbaf20731a479fb6566f2daa5514baae5223fe3b32edbce83254");
#[test]
fn plume_v1_test() {
let test_data = test_gen_signals(M, PlumeVersion::V1);
let r_point = test_data.4.unwrap();
let hashed_to_curve_r = test_data.5.unwrap();
println!("{:?}", test_data.3);
println!("{}", NonZeroScalar::new(test_data.3).unwrap().to_string());
let sig = PlumeSignature {
message: M.to_owned().into(),
pk: (G * gen_test_scalar_sk()).into(),
nullifier: test_data.1.into(),
c: NonZeroScalar::from_repr(C_V1.into()).unwrap(),
s: NonZeroScalar::new(test_data.3).unwrap(),
v1specific: Some(PlumeSignatureV1Fields {
r_point: r_point.into(),
hashed_to_curve_r: hashed_to_curve_r.into(),
}),
};
let verified = sig.verify();
println!("Verified: {}", verified);
println!(
"nullifier.x: {:?}",
hex::encode(sig.nullifier.to_encoded_point(false).x().unwrap())
);
println!(
"nullifier.y: {:?}",
hex::encode(sig.nullifier.to_encoded_point(false).y().unwrap())
);
println!("c: {:?}", hex::encode(C_V1));
println!("r_sk_c: {:?}", hex::encode(sig.s.to_bytes()));
println!(
"g_r.x: {:?}",
hex::encode(r_point.to_affine().to_encoded_point(false).x().unwrap())
);
println!(
"g_r.y: {:?}",
hex::encode(r_point.to_affine().to_encoded_point(false).y().unwrap())
);
println!(
"hash_m_pk_pow_r.x: {:?}",
hex::encode(
hashed_to_curve_r
.to_affine()
.to_encoded_point(false)
.x()
.unwrap()
)
);
println!(
"hash_m_pk_pow_r.y: {:?}",
hex::encode(
hashed_to_curve_r
.to_affine()
.to_encoded_point(false)
.y()
.unwrap()
)
);
assert!(verified);
}
#[test]
fn plume_v2_test() {
let test_data = test_gen_signals(M, PlumeVersion::V2);
assert!(PlumeSignature {
message: M.to_owned().into(),
pk: (G * gen_test_scalar_sk()).into(),
nullifier: test_data.1.into(),
c: NonZeroScalar::from_repr(test_data.2).unwrap(),
s: NonZeroScalar::new(test_data.3).unwrap(),
v1specific: None
}
.verify());
}
mod helpers {
use super::*;
use hex_literal::hex;
use k256::{
elliptic_curve::{
bigint::ArrayEncoding,
hash2curve::{ExpandMsgXmd, GroupDigest},
ops::ReduceNonZero,
PrimeField,
},
sha2::{digest::Output, Digest, Sha256},
Scalar, Secp256k1, U256,
};
#[derive(Debug)]
pub enum PlumeVersion {
V1,
V2,
}
pub fn gen_test_scalar_sk() -> Scalar {
Scalar::from_repr(
hex!("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464").into(),
)
.unwrap()
}
fn gen_test_scalar_r() -> Scalar {
Scalar::from_repr(
hex!("93b9323b629f251b8f3fc2dd11f4672c5544e8230d493eceea98a90bda789808").into(),
)
.unwrap()
}
pub fn hash_to_secp(s: &[u8]) -> ProjectivePoint {
let pt: ProjectivePoint = Secp256k1::hash_from_bytes::<ExpandMsgXmd<Sha256>>(
&[s],
&[plume_rustcrypto::DST],
)
.unwrap();
pt
}
use k256::ProjectivePoint;
pub fn test_gen_signals(
m: &[u8],
version: PlumeVersion,
) -> (
ProjectivePoint,
ProjectivePoint,
Output<Sha256>,
Scalar,
Option<ProjectivePoint>,
Option<ProjectivePoint>,
) {
let g = ProjectivePoint::GENERATOR;
let sk = gen_test_scalar_sk();
let r = gen_test_scalar_r();
let pk = &g * &sk;
let g_r = &g * &r;
let hash_m_pk =
Secp256k1::hash_from_bytes::<ExpandMsgXmd<Sha256>>(
&[[
m,
&pk.to_encoded_point(true).to_bytes().to_vec()
].concat().as_slice()],
&[plume_rustcrypto::DST],
)
.unwrap();
println!(
"h.x: {:?}",
hex::encode(hash_m_pk.to_affine().to_encoded_point(false).x().unwrap())
);
println!(
"h.y: {:?}",
hex::encode(hash_m_pk.to_affine().to_encoded_point(false).y().unwrap())
);
let hash_m_pk_pow_r = &hash_m_pk * &r;
println!(
"hash_m_pk_pow_r.x: {:?}",
hex::encode(
hash_m_pk_pow_r
.to_affine()
.to_encoded_point(false)
.x()
.unwrap()
)
);
println!(
"hash_m_pk_pow_r.y: {:?}",
hex::encode(
hash_m_pk_pow_r
.to_affine()
.to_encoded_point(false)
.y()
.unwrap()
)
);
let nullifier = &hash_m_pk * &sk;
let c = match version {
PlumeVersion::V1 => Sha256::digest(
vec![&g, &pk, &hash_m_pk, &nullifier, &g_r, &hash_m_pk_pow_r]
.into_iter()
.map(|x| x.to_encoded_point(true).to_bytes().to_vec())
.collect::<Vec<_>>()
.concat()
.as_slice(),
),
PlumeVersion::V2 => {
dbg!("entering `Sha256::digest` for `V2`");
let result = Sha256::digest(
vec![&nullifier, &g_r, &hash_m_pk_pow_r]
.into_iter()
.map(|x| x.to_encoded_point(true).to_bytes().to_vec())
.collect::<Vec<_>>()
.concat()
.as_slice(),
);
dbg!("finished `Sha256::digest` for `V2`");
result
}
};
dbg!(&c, version);
let c_scalar = Scalar::from_repr(c).unwrap();
let r_sk_c = r + sk * c_scalar;
(pk, nullifier, c, r_sk_c, Some(g_r), Some(hash_m_pk_pow_r))
}
#[cfg(test)]
mod tests {
use super::*;
use k256::elliptic_curve::sec1::ToEncodedPoint;
#[test]
fn test_hash_to_curve() {
let h = hash_to_secp(b"abc");
assert_eq!(
hex::encode(h.to_affine().to_encoded_point(false).x().unwrap()),
"3377e01eab42db296b512293120c6cee72b6ecf9f9205760bd9ff11fb3cb2c4b"
);
assert_eq!(
hex::encode(h.to_affine().to_encoded_point(false).y().unwrap()),
"7f95890f33efebd1044d382a01b1bee0900fb6116f94688d487c6c7b9c8371f6"
);
}
}
}