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
use ed25519_compact::{KeyPair, PublicKey, SecretKey, Seed, Signature};
use rand_core::{CryptoRng, RngCore};

use std::{borrow::Cow, fmt};

use crate::{Algorithm, AlgorithmSignature, Renamed};

impl AlgorithmSignature for Signature {
    fn try_from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
        let mut signature = [0u8; Signature::BYTES];
        if bytes.len() != signature.len() {
            return Err(ed25519_compact::Error::SignatureMismatch.into());
        }
        signature.copy_from_slice(bytes);
        Ok(Self::new(signature))
    }

    fn as_bytes(&self) -> Cow<[u8]> {
        Cow::Borrowed(self.as_ref())
    }
}

/// A verification key.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Ed25519VerifyingKey(PublicKey);

impl AsRef<PublicKey> for Ed25519VerifyingKey {
    fn as_ref(&self) -> &PublicKey {
        &self.0
    }
}

impl Ed25519VerifyingKey {
    /// Create a verification key from a slice.
    pub fn from_slice(raw: &[u8]) -> anyhow::Result<Ed25519VerifyingKey> {
        Ok(Ed25519VerifyingKey(PublicKey::from_slice(raw)?))
    }

    /// Return the key as raw bytes.
    pub fn as_bytes(&self) -> Cow<[u8]> {
        Cow::Borrowed(self.0.as_ref())
    }
}

/// A signing key.
pub struct Ed25519SigningKey(SecretKey);

impl fmt::Debug for Ed25519SigningKey {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_tuple("Ed25519SigningKey")
            .field(&self.0.as_ref())
            .finish()
    }
}

impl AsRef<SecretKey> for Ed25519SigningKey {
    fn as_ref(&self) -> &SecretKey {
        &self.0
    }
}

impl Ed25519SigningKey {
    /// Create a signing key from a slice.
    pub fn from_slice(raw: &[u8]) -> anyhow::Result<Ed25519SigningKey> {
        Ok(Ed25519SigningKey(SecretKey::from_slice(raw)?))
    }

    /// Convert a signing key to a verification key.
    pub fn to_verifying_key(&self) -> PublicKey {
        self.as_ref().public_key()
    }

    /// Return the key as raw bytes.
    pub fn as_bytes(&self) -> Cow<[u8]> {
        Cow::Borrowed(self.0.as_ref())
    }
}

/// Integrity algorithm using digital signatures on the Ed25519 elliptic curve.
///
/// The name of the algorithm is specified as `EdDSA` as per the [IANA registry].
/// Use `with_specific_name()` to switch to non-standard `Ed25519`.
///
/// *This type is available if the crate is built with the `ed25519-compact` feature.*
///
/// [IANA registry]: https://www.iana.org/assignments/jose/jose.xhtml
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Ed25519;

impl Ed25519 {
    /// Creates an algorithm instance with the algorithm name specified as `Ed25519`.
    /// This is a non-standard name, but it is used in some apps.
    pub fn with_specific_name() -> Renamed<Self> {
        Renamed::new(Self, "Ed25519")
    }

    /// Generate a new key pair.
    pub fn generate<R: CryptoRng + RngCore>(
        &self,
        rng: &mut R,
    ) -> (Ed25519SigningKey, Ed25519VerifyingKey) {
        let mut seed = [0u8; Seed::BYTES];
        rng.fill_bytes(&mut seed);
        let keypair = KeyPair::from_seed(Seed::new(seed));
        (
            Ed25519SigningKey(keypair.sk),
            Ed25519VerifyingKey(keypair.pk),
        )
    }
}

impl Algorithm for Ed25519 {
    type SigningKey = Ed25519SigningKey;
    type VerifyingKey = Ed25519VerifyingKey;
    type Signature = Signature;

    fn name(&self) -> Cow<'static, str> {
        Cow::Borrowed("EdDSA")
    }

    fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
        signing_key.as_ref().sign(message, Some(Default::default()))
    }

    fn verify_signature(
        &self,
        signature: &Self::Signature,
        verifying_key: &Self::VerifyingKey,
        message: &[u8],
    ) -> bool {
        verifying_key.as_ref().verify(message, signature).is_ok()
    }
}