use k256::elliptic_curve::PrimeField;
use k256::{NonZeroScalar, ProjectivePoint, PublicKey, Scalar};
use nostr::prelude::FromBech32;
use rand::{CryptoRng, RngCore};
use crate::types::{normalize_hex, Error};
pub fn hex_to_point(pubkey_hex: &str) -> Result<ProjectivePoint, Error> {
let hex_norm = normalize_hex(pubkey_hex)?;
let point_bytes = match hex_norm.len() {
64 => hex::decode(format!("02{}", hex_norm))?,
66 => {
if !hex_norm.starts_with("02") && !hex_norm.starts_with("03") {
return Err(Error::PublicKeyFormat(format!(
"Invalid prefix: {}",
&hex_norm[..2]
)));
}
hex::decode(&hex_norm)?
}
130 => {
if !hex_norm.starts_with("04") {
return Err(Error::PublicKeyFormat(format!(
"Invalid prefix: {}",
&hex_norm[..2]
)));
}
hex::decode(&hex_norm)?
}
_ => {
return Err(Error::PublicKeyFormat(format!(
"Invalid length: {}",
hex_norm.len()
)));
}
};
let public_key = PublicKey::from_sec1_bytes(&point_bytes)
.map_err(|e| Error::PublicKeyFormat(format!("SEC1 parse error: {}", e)))?;
Ok(public_key.to_projective())
}
pub fn random_non_zero_scalar(mut rng: impl RngCore + CryptoRng) -> NonZeroScalar {
NonZeroScalar::random(&mut rng)
}
pub fn parse_secret_key(key_input: &str) -> Result<Scalar, Error> {
if key_input.starts_with("nsec1") {
let sk = nostr::SecretKey::from_bech32(key_input)
.map_err(|e| Error::SecretKeyFormat(format!("Bech32 parse error: {}", e)))?;
let field_bytes = k256::FieldBytes::from(sk.to_secret_bytes());
let maybe_scalar = Scalar::from_repr_vartime(field_bytes);
if let Some(scalar) = maybe_scalar {
Ok(scalar)
} else {
Err(Error::InvalidScalarEncoding)
}
} else {
crate::types::hex_to_scalar(key_input)
}
}
pub fn parse_public_key(key_input: &str) -> Result<ProjectivePoint, Error> {
if key_input.starts_with("npub1") {
let pk = nostr::PublicKey::from_bech32(key_input)
.map_err(|e| Error::PublicKeyFormat(format!("Bech32 parse error: {}", e)))?;
let hex_pk = pk.to_hex();
hex_to_point(&hex_pk) } else {
hex_to_point(key_input)
}
}