Skip to content

Commit

Permalink
Use patched recover_from_prehash
Browse files Browse the repository at this point in the history
  • Loading branch information
mohanson committed Jul 18, 2024
1 parent 762265b commit f462869
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion checksums.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e6c62bda407981adb924ccc629a23368c41c896d9cc339308b7f7df7f971b0b4 build/release/ccc-btc-lock
1fc1af4aae068ffbf3efcc4bcfa80555882b3def1463ed2c33d5781056edf64f build/release/ccc-btc-lock
6 changes: 3 additions & 3 deletions contracts/ccc-btc-lock/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::error::Error;
use alloc::vec::Vec;
use ckb_lock_helper::{generate_sighash_all, println_hex};
use ckb_lock_helper::{generate_sighash_all, println_hex, secp256k1_patch::recover_from_prehash};
use ckb_std::{
ckb_constants::Source,
high_level::{load_script, load_witness_args},
};
use k256::ecdsa::{RecoveryId, Signature, VerifyingKey};
use k256::ecdsa::{RecoveryId, Signature};
use ripemd::{Digest, Ripemd160};
use sha2::Sha256;

Expand Down Expand Up @@ -72,7 +72,7 @@ pub fn entry() -> Result<(), Error> {
};
let rec_id = RecoveryId::try_from(rec_id).map_err(|_| Error::InvalidRecoverId)?;
let sig = Signature::from_slice(&sig_raw[1..]).map_err(|_| Error::WrongSignatureFormat)?;
let pubkey_result = VerifyingKey::recover_from_prehash(&digest_hash, &sig, rec_id)
let pubkey_result = recover_from_prehash(&digest_hash, &sig, rec_id)
.map_err(|_| Error::CanNotRecover)?
.to_sec1_bytes();
assert!(pubkey_result.len() == 33);
Expand Down
3 changes: 2 additions & 1 deletion crates/ckb-lock-helper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
blake2b-ref = "0.3.1"
ckb-std = { version = "0.15", features = ["allocator", "ckb-types", "calc-hash"]}
hex = { version = "0.4", default-features = false, features = ["alloc"]}
blake2b-ref = "0.3.1"
k256 = { version = "=0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "alloc"] }
1 change: 1 addition & 0 deletions crates/ckb-lock-helper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
extern crate alloc;
pub mod blake2b;
pub mod error;
pub mod secp256k1_patch;

use crate::blake2b::new_blake2b_stat;
use crate::error::Error;
Expand Down
52 changes: 52 additions & 0 deletions crates/ckb-lock-helper/src/secp256k1_patch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use k256::ecdsa::hazmat::bits2field;
use k256::ecdsa::signature::Result;
use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey};
use k256::elliptic_curve::bigint::CheckedAdd;
use k256::elliptic_curve::ops::{Invert, LinearCombination, Reduce};
use k256::elliptic_curve::point::DecompressPoint;
use k256::elliptic_curve::{AffinePoint, Curve, FieldBytesEncoding, PrimeField, ProjectivePoint};
use k256::{Scalar, Secp256k1};

/// Equivalent to VerifyingKey::recover_from_prehash but the final verification process is removed.
/// Ref: https://github.com/RustCrypto/signatures/issues/751.
#[allow(non_snake_case)]
pub fn recover_from_prehash(
prehash: &[u8],
signature: &Signature,
recovery_id: RecoveryId,
) -> Result<VerifyingKey> {
let (r, s) = signature.split_scalars();
let z = <Scalar as Reduce<<Secp256k1 as k256::elliptic_curve::Curve>::Uint>>::reduce_bytes(
&bits2field::<Secp256k1>(prehash)?,
);

let mut r_bytes = r.to_repr();
if recovery_id.is_x_reduced() {
match Option::<<Secp256k1 as k256::elliptic_curve::Curve>::Uint>::from(
<Secp256k1 as k256::elliptic_curve::Curve>::Uint::decode_field_bytes(&r_bytes)
.checked_add(&Secp256k1::ORDER),
) {
Some(restored) => r_bytes = restored.encode_field_bytes(),
// No reduction should happen here if r was reduced
None => return Err(Error::new()),
};
}
let R = AffinePoint::<Secp256k1>::decompress(&r_bytes, u8::from(recovery_id.is_y_odd()).into());

if R.is_none().into() {
return Err(Error::new());
}

let R = ProjectivePoint::<Secp256k1>::from(R.unwrap());
let r_inv = *r.invert();
let u1 = -(r_inv * z);
let u2 = r_inv * *s;
let pk = ProjectivePoint::<Secp256k1>::lincomb(
&ProjectivePoint::<Secp256k1>::GENERATOR,
&u1,
&R,
&u2,
);
let vk = VerifyingKey::from_affine(pk.into())?;
Ok(vk)
}

0 comments on commit f462869

Please sign in to comment.