mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-25 13:09:30 +00:00
59 lines
1.4 KiB
Rust
59 lines
1.4 KiB
Rust
|
use lazy_static::lazy_static;
|
||
|
|
||
|
use sha2::{Digest, Sha256};
|
||
|
|
||
|
use k256::{
|
||
|
elliptic_curve::{
|
||
|
ops::Reduce,
|
||
|
sec1::{Tag, ToEncodedPoint},
|
||
|
},
|
||
|
U256, Scalar, ProjectivePoint,
|
||
|
};
|
||
|
|
||
|
use bitcoin::XOnlyPublicKey;
|
||
|
|
||
|
use frost::{algorithm::Hram, curve::Secp256k1};
|
||
|
|
||
|
/// Get the x coordinate of a non-infinity, even point.
|
||
|
pub fn x(key: &ProjectivePoint) -> [u8; 32] {
|
||
|
let encoded = key.to_encoded_point(true);
|
||
|
assert_eq!(encoded.tag(), Tag::CompressedEvenY);
|
||
|
(*encoded.x().expect("point at infinity")).into()
|
||
|
}
|
||
|
|
||
|
pub fn x_only(key: &ProjectivePoint) -> XOnlyPublicKey {
|
||
|
XOnlyPublicKey::from_slice(&x(key)).unwrap()
|
||
|
}
|
||
|
|
||
|
pub fn make_even(mut key: ProjectivePoint) -> (ProjectivePoint, u64) {
|
||
|
let mut c = 0;
|
||
|
while key.to_encoded_point(true).tag() == Tag::CompressedOddY {
|
||
|
key += ProjectivePoint::GENERATOR;
|
||
|
c += 1;
|
||
|
}
|
||
|
(key, c)
|
||
|
}
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub struct BitcoinHram {}
|
||
|
|
||
|
lazy_static! {
|
||
|
static ref TAG_HASH: [u8; 32] = Sha256::digest(b"BIP0340/challenge").into();
|
||
|
}
|
||
|
|
||
|
#[allow(non_snake_case)]
|
||
|
impl Hram<Secp256k1> for BitcoinHram {
|
||
|
fn hram(R: &ProjectivePoint, A: &ProjectivePoint, m: &[u8]) -> Scalar {
|
||
|
let (R, _) = make_even(*R);
|
||
|
|
||
|
let mut data = Sha256::new();
|
||
|
data.update(*TAG_HASH);
|
||
|
data.update(*TAG_HASH);
|
||
|
data.update(x(&R));
|
||
|
data.update(x(A));
|
||
|
data.update(m);
|
||
|
|
||
|
Scalar::from_uint_reduced(U256::from_be_slice(&data.finalize()))
|
||
|
}
|
||
|
}
|