use k256::elliptic_curve::FieldBytes;
use k256::elliptic_curve::bigint::U256;
use k256::elliptic_curve::group::GroupEncoding;
use k256::elliptic_curve::ops::Reduce;
use k256::{AffinePoint, ProjectivePoint, Scalar, Secp256k1};
use sha2::{Digest, Sha256};
use std::sync::Arc;
use crate::group::Group;
use num_bigint::BigInt;
#[derive(Debug, Clone)]
pub struct Secp256k1Group {
order: BigInt,
}
impl Secp256k1Group {
pub fn new() -> Arc<Self> {
let order_bytes: [u8; 32] = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48,
0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41,
];
let order = BigInt::from_bytes_be(num_bigint::Sign::Plus, &order_bytes);
Arc::new(Secp256k1Group { order })
}
}
impl Group for Secp256k1Group {
type Scalar = Scalar;
type Element = AffinePoint;
fn order(&self) -> &Self::Scalar {
static ORDER_PLACEHOLDER: Scalar = Scalar::ONE;
&ORDER_PLACEHOLDER
}
fn subgroup_order(&self) -> &Self::Scalar {
static ORDER_PLACEHOLDER: Scalar = Scalar::ONE;
&ORDER_PLACEHOLDER
}
fn generator(&self) -> Self::Element {
AffinePoint::GENERATOR
}
fn subgroup_generator(&self) -> Self::Element {
AffinePoint::GENERATOR
}
fn identity(&self) -> Self::Element {
AffinePoint::IDENTITY
}
fn exp(
&self,
base: &Self::Element,
scalar: &Self::Scalar,
) -> Self::Element {
(ProjectivePoint::from(*base) * scalar).into()
}
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
(ProjectivePoint::from(*a) + ProjectivePoint::from(*b)).into()
}
fn scalar_inverse(&self, x: &Self::Scalar) -> Option<Self::Scalar> {
x.invert().into()
}
fn element_inverse(&self, x: &Self::Element) -> Option<Self::Element> {
Some((-ProjectivePoint::from(*x)).into())
}
fn hash_to_scalar(&self, data: &[u8]) -> Self::Scalar {
let hash = Sha256::digest(data);
let mut field_bytes = FieldBytes::<Secp256k1>::default();
let hash_len = hash.len().min(field_bytes.len());
let field_bytes_len = field_bytes.len();
field_bytes[(field_bytes_len - hash_len)..]
.copy_from_slice(&hash[..hash_len]);
Scalar::reduce(U256::from_be_slice(field_bytes.as_ref()))
}
fn element_to_bytes(&self, elem: &Self::Element) -> Vec<u8> {
elem.to_bytes().to_vec()
}
fn bytes_to_element(&self, bytes: &[u8]) -> Option<Self::Element> {
if bytes.len() != 33 {
return None;
}
let mut array = [0u8; 33];
array.copy_from_slice(bytes);
let ct_result = AffinePoint::from_bytes((&array).into());
if bool::from(ct_result.is_some()) {
Some(ct_result.unwrap())
} else {
None
}
}
fn scalar_to_bytes(&self, scalar: &Self::Scalar) -> Vec<u8> {
scalar.to_bytes().to_vec()
}
fn generate_private_key(&self) -> Self::Scalar {
let mut bytes = [0u8; 32];
for byte in &mut bytes {
*byte = rand::random::<u8>();
}
Scalar::reduce(U256::from_be_slice(&bytes))
}
fn generate_public_key(&self, private_key: &Self::Scalar) -> Self::Element {
(AffinePoint::GENERATOR * private_key).into()
}
fn scalar_mul(&self, a: &Self::Scalar, b: &Self::Scalar) -> Self::Scalar {
a * b
}
fn scalar_sub(&self, a: &Self::Scalar, b: &Self::Scalar) -> Self::Scalar {
a - b
}
}
impl Secp256k1Group {
pub fn order_as_bigint(&self) -> &BigInt {
&self.order
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_secp256k1_group_new() {
let group = Secp256k1Group::new();
let order = group.order_as_bigint();
assert_ne!(*order, num_bigint::BigInt::from(1u32));
assert!(*order > num_bigint::BigInt::from(1u64) << 250);
}
#[test]
fn test_generate_keypair() {
let group = Secp256k1Group::new();
let privkey = group.generate_private_key();
let pubkey = group.generate_public_key(&privkey);
assert_ne!(pubkey, AffinePoint::IDENTITY);
}
#[test]
fn test_exp() {
let group = Secp256k1Group::new();
let g = group.generator();
let one = Scalar::ONE;
assert_eq!(group.exp(&g, &one), g);
assert_eq!(group.exp(&g, &Scalar::ZERO), group.identity());
}
#[test]
fn test_mul() {
let group = Secp256k1Group::new();
let g = group.generator();
let g_plus_g = group.mul(&g, &g);
let two_g = group.exp(&g, &Scalar::from(2u32));
assert_eq!(g_plus_g, two_g);
}
#[test]
fn test_scalar_inverse() {
let group = Secp256k1Group::new();
let x = Scalar::from(5u32);
let inv = group.scalar_inverse(&x).unwrap();
let result = x * inv;
assert_eq!(result, Scalar::ONE);
}
#[test]
fn test_element_inverse() {
let group = Secp256k1Group::new();
let g = group.generator();
let neg_g = group.element_inverse(&g).unwrap();
let result = group.mul(&g, &neg_g);
assert_eq!(result, AffinePoint::IDENTITY);
}
#[test]
fn test_hash_to_scalar() {
let group = Secp256k1Group::new();
let data = b"test data";
let scalar = group.hash_to_scalar(data);
assert_ne!(scalar, Scalar::ZERO);
}
#[test]
fn test_serialize_roundtrip() {
let group = Secp256k1Group::new();
let g = group.generator();
let bytes = group.element_to_bytes(&g);
assert_eq!(bytes.len(), 33);
let restored = group.bytes_to_element(&bytes).unwrap();
assert_eq!(g, restored);
}
#[test]
fn test_scalar_serialize_roundtrip() {
let group = Secp256k1Group::new();
let scalar = Scalar::from(42u32);
let bytes = group.scalar_to_bytes(&scalar);
assert_eq!(bytes.len(), 32);
}
}