keri_core/keys/
mod.rs

1use ed25519_dalek::{Signer, Verifier};
2use k256::ecdsa::{signature::Signer as EcdsaSigner, Signature as EcdsaSignature, SigningKey};
3use k256::ecdsa::{signature::Verifier as EcdsaVerifier, VerifyingKey};
4use serde_derive::{Deserialize, Serialize};
5use zeroize::Zeroize;
6
7#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
8pub enum KeysError {
9    #[error("ED25519Dalek key error")]
10    Ed25519DalekKeyError,
11    #[error("ED25519Dalek signature error")]
12    Ed25519DalekSignatureError,
13    #[error("ECDSA signature error")]
14    EcdsaError,
15}
16
17impl From<ed25519_dalek::SignatureError> for KeysError {
18    fn from(_: ed25519_dalek::SignatureError) -> Self {
19        KeysError::Ed25519DalekSignatureError
20    }
21}
22
23#[derive(
24    Debug, Clone, PartialEq, Hash, Eq, Default, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize,
25)]
26#[rkyv(compare(PartialEq), derive(Debug))]
27pub struct PublicKey {
28    pub public_key: Vec<u8>,
29}
30
31impl PublicKey {
32    pub fn new(key: Vec<u8>) -> Self {
33        PublicKey {
34            public_key: key.to_vec(),
35        }
36    }
37
38    pub fn key(&self) -> Vec<u8> {
39        self.public_key.clone()
40    }
41
42    pub fn verify_ed(&self, msg: &[u8], sig: &[u8]) -> bool {
43        let binding = self.key();
44        let key: &[u8; 32] = match binding.as_slice().try_into() {
45            Ok(arr) => arr,
46            Err(_) => panic!("Vector does not have exactly 32 elements"),
47        };
48        if let Ok(key) = ed25519_dalek::VerifyingKey::from_bytes(key) {
49            use arrayref::array_ref;
50            if sig.len() != 64 {
51                return false;
52            }
53            let sig = ed25519_dalek::Signature::from(array_ref!(sig, 0, 64).to_owned());
54            match key.verify(msg, &sig) {
55                Ok(()) => true,
56                Err(_) => false,
57            }
58        } else {
59            false
60        }
61    }
62
63    pub fn verify_ecdsa(&self, msg: &[u8], sig: &[u8]) -> bool {
64        match VerifyingKey::from_sec1_bytes(&self.key()) {
65            Ok(k) => {
66                use k256::ecdsa::Signature;
67                if let Ok(sig) = Signature::try_from(sig) {
68                    match k.verify(msg, &sig) {
69                        Ok(()) => true,
70                        Err(_) => false,
71                    }
72                } else {
73                    false
74                }
75            }
76            Err(_) => false,
77        }
78    }
79}
80
81#[derive(Debug, PartialEq, Clone)]
82pub struct PrivateKey {
83    key: Vec<u8>,
84}
85
86impl PrivateKey {
87    pub fn new(key: Vec<u8>) -> Self {
88        Self { key }
89    }
90
91    pub fn sign_ecdsa(&self, msg: &[u8]) -> Result<Vec<u8>, KeysError> {
92        let sig: EcdsaSignature = EcdsaSigner::sign(
93            &SigningKey::from_bytes(&self.key).map_err(|_e| KeysError::Ed25519DalekKeyError)?,
94            msg,
95        );
96        Ok(sig.as_ref().to_vec())
97    }
98
99    pub fn sign_ed(&self, msg: &[u8]) -> Result<Vec<u8>, KeysError> {
100        let sk = ed25519_dalek::SigningKey::from_bytes(arrayref::array_ref![self.key, 0, 32]);
101
102        Ok(sk.sign(msg).to_vec())
103    }
104
105    pub fn key(&self) -> Vec<u8> {
106        self.key.clone()
107    }
108}
109
110impl Drop for PrivateKey {
111    fn drop(&mut self) {
112        self.key.zeroize()
113    }
114}
115
116#[test]
117fn libsodium_to_ed25519_dalek_compat() {
118    use ed25519_dalek::Signature;
119    use rand::rngs::OsRng;
120
121    let kp = ed25519_dalek::SigningKey::generate(&mut OsRng);
122
123    let msg = b"are libsodium and dalek compatible?";
124
125    let dalek_sig = kp.sign(msg);
126
127    use sodiumoxide::crypto::sign;
128
129    let sodium_pk = sign::ed25519::PublicKey::from_slice(&kp.verifying_key().to_bytes());
130    assert!(sodium_pk.is_some());
131    let sodium_pk = sodium_pk.unwrap();
132    let mut sodium_sk_concat = kp.to_bytes().to_vec();
133    sodium_sk_concat.append(&mut kp.verifying_key().to_bytes().to_vec().clone());
134    let sodium_sk = sign::ed25519::SecretKey::from_slice(&sodium_sk_concat);
135    assert!(sodium_sk.is_some());
136    let sodium_sk = sodium_sk.unwrap();
137
138    let sodium_sig = sign::sign(msg, &sodium_sk);
139
140    assert!(sign::verify_detached(
141        &sign::ed25519::Signature::from_bytes(&dalek_sig.to_bytes()).unwrap(),
142        msg,
143        &sodium_pk
144    ));
145
146    assert!(kp
147        .verify(
148            msg,
149            &Signature::from_bytes(&arrayref::array_ref!(sodium_sig, 0, 64).to_owned())
150        )
151        .is_ok());
152}