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
use crate::{Signer, SigningError};
use core::convert::TryFrom;
use core::str::FromStr;
use m10_protos::sdk::signature::Algorithm;
use ring::{
    rand,
    signature::{EcdsaKeyPair, KeyPair, ECDSA_P256_SHA256_ASN1_SIGNING},
};
use std::fs::File;
use std::io::{Read, Write};
#[derive(serde::Deserialize)]
#[serde(try_from = "String", into = "String")]
pub struct P256 {
    #[serde(flatten)]
    key_pair: EcdsaKeyPair,
    #[serde(skip)]
    rng: rand::SystemRandom,
}
impl P256 {
    
    pub fn new_key_pair(path: Option<&str>) -> Result<Self, SigningError> {
        let rng = rand::SystemRandom::new();
        let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, &rng)
            .map_err(|_| SigningError::Internal)?;
        if let Some(p) = path {
            let mut key_file = File::create(p)?;
            key_file.write_all(pkcs8_bytes.as_ref())?;
        }
        Ok(Self {
            key_pair: EcdsaKeyPair::from_pkcs8(
                &ECDSA_P256_SHA256_ASN1_SIGNING,
                pkcs8_bytes.as_ref(),
            )?,
            rng,
        })
    }
    
    pub fn load_key_pair(path: &str) -> Result<Self, SigningError> {
        let mut key_file = File::open(path)?;
        let mut pkcs8_bytes: Vec<u8> = Vec::new();
        key_file.read_to_end(&mut pkcs8_bytes)?;
        let rng = rand::SystemRandom::new();
        Ok(Self {
            key_pair: EcdsaKeyPair::from_pkcs8(
                &ECDSA_P256_SHA256_ASN1_SIGNING,
                pkcs8_bytes.as_ref(),
            )?,
            rng,
        })
    }
    
    pub fn new_key_pair_exportable() -> Result<(Vec<u8>, Self), SigningError> {
        let rng = rand::SystemRandom::new();
        let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, &rng)
            .map_err(|_| SigningError::Internal)?;
        let key_pair =
            EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8_bytes.as_ref())?;
        Ok((pkcs8_bytes.as_ref().to_vec(), Self { key_pair, rng }))
    }
    
    pub fn from_pkcs8(bytes: &[u8]) -> Result<Self, SigningError> {
        let rng = rand::SystemRandom::new();
        let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, bytes)?;
        Ok(Self { key_pair, rng })
    }
}
#[async_trait::async_trait]
impl Signer for P256 {
    async fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, super::SigningError> {
        self.key_pair
            .sign(&self.rng, msg)
            .map(|x| x.as_ref().to_vec())
            .map_err(|_| super::SigningError::Internal)
    }
    fn public_key(&self) -> &[u8] {
        self.key_pair.public_key().as_ref()
    }
    fn algorithm(&self) -> Algorithm {
        Algorithm::P256Sha256Asn1
    }
}
impl FromStr for P256 {
    type Err = SigningError;
    fn from_str(key_pair_enc: &str) -> Result<Self, Self::Err> {
        let pkcs8_bytes = base64::decode(key_pair_enc).unwrap_or_default();
        P256::from_pkcs8(&pkcs8_bytes)
    }
}
impl TryFrom<String> for P256 {
    type Error = SigningError;
    fn try_from(key_pair: String) -> Result<Self, Self::Error> {
        key_pair.parse()
    }
}