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