Skip to main content

confium_tc_frost_p256/
keys.rs

1//! Keypair generation for threshold P-256.
2
3use crate::scalar;
4use p256::{
5    AffinePoint, ProjectivePoint, Scalar,
6    ecdsa::{SigningKey, VerifyingKey},
7    elliptic_curve::sec1::ToSec1Point,
8};
9
10/// A P-256 keypair.
11#[derive(Debug, Clone)]
12pub struct Keypair {
13    /// Secret scalar.
14    pub secret_scalar: Scalar,
15    /// Public key (affine point).
16    pub public_key: AffinePoint,
17}
18
19impl Keypair {
20    /// Convert to `p256::ecdsa::SigningKey`.
21    pub fn to_signing_key(&self) -> SigningKey {
22        let bytes = scalar::scalar_to_bytes(&self.secret_scalar);
23        SigningKey::from_bytes((&bytes).into()).expect("scalar is in valid range")
24    }
25
26    /// Convert to `p256::ecdsa::VerifyingKey`.
27    pub fn to_verifying_key(&self) -> VerifyingKey {
28        VerifyingKey::from_affine(self.public_key).expect("public key is valid")
29    }
30}
31
32/// Generate a fresh random keypair.
33pub fn generate_keypair() -> Keypair {
34    let secret = loop {
35        let s = scalar::random_scalar();
36        if s != Scalar::ZERO {
37            break s;
38        }
39    };
40    let public = public_key_for(&secret);
41    Keypair {
42        secret_scalar: secret,
43        public_key: public,
44    }
45}
46
47/// Compute the public key for a given secret scalar.
48pub fn public_key_for(secret: &Scalar) -> AffinePoint {
49    let g = ProjectivePoint::GENERATOR;
50    let p = g * secret;
51    p.to_affine()
52}
53
54/// SEC1-encoded public key bytes (uncompressed, 65 bytes).
55pub fn public_key_sec1(affine: &AffinePoint) -> Vec<u8> {
56    affine.to_sec1_point(false).as_bytes().to_vec()
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn keypair_generation_is_unique() {
65        let k1 = generate_keypair();
66        let k2 = generate_keypair();
67        assert_ne!(k1.secret_scalar, k2.secret_scalar);
68        assert_ne!(k1.public_key, k2.public_key);
69    }
70
71    #[test]
72    fn secret_to_public_is_deterministic() {
73        let k = generate_keypair();
74        let pk_again = public_key_for(&k.secret_scalar);
75        assert_eq!(pk_again, k.public_key);
76    }
77
78    #[test]
79    fn public_key_sec1_is_65_bytes_uncompressed() {
80        let k = generate_keypair();
81        let bytes = public_key_sec1(&k.public_key);
82        assert_eq!(bytes.len(), 65);
83        assert_eq!(bytes[0], 0x04);
84    }
85}