Skip to main content

karyon_core/crypto/
key_pair.rs

1use ed25519_dalek::{Signer as _, Verifier as _};
2use rand::RngCore;
3
4use crate::{error::Error, Result};
5
6/// key cryptography type
7pub enum KeyPairType {
8    Ed25519,
9}
10
11/// A Secret key
12pub struct SecretKey(pub Vec<u8>);
13
14#[derive(Clone)]
15pub enum KeyPair {
16    Ed25519(Ed25519KeyPair),
17}
18
19impl KeyPair {
20    /// Generate a new random keypair.
21    pub fn generate(kp_type: &KeyPairType) -> Self {
22        match kp_type {
23            KeyPairType::Ed25519 => Self::Ed25519(Ed25519KeyPair::generate()),
24        }
25    }
26
27    /// Sign a message using the private key.
28    pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
29        match self {
30            KeyPair::Ed25519(kp) => kp.sign(msg),
31        }
32    }
33
34    /// Get the public key of this keypair.
35    pub fn public(&self) -> PublicKey {
36        match self {
37            KeyPair::Ed25519(kp) => kp.public(),
38        }
39    }
40
41    /// Get the secret key of this keypair.
42    pub fn secret(&self) -> SecretKey {
43        match self {
44            KeyPair::Ed25519(kp) => kp.secret(),
45        }
46    }
47}
48
49/// An extension trait, adding essential methods to all [`KeyPair`] types.
50trait KeyPairExt {
51    /// Sign a message using the private key.
52    fn sign(&self, msg: &[u8]) -> Vec<u8>;
53
54    /// Get the public key of this keypair.
55    fn public(&self) -> PublicKey;
56
57    /// Get the secret key of this keypair.
58    fn secret(&self) -> SecretKey;
59}
60
61#[derive(Clone)]
62pub struct Ed25519KeyPair(ed25519_dalek::SigningKey);
63
64impl Ed25519KeyPair {
65    fn generate() -> Self {
66        // XXX: switch back to SigningKey::generate(&mut OsRng) once
67        // ed25519-dalek 3.0 stable is released. 2.2 pins rand_core 0.6 which
68        // is incompatible with rand 0.9's rand_core 0.9, so we fill the secret
69        // bytes ourselves and load via from_bytes.
70        let mut secret = [0u8; 32];
71        rand::rng().fill_bytes(&mut secret);
72        Self(ed25519_dalek::SigningKey::from_bytes(&secret))
73    }
74}
75
76impl KeyPairExt for Ed25519KeyPair {
77    fn sign(&self, msg: &[u8]) -> Vec<u8> {
78        self.0.sign(msg).to_bytes().to_vec()
79    }
80
81    fn public(&self) -> PublicKey {
82        PublicKey::Ed25519(Ed25519PublicKey(self.0.verifying_key()))
83    }
84
85    fn secret(&self) -> SecretKey {
86        SecretKey(self.0.to_bytes().to_vec())
87    }
88}
89
90#[derive(Debug)]
91pub enum PublicKey {
92    Ed25519(Ed25519PublicKey),
93}
94
95impl PublicKey {
96    pub fn from_bytes(kp_type: &KeyPairType, pk: &[u8]) -> Result<Self> {
97        match kp_type {
98            KeyPairType::Ed25519 => Ok(Self::Ed25519(Ed25519PublicKey::from_bytes(pk)?)),
99        }
100    }
101
102    pub fn as_bytes(&self) -> &[u8] {
103        match self {
104            Self::Ed25519(pk) => pk.as_bytes(),
105        }
106    }
107
108    /// Verify a signature on a message with this public key.
109    pub fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
110        match self {
111            Self::Ed25519(pk) => pk.verify(msg, signature),
112        }
113    }
114}
115
116/// An extension trait, adding essential methods to all [`PublicKey`] types.
117trait PublicKeyExt {
118    fn as_bytes(&self) -> &[u8];
119
120    /// Verify a signature on a message with this public key.
121    fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()>;
122}
123
124#[derive(Debug)]
125pub struct Ed25519PublicKey(ed25519_dalek::VerifyingKey);
126
127impl Ed25519PublicKey {
128    pub fn from_bytes(pk: &[u8]) -> Result<Self> {
129        let pk_bytes: [u8; 32] = pk
130            .try_into()
131            .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 32]".to_string()))?;
132
133        Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(&pk_bytes)?))
134    }
135}
136
137impl PublicKeyExt for Ed25519PublicKey {
138    fn as_bytes(&self) -> &[u8] {
139        self.0.as_bytes()
140    }
141
142    fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
143        let sig_bytes: [u8; 64] = signature
144            .try_into()
145            .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 64]".to_string()))?;
146        self.0
147            .verify(msg, &ed25519_dalek::Signature::from_bytes(&sig_bytes))?;
148        Ok(())
149    }
150}