1use crate::types::{ECDSACurve, ExportKeyFormat, SHAFamily};
4use generic_array::GenericArray;
5use p256::ecdsa::{SigningKey, VerifyingKey};
6use rand_core::OsRng;
7use signature::{Signer, Verifier};
8
9pub struct ECDSA;
10
11impl ECDSA {
12 pub async fn generate_key_pair(
13 curve: Option<ECDSACurve>,
14 ) -> Result<(Vec<u8>, Vec<u8>), Box<dyn std::error::Error>> {
15 let curve = curve.unwrap_or(ECDSACurve::P256);
16
17 match curve {
18 ECDSACurve::P256 => {
19 let signing_key = SigningKey::random(&mut OsRng);
20 let verifying_key = signing_key.verifying_key();
21
22 let private_key = signing_key.to_bytes().to_vec();
23 let public_key = verifying_key.to_encoded_point(false).as_bytes().to_vec();
24
25 Ok((private_key, public_key))
26 }
27 _ => Err("Currently only P-256 curve is supported".into()),
28 }
29 }
30
31 pub async fn import_private_key(
32 private_key: impl AsRef<[u8]>,
33 curve: ECDSACurve,
34 _extractable: bool,
35 ) -> Result<SigningKey, Box<dyn std::error::Error>> {
36 match curve {
37 ECDSACurve::P256 => {
38 let bytes = private_key.as_ref();
39 let array_ref = GenericArray::from_slice(bytes);
40 let key = SigningKey::from_bytes(array_ref)?;
41 Ok(key)
42 }
43 _ => Err("Currently only P-256 curve is supported".into()),
44 }
45 }
46
47 pub async fn import_public_key(
48 public_key: impl AsRef<[u8]>,
49 curve: ECDSACurve,
50 _extractable: bool,
51 ) -> Result<VerifyingKey, Box<dyn std::error::Error>> {
52 match curve {
53 ECDSACurve::P256 => {
54 let key = VerifyingKey::from_sec1_bytes(public_key.as_ref())?;
55 Ok(key)
56 }
57 _ => Err("Currently only P-256 curve is supported".into()),
58 }
59 }
60
61 pub async fn sign(
62 private_key: &SigningKey,
63 data: impl AsRef<[u8]>,
64 hash: Option<SHAFamily>,
65 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
66 let hash = hash.unwrap_or(SHAFamily::SHA256);
67
68 match hash {
69 SHAFamily::SHA256 => {
70 let signature: p256::ecdsa::Signature = private_key.sign(data.as_ref());
71 Ok(signature.to_vec())
72 }
73 _ => Err("Currently only SHA-256 is supported for signing".into()),
74 }
75 }
76
77 pub async fn verify(
78 public_key: &VerifyingKey,
79 signature: impl AsRef<[u8]>,
80 data: impl AsRef<[u8]>,
81 hash: Option<SHAFamily>,
82 ) -> Result<bool, Box<dyn std::error::Error>> {
83 let hash = hash.unwrap_or(SHAFamily::SHA256);
84
85 match hash {
86 SHAFamily::SHA256 => {
87 let sig = p256::ecdsa::Signature::from_slice(signature.as_ref())?;
88 Ok(public_key.verify(data.as_ref(), &sig).is_ok())
89 }
90 _ => Err("Currently only SHA-256 is supported for verification".into()),
91 }
92 }
93
94 pub async fn export_key(
95 key: &(impl AsRef<[u8]> + ?Sized),
96 format: ExportKeyFormat,
97 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
98 match format {
99 ExportKeyFormat::SPKI => {
100 if let Ok(public_key) = VerifyingKey::from_sec1_bytes(key.as_ref()) {
101 Ok(public_key.to_encoded_point(false).as_bytes().to_vec())
102 } else {
103 Err("Key is not a valid public key".into())
104 }
105 }
106 ExportKeyFormat::PKCS8 => {
107 let array_ref = GenericArray::from_slice(key.as_ref());
108 if let Ok(private_key) = SigningKey::from_bytes(array_ref) {
109 Ok(private_key.to_bytes().to_vec())
110 } else {
111 Err("Key is not a valid private key".into())
112 }
113 }
114 _ => Err("Unsupported export format".into()),
115 }
116 }
117
118 pub async fn export_key_private(
119 key: &SigningKey,
120 format: ExportKeyFormat,
121 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
122 match format {
123 ExportKeyFormat::PKCS8 => Ok(key.to_bytes().to_vec()),
124 _ => Err("Unsupported export format for private key".into()),
125 }
126 }
127
128 pub async fn export_key_public(
129 key: &VerifyingKey,
130 format: ExportKeyFormat,
131 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
132 match format {
133 ExportKeyFormat::SPKI => Ok(key.to_encoded_point(false).as_bytes().to_vec()),
134 _ => Err("Unsupported export format for public key".into()),
135 }
136 }
137}