opentitanlib/crypto/
ecdsa.rs1use anyhow::{Context, Result, anyhow, ensure};
6use ecdsa::Signature;
7use ecdsa::elliptic_curve::pkcs8::{DecodePrivateKey, EncodePrivateKey};
8use ecdsa::elliptic_curve::pkcs8::{DecodePublicKey, EncodePublicKey};
9use ecdsa::signature::hazmat::PrehashVerifier;
10use p256::NistP256;
11use p256::ecdsa::{SigningKey, VerifyingKey};
12use rand::rngs::OsRng;
13use serde::Deserialize;
14use serde_annotate::Annotate;
15use sha2::digest::generic_array::GenericArray;
16use std::fs::File;
17use std::io::{Read, Write};
18use std::path::Path;
19use std::str::FromStr;
20
21use super::Error;
22use crate::crypto::sha256::Sha256Digest;
23
24pub struct EcdsaPrivateKey {
25 pub key: SigningKey,
26}
27
28pub struct EcdsaPublicKey {
29 pub key: VerifyingKey,
30}
31
32impl Default for EcdsaPrivateKey {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl EcdsaPrivateKey {
39 pub fn new() -> Self {
40 Self {
41 key: SigningKey::random(&mut OsRng),
42 }
43 }
44
45 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
46 self.key.write_pkcs8_der_file(path)?;
47 Ok(())
48 }
49
50 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
51 let key = SigningKey::read_pkcs8_der_file(path)?;
52 Ok(Self { key })
53 }
54
55 pub fn public_key(&self) -> EcdsaPublicKey {
56 EcdsaPublicKey {
57 key: *self.key.verifying_key(),
58 }
59 }
60
61 pub fn sign(&self, digest: &Sha256Digest) -> Result<EcdsaRawSignature> {
62 let (sig, _) = self.key.sign_prehash_recoverable(digest.as_ref())?;
63 let bytes = sig.to_bytes();
64 let half = bytes.len() / 2;
65 let mut r = Vec::new();
69 r.extend(bytes[..half].iter().rev());
70 let mut s = Vec::new();
71 s.extend(bytes[half..].iter().rev());
72 Ok(EcdsaRawSignature { r, s })
73 }
74
75 pub fn digest_and_sign(&self, data: &[u8]) -> Result<EcdsaRawSignature> {
76 self.sign(&Sha256Digest::hash(data))
77 }
78}
79
80#[derive(Debug, Deserialize, Annotate)]
81pub struct EcdsaRawSignature {
82 #[serde(with = "serde_bytes")]
83 #[annotate(format = hexstr)]
84 pub r: Vec<u8>,
85 #[serde(with = "serde_bytes")]
86 #[annotate(format = hexstr)]
87 pub s: Vec<u8>,
88}
89
90impl Default for EcdsaRawSignature {
91 fn default() -> Self {
92 Self {
93 r: vec![0u8; 32],
94 s: vec![0u8; 32],
95 }
96 }
97}
98
99impl TryFrom<&[u8]> for EcdsaRawSignature {
100 type Error = Error;
101 fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
102 if value.len() != Self::SIZE {
103 return Err(Error::InvalidSignature(anyhow!(
104 "bad length: {}",
105 value.len()
106 )));
107 }
108 let mut value = std::io::Cursor::new(value);
109 EcdsaRawSignature::read(&mut value).map_err(Error::InvalidSignature)
110 }
111}
112
113impl EcdsaRawSignature {
114 const SIZE: usize = 64;
115
116 pub fn read(src: &mut impl Read) -> Result<Self> {
117 let mut sig = Self::default();
118 src.read_exact(&mut sig.r)?;
119 src.read_exact(&mut sig.s)?;
120 Ok(sig)
121 }
122
123 pub fn read_from_file(path: &Path) -> Result<EcdsaRawSignature> {
124 let mut file =
125 File::open(path).with_context(|| format!("Failed to read file: {path:?}"))?;
126 let file_size = std::fs::metadata(path)
127 .with_context(|| format!("Failed to get metadata for {path:?}"))?
128 .len();
129
130 let raw_size = Self::SIZE as u64;
131 if file_size == raw_size {
132 EcdsaRawSignature::read(&mut file)
134 } else {
135 let mut data = Vec::<u8>::new();
137
138 file.read_to_end(&mut data)
139 .with_context(|| format!("Failed to read {path:?}"))?;
140
141 EcdsaRawSignature::from_der(&data).with_context(|| format!("Failed parsing {path:?}"))
142 }
143 }
144
145 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
146 ensure!(
147 self.r.len() == 32,
148 Error::InvalidSignature(anyhow!("bad r length: {}", self.r.len()))
149 );
150 ensure!(
151 self.s.len() == 32,
152 Error::InvalidSignature(anyhow!("bad s length: {}", self.s.len()))
153 );
154 dest.write_all(&self.r)?;
155 dest.write_all(&self.s)?;
156 Ok(())
157 }
158
159 pub fn to_vec(&self) -> Result<Vec<u8>> {
160 let mut sig = Vec::new();
161 self.write(&mut sig)?;
162 Ok(sig)
163 }
164
165 pub fn is_empty(&self) -> bool {
166 self.r.iter().all(|&v| v == 0) && self.s.iter().all(|&v| v == 0)
167 }
168
169 fn from_der(data: &[u8]) -> Result<EcdsaRawSignature> {
170 let sig = Signature::<NistP256>::from_der(data).with_context(|| "Failed to parse DER")?;
171
172 let mut r: Vec<u8> = sig.r().to_bytes().to_vec();
179 let mut s: Vec<u8> = sig.s().to_bytes().to_vec();
180
181 r.reverse();
183 s.reverse();
184
185 r.resize(32, 0u8);
186 s.resize(32, 0u8);
187
188 Ok(EcdsaRawSignature { r, s })
189 }
190}
191
192impl EcdsaPublicKey {
193 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
194 self.key.write_public_key_der_file(path)?;
195 Ok(())
196 }
197
198 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
199 let key = VerifyingKey::read_public_key_der_file(path)?;
200 Ok(Self { key })
201 }
202
203 pub fn verify(&self, digest: &Sha256Digest, signature: &EcdsaRawSignature) -> Result<()> {
204 let mut bytes = signature.to_vec()?;
205 let half = bytes.len() / 2;
206 bytes[..half].reverse();
210 bytes[half..].reverse();
211 let signature = Signature::from_slice(&bytes)?;
212 self.key.verify_prehash(digest.as_ref(), &signature)?;
213 Ok(())
214 }
215}
216
217impl TryFrom<&EcdsaRawPublicKey> for EcdsaPublicKey {
218 type Error = Error;
219 fn try_from(v: &EcdsaRawPublicKey) -> Result<Self, Self::Error> {
220 let mut x = v.x.clone();
221 let mut y = v.y.clone();
222
223 x.reverse();
224 y.reverse();
225
226 let key = VerifyingKey::from_encoded_point(&p256::EncodedPoint::from_affine_coordinates(
227 &GenericArray::from(<[u8; 32]>::try_from(x.as_slice()).unwrap()),
228 &GenericArray::from(<[u8; 32]>::try_from(y.as_slice()).unwrap()),
229 false,
230 ))
231 .map_err(|e| Error::Other(anyhow!(e)))
232 .context("Failed to create verifying key from raw public key")?;
233 Ok(Self { key })
234 }
235}
236
237#[derive(Debug, Deserialize, Annotate)]
238pub struct EcdsaRawPublicKey {
239 #[serde(with = "serde_bytes")]
240 #[annotate(format = hexstr)]
241 pub x: Vec<u8>,
242 #[serde(with = "serde_bytes")]
243 #[annotate(format = hexstr)]
244 pub y: Vec<u8>,
245}
246
247impl Default for EcdsaRawPublicKey {
248 fn default() -> Self {
249 Self {
250 x: vec![0u8; 32],
251 y: vec![0u8; 32],
252 }
253 }
254}
255
256impl TryFrom<&EcdsaPublicKey> for EcdsaRawPublicKey {
257 type Error = Error;
258 fn try_from(v: &EcdsaPublicKey) -> Result<Self, Self::Error> {
259 let point = v.key.to_encoded_point(false);
260 let mut x = point.x().unwrap().as_slice().to_vec();
263 let mut y = point.y().unwrap().as_slice().to_vec();
264 x.reverse();
265 y.reverse();
266 Ok(EcdsaRawPublicKey { x, y })
267 }
268}
269
270impl TryFrom<EcdsaPublicKey> for EcdsaRawPublicKey {
271 type Error = Error;
272 fn try_from(v: EcdsaPublicKey) -> Result<Self, Self::Error> {
273 EcdsaRawPublicKey::try_from(&v)
274 }
275}
276
277impl FromStr for EcdsaRawPublicKey {
278 type Err = Error;
279 fn from_str(s: &str) -> Result<Self, Self::Err> {
280 let key = EcdsaPublicKey::load(s)
281 .with_context(|| format!("Failed to load {s}"))
282 .map_err(Error::Other)?;
283 EcdsaRawPublicKey::try_from(&key)
284 }
285}
286
287impl EcdsaRawPublicKey {
288 pub const SIZE: usize = 32 + 32;
289 pub fn read(src: &mut impl Read) -> Result<Self> {
290 let mut key = Self::default();
291 src.read_exact(&mut key.x)?;
292 src.read_exact(&mut key.y)?;
293 Ok(key)
294 }
295 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
296 ensure!(
297 self.x.len() == 32,
298 Error::InvalidPublicKey(anyhow!("bad x length: {}", self.x.len()))
299 );
300 ensure!(
301 self.y.len() == 32,
302 Error::InvalidPublicKey(anyhow!("bad y length: {}", self.y.len()))
303 );
304 dest.write_all(&self.x)?;
305 dest.write_all(&self.y)?;
306 Ok(())
307 }
308}