Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Libsecp v0.30.0 compat #199

Merged
merged 2 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ecdsa_fun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ required-features = ["libsecp_compat"]

[features]
default = ["std"]
libsecp_compat = ["libsecp_compat_0_28", "secp256kfun/libsecp_compat"]
libsecp_compat = ["libsecp_compat_0_30", "secp256kfun/libsecp_compat"]
libsecp_compat_0_27 = ["secp256kfun/libsecp_compat_0_27"]
libsecp_compat_0_28 = ["secp256kfun/libsecp_compat_0_28"]
libsecp_compat_0_29 = ["secp256kfun/libsecp_compat_0_29"]
libsecp_compat_0_30 = ["secp256kfun/libsecp_compat_0_30"]
std = ["alloc"]
alloc = ["secp256kfun/alloc", "sigma_fun?/alloc" ]
serde = ["secp256kfun/serde","sigma_fun?/serde"]
Expand Down
17 changes: 17 additions & 0 deletions ecdsa_fun/src/libsecp_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,20 @@ mod v0_29 {
}
}
}

#[cfg(feature = "libsecp_compat_0_30")]
mod v0_30 {
use crate::{fun::secp256k1_0_30::ecdsa, Signature};

impl From<Signature> for ecdsa::Signature {
fn from(sig: Signature) -> Self {
ecdsa::Signature::from_compact(sig.to_bytes().as_ref()).unwrap()
}
}

impl From<ecdsa::Signature> for Signature {
fn from(sig: ecdsa::Signature) -> Self {
Signature::from_bytes(sig.serialize_compact()).unwrap()
}
}
}
1 change: 1 addition & 0 deletions schnorr_fun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ libsecp_compat = ["libsecp_compat_0_29", "secp256kfun/libsecp_compat"]
libsecp_compat_0_27 = ["secp256kfun/libsecp_compat_0_27"]
libsecp_compat_0_28 = ["secp256kfun/libsecp_compat_0_28"]
libsecp_compat_0_29 = ["secp256kfun/libsecp_compat_0_29"]
libsecp_compat_0_30 = ["secp256kfun/libsecp_compat_0_30"]
proptest = ["secp256kfun/proptest"]
share_backup = ["dep:bech32"]

Expand Down
12 changes: 5 additions & 7 deletions schnorr_fun/benches/bench_schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ fn sign_schnorr(c: &mut Criterion) {
}

{
use secp256k1::{Keypair, Message, Secp256k1};
use secp256k1::{Keypair, Secp256k1};
let secp = Secp256k1::new();
let kp = Keypair::from_secret_key(&secp, &(*SK).into());
let msg = Message::from_digest_slice(&MESSAGE[..]).unwrap();
group.bench_function("secp::schnorrsig_sign_no_aux_rand", |b| {
b.iter(|| {
secp.sign_schnorr_no_aux_rand(&msg, &kp);
secp.sign_schnorr_no_aux_rand(&MESSAGE[..], &kp);
});
});
}
Expand All @@ -57,14 +56,13 @@ fn verify_schnorr(c: &mut Criterion) {
}

{
use secp256k1::{Keypair, Message, Secp256k1, XOnlyPublicKey};
use secp256k1::{Keypair, Secp256k1, XOnlyPublicKey};
let secp = Secp256k1::new();
let kp = Keypair::from_secret_key(&secp, &(*SK).into());
let pk = XOnlyPublicKey::from_keypair(&kp).0;
let msg = Message::from_digest_slice(&MESSAGE[..]).unwrap();
let sig = secp.sign_schnorr_no_aux_rand(&msg, &kp);
let sig = secp.sign_schnorr_no_aux_rand(&MESSAGE[..], &kp);
group.bench_function("secp::schnorrsig_verify", |b| {
b.iter(|| secp.verify_schnorr(&sig, &msg, &pk));
b.iter(|| secp.verify_schnorr(&sig, &MESSAGE[..], &pk));
});
}
}
Expand Down
12 changes: 12 additions & 0 deletions schnorr_fun/src/frost/shared_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ impl<T: PointType, Z: ZeroChoice> SharedKey<T, Z> {

Some(Self::from_inner(poly))
}

/// Gets an image at any index for the shared key. This can't be used for much other than
/// checking whether `Point` is the correct share image at a certain index. This can be useful
/// when you load in a share backup and want to check that it's correct.
///
/// To verify a signature share for certain share you should use [`verification_share`] (which
/// contains a share image).
///
/// [`verification_share`]: Self::verification_share
pub fn share_image(&self, index: PartyIndex) -> Point<NonNormal, Public, Zero> {
poly::point::eval(&self.point_polynomial, index)
}
}

impl SharedKey<Normal> {
Expand Down
17 changes: 17 additions & 0 deletions schnorr_fun/src/libsecp_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,20 @@ mod v0_29 {
}
}
}

#[cfg(feature = "libsecp_compat_0_30")]
mod v0_30 {
use secp256kfun::secp256k1_0_30::schnorr;

impl From<crate::Signature> for schnorr::Signature {
fn from(sig: crate::Signature) -> Self {
schnorr::Signature::from_byte_array(sig.to_bytes())
}
}

impl From<schnorr::Signature> for crate::Signature {
fn from(sig: schnorr::Signature) -> Self {
crate::Signature::from_bytes(*sig.as_ref()).unwrap()
}
}
}
6 changes: 2 additions & 4 deletions schnorr_fun/tests/against_c_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ proptest! {
) {
let secp = &*SECP;
let keypair = secp256k1::Keypair::from_secret_key(secp, &key.into());
let secp_msg = secp256k1::Message::from_digest_slice(&msg).unwrap();
let sig = secp.sign_schnorr_no_aux_rand(&secp_msg, &keypair);
let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair);
let schnorr = Schnorr::<Sha256,Bip340NoAux>::default();
let fun_keypair = schnorr.new_keypair(key);
let fun_msg = Message::<Public>::raw(&msg);
Expand All @@ -79,8 +78,7 @@ proptest! {
let secp = &*SECP;
let keypair = secp256k1::Keypair::from_secret_key(secp, &key.into());
let fun_pk = secp256k1::XOnlyPublicKey::from_keypair(&keypair).0.into();
let secp_msg = secp256k1::Message::from_digest_slice(&msg).unwrap();
let sig = secp.sign_schnorr_with_aux_rand(&secp_msg, &keypair, &aux_rand);
let sig = secp.sign_schnorr_with_aux_rand(&msg, &keypair, &aux_rand);
let schnorr = Schnorr::<Sha256,_>::verify_only();
let fun_msg = Message::<Public>::raw(&msg);
prop_assert!(schnorr.verify(&fun_pk, fun_msg, &sig.into()));
Expand Down
6 changes: 5 additions & 1 deletion secp256kfun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bincode = { version = "2.0.0-rc.3", optional = true, default-features = false, f
secp256k1_0_27 = { package = "secp256k1", version = "0.27", optional = true, default-features = false }
secp256k1_0_28 = { package = "secp256k1", version = "0.28", optional = true, default-features = false }
secp256k1_0_29 = { package = "secp256k1", version = "0.29", optional = true, default-features = false }
secp256k1_0_30 = { package = "secp256k1", version = "0.30", optional = true, default-features = false }


[dev-dependencies]
Expand All @@ -43,14 +44,15 @@ wasm-bindgen-test = "0.3"

[features]
default = ["std"]
libsecp_compat = ["libsecp_compat_0_29"]
libsecp_compat = ["libsecp_compat_0_30"]
alloc = [
"serde?/alloc",
"digest/alloc",
"bincode?/alloc",
"secp256k1_0_27?/alloc",
"secp256k1_0_28?/alloc",
"secp256k1_0_29?/alloc",
"secp256k1_0_30?/alloc"
]
std = ["alloc", "subtle/std", "digest/std", "bincode?/std", "secp256k1_0_27?/std", "secp256k1_0_28?/std"]
serde = [
Expand All @@ -59,11 +61,13 @@ serde = [
"secp256k1_0_27?/serde",
"secp256k1_0_28?/serde",
"secp256k1_0_29?/serde",
"secp256k1_0_30?/serde"
]

libsecp_compat_0_27 = [ "dep:secp256k1_0_27" ]
libsecp_compat_0_28 = [ "dep:secp256k1_0_28" ]
libsecp_compat_0_29 = [ "dep:secp256k1_0_29" ]
libsecp_compat_0_30 = [ "dep:secp256k1_0_30" ]


[[bench]]
Expand Down
6 changes: 5 additions & 1 deletion secp256kfun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@ pub extern crate secp256k1_0_28;
/// Re-export `secp256k1`
pub extern crate secp256k1_0_29;

#[cfg(feature = "libsecp_compat_0_30")]
/// Re-export `secp256k1`
pub extern crate secp256k1_0_30;

#[cfg(feature = "libsecp_compat")]
pub use secp256k1_0_29 as secp256k1;
pub use secp256k1_0_30 as secp256k1;

/// Convenience module to import the most frequently used tools
pub mod prelude {
Expand Down
103 changes: 103 additions & 0 deletions secp256kfun/src/libsecp_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,109 @@ mod v0_29 {



#[test]
fn scalar_roundtrip(scalar in any::<Scalar<Public, Zero>>()) {
let secp_scalar = secp256k1::Scalar::from(scalar);
let rt_scalar = Scalar::from(secp_scalar);
assert_eq!(rt_scalar, scalar);
}
}
}
}

#[cfg(feature = "libsecp_compat_0_30")]
mod v0_30 {
use crate::{marker::*, Point, Scalar};
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
use secp256k1_0_30 as secp256k1;

impl From<Scalar> for SecretKey {
fn from(scalar: Scalar) -> Self {
SecretKey::from_byte_array(&scalar.to_bytes()).unwrap()
}
}

impl From<SecretKey> for Scalar {
fn from(sk: SecretKey) -> Self {
Scalar::from_slice(&sk[..])
.unwrap()
.non_zero()
.expect("SecretKey is never zero")
}
}

impl<Z> From<Scalar<Public, Z>> for secp256k1::Scalar {
fn from(value: Scalar<Public, Z>) -> Self {
secp256k1::Scalar::from_be_bytes(value.to_bytes()).unwrap()
}
}

impl From<secp256k1::Scalar> for Scalar<Public, Zero> {
fn from(value: secp256k1::Scalar) -> Self {
Scalar::from_bytes(value.to_be_bytes()).unwrap()
}
}

impl From<PublicKey> for Point {
fn from(pk: PublicKey) -> Self {
Point::<Normal, Public, NonZero>::from_bytes(pk.serialize()).unwrap()
}
}

impl From<Point> for PublicKey {
fn from(pk: Point) -> Self {
PublicKey::from_slice(pk.to_bytes().as_ref()).unwrap()
}
}

impl From<Point<EvenY>> for XOnlyPublicKey {
fn from(point: Point<EvenY>) -> Self {
XOnlyPublicKey::from_byte_array(&point.to_xonly_bytes()).unwrap()
}
}

impl From<XOnlyPublicKey> for Point<EvenY> {
fn from(pk: XOnlyPublicKey) -> Self {
Point::from_xonly_bytes(pk.serialize()).unwrap()
}
}

#[cfg(test)]
mod test {
use super::*;
use core::str::FromStr;
#[cfg(feature = "proptest")]
use proptest::prelude::*;

#[test]
fn public_key() {
let pk = PublicKey::from_str("0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8").unwrap();
let point = Point::from(pk);
assert_eq!(pk.serialize().as_ref(), point.to_bytes().as_ref());
}

#[cfg(feature = "proptest")]
proptest! {

#[test]
fn prop_public_key(first_byte in 0u8..10, x_bytes in any::<[u8;32]>()) {
let mut bytes = [0u8;33];
bytes[0] = first_byte;
bytes[1..33].copy_from_slice(&x_bytes[..]);
let pk = PublicKey::from_slice(&bytes[..]).ok();
let point = Point::<_,Public, >::from_bytes(bytes);
assert_eq!(pk.map(|pk| pk.serialize()), point.map(|point| point.to_bytes()));
}

#[test]
fn prop_secret_key(bytes in any::<[u8;32]>()) {
let sk = SecretKey::from_slice(&bytes[..]).unwrap();
let scalar = Scalar::from(sk);
assert_eq!(&sk[..], scalar.to_bytes().as_ref());
}



#[test]
fn scalar_roundtrip(scalar in any::<Scalar<Public, Zero>>()) {
let secp_scalar = secp256k1::Scalar::from(scalar);
Expand Down
Loading