did_crypto/crypto/ecdsa/
_384.rs

1use std::str::FromStr;
2
3use crate::{
4    algorithms::Algorithm,
5    crypto::{SignFromKey, VerifyFromKey},
6    errors::Error,
7    log,
8};
9use elliptic_curve::pkcs8::DecodePublicKey;
10use p384::{
11    ecdsa::{
12        signature::{Signer, Verifier},
13        Signature, SigningKey, VerifyingKey,
14    },
15    NistP384,
16};
17
18pub struct P384SigningKey {
19    key: SigningKey,
20}
21
22impl SignFromKey for P384SigningKey {
23    fn sign(&self, content: String, _alg: Algorithm) -> Result<String, Error> {
24        let sig_result: Result<Signature, p384::ecdsa::Error> =
25            self.key.try_sign(content.as_bytes());
26        let signature = match sig_result {
27            Ok(val) => val,
28            Err(error) => {
29                log::error(error.to_string().as_str());
30                return Err(Error::SIGNING_FAILED);
31            }
32        };
33
34        Ok(base64_url::encode(signature.to_bytes().as_slice()))
35    }
36}
37
38impl P384SigningKey {
39    pub fn from_pem(key_str: &str) -> Result<Self, Error> {
40        let ec_key = match key_str.starts_with("-----BEGIN EC PRIVATE KEY-----") {
41            true => {
42                let key_scalar: elliptic_curve::SecretKey<NistP384> =
43                    match elliptic_curve::SecretKey::from_sec1_pem(key_str) {
44                        Ok(val) => val,
45                        Err(error) => {
46                            log::error(error.to_string().as_str());
47                            return Err(Error::EC_PEM_ERROR);
48                        }
49                    };
50
51                match SigningKey::from_bytes(&key_scalar.as_scalar_primitive().to_bytes()) {
52                    Ok(val) => val,
53                    Err(error) => {
54                        log::error(error.to_string().as_str());
55                        return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
56                    }
57                }
58            }
59            false => {
60                let key_scalar: elliptic_curve::SecretKey<NistP384> =
61                    match elliptic_curve::SecretKey::from_str(key_str) {
62                        Ok(val) => val,
63                        Err(error) => {
64                            log::error(error.to_string().as_str());
65                            return Err(Error::EC_PEM_ERROR);
66                        }
67                    };
68
69                match SigningKey::from_bytes(&key_scalar.as_scalar_primitive().to_bytes()) {
70                    Ok(val) => val,
71                    Err(error) => {
72                        log::error(error.to_string().as_str());
73                        return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
74                    }
75                }
76            }
77        };
78
79        Ok(P384SigningKey { key: ec_key })
80    }
81}
82
83pub struct P384VerifyingKey {
84    key: VerifyingKey,
85}
86
87impl VerifyFromKey for P384VerifyingKey {
88    fn verify(&self, content: String, signature: String, _alg: Algorithm) -> Result<bool, Error> {
89        let decoded_sig = match base64_url::decode(signature.as_bytes()) {
90            Ok(val) => val,
91            Err(error) => {
92                log::error(error.to_string().as_str());
93                return Err(Error::DECODING_ERROR);
94            }
95        };
96
97        let sig = match Signature::from_slice(&decoded_sig) {
98            Ok(val) => val,
99            Err(error) => {
100                log::error(error.to_string().as_str());
101                return Err(Error::SIGNATURE_IDENTIFICATION_FAILED);
102            }
103        };
104
105        let verify_result: Result<(), p384::ecdsa::Error> =
106            self.key.verify(content.as_bytes(), &sig);
107        if verify_result.is_ok() {
108            return Ok(true);
109        } else {
110            match verify_result.err() {
111                Some(error) => {
112                    log::error(error.to_string().as_str());
113                }
114                None => {}
115            };
116            return Ok(false);
117        }
118    }
119}
120
121impl P384VerifyingKey {
122    pub fn from_pem(key_str: &str) -> Result<Self, Error> {
123        let key_scalar: elliptic_curve::PublicKey<NistP384> =
124            match elliptic_curve::PublicKey::from_public_key_pem(key_str) {
125                Ok(val) => val,
126                Err(error) => {
127                    log::error(error.to_string().as_str());
128                    return Err(Error::EC_PEM_ERROR);
129                }
130            };
131        let ec_key = match VerifyingKey::from_sec1_bytes(&key_scalar.to_sec1_bytes()) {
132            Ok(val) => val,
133            Err(error) => {
134                log::error(error.to_string().as_str());
135                return Err(Error::PUBLIC_KEY_IDENTIFICATION_ERROR);
136            }
137        };
138
139        Ok(P384VerifyingKey { key: ec_key })
140    }
141}
142
143pub fn ec_384_sign(message: String, key: impl SignFromKey) -> Result<String, Error> {
144    key.sign(message, Algorithm::ES384)
145}
146
147pub fn ec_384_verify(message: String, sig: String, key: impl VerifyFromKey) -> Result<bool, Error> {
148    key.verify(message, sig, Algorithm::ES384)
149}