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

use std::borrow::Cow;
use std::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::Owned(self.as_ref().to_vec())
    }
}

/// 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)?))
    }
}

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

impl fmt::Debug for Ed25519SigningKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Ed25519 secret key: {:?}", self.as_ref().as_ref())
    }
}

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()
    }
}

/// 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-dalek` 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 keypair = KeyPair::from_seed(Seed::new(rng.gen()));
        (
            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()
    }
}