aboutsummaryrefslogtreecommitdiff
path: root/core/src/crypto/key_pair.rs
blob: a7a8eafb0e45dfbe05a8a15228a4cadd702c0cb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use ed25519_dalek::{Signer as _, Verifier as _};
use rand::rngs::OsRng;

use crate::{error::Error, Result};

/// key cryptography type
pub enum KeyPairType {
    Ed25519,
}

/// A Secret key
pub struct SecretKey(pub Vec<u8>);

#[derive(Clone)]
pub enum KeyPair {
    Ed25519(Ed25519KeyPair),
}

impl KeyPair {
    /// Generate a new random keypair.
    pub fn generate(kp_type: &KeyPairType) -> Self {
        match kp_type {
            KeyPairType::Ed25519 => Self::Ed25519(Ed25519KeyPair::generate()),
        }
    }

    /// Sign a message using the private key.
    pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
        match self {
            KeyPair::Ed25519(kp) => kp.sign(msg),
        }
    }

    /// Get the public key of this keypair.
    pub fn public(&self) -> PublicKey {
        match self {
            KeyPair::Ed25519(kp) => kp.public(),
        }
    }

    /// Get the secret key of this keypair.
    pub fn secret(&self) -> SecretKey {
        match self {
            KeyPair::Ed25519(kp) => kp.secret(),
        }
    }
}

/// An extension trait, adding essential methods to all [`KeyPair`] types.
trait KeyPairExt {
    /// Sign a message using the private key.
    fn sign(&self, msg: &[u8]) -> Vec<u8>;

    /// Get the public key of this keypair.
    fn public(&self) -> PublicKey;

    /// Get the secret key of this keypair.
    fn secret(&self) -> SecretKey;
}

#[derive(Clone)]
pub struct Ed25519KeyPair(ed25519_dalek::SigningKey);

impl Ed25519KeyPair {
    fn generate() -> Self {
        Self(ed25519_dalek::SigningKey::generate(&mut OsRng))
    }
}

impl KeyPairExt for Ed25519KeyPair {
    fn sign(&self, msg: &[u8]) -> Vec<u8> {
        self.0.sign(msg).to_bytes().to_vec()
    }

    fn public(&self) -> PublicKey {
        PublicKey::Ed25519(Ed25519PublicKey(self.0.verifying_key()))
    }

    fn secret(&self) -> SecretKey {
        SecretKey(self.0.to_bytes().to_vec())
    }
}

#[derive(Debug)]
pub enum PublicKey {
    Ed25519(Ed25519PublicKey),
}

impl PublicKey {
    pub fn from_bytes(kp_type: &KeyPairType, pk: &[u8]) -> Result<Self> {
        match kp_type {
            KeyPairType::Ed25519 => Ok(Self::Ed25519(Ed25519PublicKey::from_bytes(pk)?)),
        }
    }

    pub fn as_bytes(&self) -> &[u8] {
        match self {
            Self::Ed25519(pk) => pk.as_bytes(),
        }
    }

    /// Verify a signature on a message with this public key.
    pub fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
        match self {
            Self::Ed25519(pk) => pk.verify(msg, signature),
        }
    }
}

/// An extension trait, adding essential methods to all [`PublicKey`] types.
trait PublicKeyExt {
    fn as_bytes(&self) -> &[u8];

    /// Verify a signature on a message with this public key.
    fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()>;
}

#[derive(Debug)]
pub struct Ed25519PublicKey(ed25519_dalek::VerifyingKey);

impl Ed25519PublicKey {
    pub fn from_bytes(pk: &[u8]) -> Result<Self> {
        let pk_bytes: [u8; 32] = pk
            .try_into()
            .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 32]"))?;

        Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(&pk_bytes)?))
    }
}

impl PublicKeyExt for Ed25519PublicKey {
    fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }

    fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
        let sig_bytes: [u8; 64] = signature
            .try_into()
            .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 64]"))?;
        self.0
            .verify(msg, &ed25519_dalek::Signature::from_bytes(&sig_bytes))?;
        Ok(())
    }
}