Skip to main content

co_didcomm/crypto/
signer.rs

1use std::convert::{TryFrom, TryInto};
2
3use super::*;
4
5/// Signature related batteries for DIDComm.
6/// Implementation of all algorithms required by (spec)[https://identity.foundation/didcomm-messaging/spec/#algorithms]
7#[derive(Debug, Clone)]
8pub enum SignatureAlgorithm {
9    /// `ed25519` signature
10    EdDsa,
11    /// `ECDSA/P-256` NIST signature
12    Es256,
13    /// `ECDSA/secp256k1` signature
14    Es256k,
15}
16
17impl Signer for SignatureAlgorithm {
18    /// Builds signer FnOnce, which performs signing.
19    ///
20    /// # Examples
21    /// ```
22    /// # fn main() {
23    /// use co_didcomm::crypto::{SignatureAlgorithm, Signer};
24    /// let signer = SignatureAlgorithm::Es256k.signer();
25    /// # }
26    ///```
27    fn signer(&self) -> SigningMethod {
28        match self {
29            // an &[u8] representing the scalar for the secret key, and a compressed Edwards-Y coordinate of a point on curve25519, both as bytes.
30            SignatureAlgorithm::EdDsa => {
31                Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
32                    use ed25519_dalek::{Signer, SigningKey, SECRET_KEY_LENGTH};
33                    let key = SigningKey::from_bytes(
34                        key.try_into().map_err(|_| Error::InvalidKeySize(format!("ed25519 expects key size of {}", SECRET_KEY_LENGTH)))?
35                    );
36                    let s = key.sign(message);
37                    Ok(s.to_bytes().to_vec())
38                })
39            }
40            SignatureAlgorithm::Es256 => {
41                Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
42                    use p256::ecdsa::{signature::Signer, Signature, SigningKey};
43                    let sk = SigningKey::from_bytes(
44                        key.try_into().map_err(|_| Error::InvalidKeySize(format!("p256 invalid key size")))?
45                    )?;
46                    let signature: Signature = sk.sign(message);
47                    Ok(signature.to_bytes().to_vec())
48                })
49            }
50            SignatureAlgorithm::Es256k => {
51                Box::new(|key: &[u8], message: &[u8]| -> Result<Vec<u8>, Error> {
52                    use k256::ecdsa::{signature::Signer, Signature, SigningKey};
53                    let sk = SigningKey::from_bytes(
54                        key.try_into().map_err(|_| Error::InvalidKeySize(format!("k256 invalid key size")))?
55                    ).map_err(|e| Error::Generic(e.to_string()))?;
56                    let signature: Signature = sk.sign(message);
57                    Ok(signature.to_bytes().to_vec())
58                })
59            }
60        }
61    }
62
63    /// Builds validator FnOnce, which performs signature validation.
64    ///
65    /// # Examples
66    /// ```
67    /// # fn main() {
68    /// use co_didcomm::crypto::{Signer, SignatureAlgorithm};
69    /// let validator = SignatureAlgorithm::Es256k.validator();
70    /// # }
71    /// ```
72    fn validator(&self) -> ValidationMethod {
73        match self {
74            SignatureAlgorithm::EdDsa => Box::new(
75                |key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
76                    use ed25519_dalek::{VerifyingKey, Signature, Verifier, SECRET_KEY_LENGTH};
77                    let ed25519_key = key.try_into()
78                        .map_err(|_| Error::InvalidKeySize(format!("ed25519 expects key size of {}", SECRET_KEY_LENGTH)))?;
79                    let key = VerifyingKey::from_bytes(ed25519_key)?;
80                    let s = Signature::try_from(signature)?;
81                    Ok(key.verify(message, &s).is_ok())
82                },
83            ),
84            SignatureAlgorithm::Es256 => Box::new(
85                |key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
86                    use p256::ecdsa::{signature::Verifier, Signature, VerifyingKey};
87                    let key = VerifyingKey::from_sec1_bytes(key)?;
88                    let s = Signature::try_from(signature)?;
89                    Ok(key.verify(message, &s).is_ok())
90                },
91            ),
92            SignatureAlgorithm::Es256k => Box::new(
93                |key: &[u8], message: &[u8], signature: &[u8]| -> Result<bool, Error> {
94                    use k256::ecdsa::{signature::Verifier, Signature, VerifyingKey};
95                    let vk = VerifyingKey::from_sec1_bytes(key)?;
96                    let signature = Signature::try_from(signature)?;
97                    Ok(vk.verify(message, &signature).is_ok())
98                },
99            ),
100        }
101    }
102}
103
104impl TryFrom<&String> for SignatureAlgorithm {
105    type Error = Error;
106
107    fn try_from(value: &String) -> Result<Self, Self::Error> {
108        match &value[..] {
109            "EdDSA" => Ok(Self::EdDsa),
110            "ES256" => Ok(Self::Es256),
111            "ES256K" => Ok(Self::Es256k),
112            _ => Err(Error::JwsParseError),
113        }
114    }
115}
116
117#[test]
118fn es256k_test() {
119    use k256::{ecdsa::SigningKey, elliptic_curve::rand_core::OsRng};
120    // Arrange
121    let sk = SigningKey::random(&mut OsRng);
122    let vk = &sk.verifying_key();
123    let m = b"this is the message we're signing in this test...";
124    // Act
125    let signer = SignatureAlgorithm::Es256k.signer();
126    let validator = SignatureAlgorithm::Es256k.validator();
127    let sk: Vec<u8> = sk.to_bytes().to_vec();
128    let vk = vk.to_sec1_bytes().to_vec();
129    let signature = signer(&sk, m);
130    let validation = validator(&vk, m, &signature.unwrap());
131    // Assert
132    assert!(&validation.is_ok());
133    assert!(validation.unwrap());
134}