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
use p256::{
    ecdsa::{signature::RandomizedSigner, signature::Verifier as _, Signature, Signer, Verifier},
    elliptic_curve::Generate,
    PublicKey, SecretKey,
};
use rand_core::{CryptoRng, RngCore};

use std::borrow::Cow;
use std::convert::TryFrom;

use crate::error::ValidationError;
use crate::{Algorithm, AlgorithmSignature};

impl AlgorithmSignature for Signature {
    fn try_from_slice(slice: &[u8]) -> anyhow::Result<Self> {
        Signature::try_from(slice).map_err(|e| anyhow::anyhow!(e))
    }

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

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

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

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

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

/// A signing key.
#[derive(Debug)]
pub struct Es256kSigningKey(SecretKey);

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

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

    /// Convert a signing key to a verification key.
    pub fn to_verifying_key(&self) -> PublicKey {
        PublicKey::from_secret_key(&self.0, true).unwrap()
    }
}

/// Algorithm implementing elliptic curve digital signatures (ECDSA) on the p256 curve.
///
/// The algorithm does not fix the choice of the message digest algorithm; instead,
/// it is provided as a type parameter. SHA-256 is the default parameter value,
/// but it can be set to any cryptographically secure hash function with 32-byte output
/// (e.g., SHA3-256).
///
/// *This type is available if the crate is built with the `p256` feature.*
#[derive(Debug)]
pub struct Es256k<R: CryptoRng + RngCore> {
    rng: R,
}

impl<R: CryptoRng + RngCore> Es256k<R> {
    /// Create an Es256k structure that uses the provided RNG
    pub fn new(rng: R) -> Self {
        Es256k { rng }
    }
}

impl<R: CryptoRng + RngCore> Algorithm for Es256k<R> {
    type SigningKey = Es256kSigningKey;
    type VerifyingKey = Es256kVerifyingKey;
    type Signature = Signature;

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

    fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
        let signer = Signer::new(signing_key.as_ref()).unwrap();
        signer.sign_with_rng(&mut rand_core::OsRng, message)
    }

    fn verify_signature(
        &self,
        signature: &Self::Signature,
        verifying_key: &Self::VerifyingKey,
        message: &[u8],
    ) -> bool {
        let verifier = match Verifier::new(verifying_key.as_ref()) {
            Err(_) => return false,
            Ok(verifier) => verifier,
        };
        verifier.verify(&message, signature).is_ok()
    }
}

impl<R: CryptoRng + RngCore> Es256k<R> {
    /// Generate a new key pair.
    pub fn generate(&mut self) -> (Es256kSigningKey, Es256kVerifyingKey) {
        let signing_key = Es256kSigningKey(SecretKey::generate(&mut self.rng));
        let verifying_key =
            Es256kVerifyingKey(PublicKey::from_secret_key(signing_key.as_ref(), true).unwrap());
        (signing_key, verifying_key)
    }
}