1use crate::{Algorithm, EcdsaCurve, Error, Result, public::EcdsaPublicKey};
4use core::fmt;
5use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
6use sec1::consts::{U32, U48, U66};
7use subtle::{Choice, ConstantTimeEq};
8use zeroize::Zeroize;
9
10#[cfg(feature = "rand_core")]
11use rand_core::CryptoRng;
12
13#[derive(Clone)]
15pub struct EcdsaPrivateKey<const SIZE: usize> {
16 bytes: [u8; SIZE],
18}
19
20impl<const SIZE: usize> EcdsaPrivateKey<SIZE> {
21 pub fn as_slice(&self) -> &[u8] {
23 self.bytes.as_ref()
24 }
25
26 pub fn into_bytes(self) -> [u8; SIZE] {
28 self.bytes
29 }
30
31 fn needs_leading_zero(&self) -> bool {
33 self.bytes[0] >= 0x80
34 }
35}
36
37impl<const SIZE: usize> Decode for EcdsaPrivateKey<SIZE> {
38 type Error = Error;
39
40 fn decode(reader: &mut impl Reader) -> Result<Self> {
41 reader.read_prefixed(|reader| {
42 let mut len = reader.remaining_len();
43
44 if len == SIZE.checked_add(1).ok_or(encoding::Error::Length)? {
47 if u8::decode(reader)? != 0 {
49 return Err(Error::FormatEncoding);
50 }
51
52 len = SIZE;
53 }
54
55 const MIN_SIZE: usize = 32;
57 if len < MIN_SIZE || len > SIZE {
58 return Err(encoding::Error::Length.into());
59 }
60
61 let leading_zeros = SIZE.checked_sub(len).ok_or(encoding::Error::Length)?;
64
65 let mut bytes = [0u8; SIZE];
66 reader.read(&mut bytes[leading_zeros..])?;
67 Ok(Self { bytes })
68 })
69 }
70}
71
72impl<const SIZE: usize> Encode for EcdsaPrivateKey<SIZE> {
73 fn encoded_len(&self) -> encoding::Result<usize> {
74 [4, self.needs_leading_zero().into(), SIZE].checked_sum()
75 }
76
77 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
78 [self.needs_leading_zero().into(), SIZE]
79 .checked_sum()?
80 .encode(writer)?;
81
82 if self.needs_leading_zero() {
83 writer.write(&[0])?;
84 }
85
86 writer.write(&self.bytes)?;
87 Ok(())
88 }
89}
90
91impl<const SIZE: usize> From<[u8; SIZE]> for EcdsaPrivateKey<SIZE> {
92 fn from(bytes: [u8; SIZE]) -> Self {
93 Self { bytes }
94 }
95}
96
97impl<const SIZE: usize> AsRef<[u8; SIZE]> for EcdsaPrivateKey<SIZE> {
98 fn as_ref(&self) -> &[u8; SIZE] {
99 &self.bytes
100 }
101}
102
103impl<const SIZE: usize> ConstantTimeEq for EcdsaPrivateKey<SIZE> {
104 fn ct_eq(&self, other: &Self) -> Choice {
105 self.as_ref().ct_eq(other.as_ref())
106 }
107}
108
109impl<const SIZE: usize> PartialEq for EcdsaPrivateKey<SIZE> {
110 fn eq(&self, other: &Self) -> bool {
111 self.ct_eq(other).into()
112 }
113}
114
115impl<const SIZE: usize> Eq for EcdsaPrivateKey<SIZE> {}
116
117impl<const SIZE: usize> fmt::Debug for EcdsaPrivateKey<SIZE> {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.debug_struct("EcdsaPrivateKey").finish_non_exhaustive()
120 }
121}
122
123impl<const SIZE: usize> fmt::LowerHex for EcdsaPrivateKey<SIZE> {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 for byte in self.as_ref() {
126 write!(f, "{byte:02x}")?;
127 }
128 Ok(())
129 }
130}
131
132impl<const SIZE: usize> fmt::UpperHex for EcdsaPrivateKey<SIZE> {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 for byte in self.as_ref() {
135 write!(f, "{byte:02X}")?;
136 }
137 Ok(())
138 }
139}
140
141impl<const SIZE: usize> Drop for EcdsaPrivateKey<SIZE> {
142 fn drop(&mut self) {
143 self.bytes.zeroize();
144 }
145}
146
147#[cfg(feature = "p256")]
148impl From<p256::SecretKey> for EcdsaPrivateKey<32> {
149 fn from(sk: p256::SecretKey) -> EcdsaPrivateKey<32> {
150 EcdsaPrivateKey {
151 bytes: sk.to_bytes().into(),
152 }
153 }
154}
155
156#[cfg(feature = "p384")]
157impl From<p384::SecretKey> for EcdsaPrivateKey<48> {
158 fn from(sk: p384::SecretKey) -> EcdsaPrivateKey<48> {
159 EcdsaPrivateKey {
160 bytes: sk.to_bytes().into(),
161 }
162 }
163}
164
165#[cfg(feature = "p521")]
166impl From<p521::SecretKey> for EcdsaPrivateKey<66> {
167 fn from(sk: p521::SecretKey) -> EcdsaPrivateKey<66> {
168 let mut bytes = [0u8; 66];
170 bytes.copy_from_slice(&sk.to_bytes());
171 EcdsaPrivateKey { bytes }
172 }
173}
174
175#[derive(Clone, Debug)]
177pub enum EcdsaKeypair {
178 NistP256 {
180 public: sec1::EncodedPoint<U32>,
182
183 private: EcdsaPrivateKey<32>,
185 },
186
187 NistP384 {
189 public: sec1::EncodedPoint<U48>,
191
192 private: EcdsaPrivateKey<48>,
194 },
195
196 NistP521 {
198 public: sec1::EncodedPoint<U66>,
200
201 private: EcdsaPrivateKey<66>,
203 },
204}
205
206impl EcdsaKeypair {
207 #[cfg(feature = "rand_core")]
209 #[allow(unused_variables)]
210 pub fn random<R: CryptoRng + ?Sized>(rng: &mut R, curve: EcdsaCurve) -> Result<Self> {
211 match curve {
212 #[cfg(feature = "p256")]
213 EcdsaCurve::NistP256 => {
214 let private = p256::SecretKey::random(rng);
215 let public = private.public_key();
216 Ok(EcdsaKeypair::NistP256 {
217 private: private.into(),
218 public: public.into(),
219 })
220 }
221 #[cfg(feature = "p384")]
222 EcdsaCurve::NistP384 => {
223 let private = p384::SecretKey::random(rng);
224 let public = private.public_key();
225 Ok(EcdsaKeypair::NistP384 {
226 private: private.into(),
227 public: public.into(),
228 })
229 }
230 #[cfg(feature = "p521")]
231 EcdsaCurve::NistP521 => {
232 let private = p521::SecretKey::random(rng);
233 let public = private.public_key();
234 Ok(EcdsaKeypair::NistP521 {
235 private: private.into(),
236 public: public.into(),
237 })
238 }
239 #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
240 _ => Err(Error::AlgorithmUnknown),
241 }
242 }
243
244 pub fn algorithm(&self) -> Algorithm {
246 Algorithm::Ecdsa {
247 curve: self.curve(),
248 }
249 }
250
251 pub fn curve(&self) -> EcdsaCurve {
253 match self {
254 Self::NistP256 { .. } => EcdsaCurve::NistP256,
255 Self::NistP384 { .. } => EcdsaCurve::NistP384,
256 Self::NistP521 { .. } => EcdsaCurve::NistP521,
257 }
258 }
259
260 pub fn public_key_bytes(&self) -> &[u8] {
262 match self {
263 Self::NistP256 { public, .. } => public.as_ref(),
264 Self::NistP384 { public, .. } => public.as_ref(),
265 Self::NistP521 { public, .. } => public.as_ref(),
266 }
267 }
268
269 pub fn private_key_bytes(&self) -> &[u8] {
271 match self {
272 Self::NistP256 { private, .. } => private.as_ref(),
273 Self::NistP384 { private, .. } => private.as_ref(),
274 Self::NistP521 { private, .. } => private.as_ref(),
275 }
276 }
277}
278
279impl ConstantTimeEq for EcdsaKeypair {
280 fn ct_eq(&self, other: &Self) -> Choice {
281 let public_eq =
282 Choice::from((EcdsaPublicKey::from(self) == EcdsaPublicKey::from(other)) as u8);
283
284 let private_key_a = match self {
285 Self::NistP256 { private, .. } => private.as_slice(),
286 Self::NistP384 { private, .. } => private.as_slice(),
287 Self::NistP521 { private, .. } => private.as_slice(),
288 };
289
290 let private_key_b = match other {
291 Self::NistP256 { private, .. } => private.as_slice(),
292 Self::NistP384 { private, .. } => private.as_slice(),
293 Self::NistP521 { private, .. } => private.as_slice(),
294 };
295
296 public_eq & private_key_a.ct_eq(private_key_b)
297 }
298}
299
300impl Eq for EcdsaKeypair {}
301
302impl PartialEq for EcdsaKeypair {
303 fn eq(&self, other: &Self) -> bool {
304 self.ct_eq(other).into()
305 }
306}
307
308impl Decode for EcdsaKeypair {
309 type Error = Error;
310
311 fn decode(reader: &mut impl Reader) -> Result<Self> {
312 match EcdsaPublicKey::decode(reader)? {
313 EcdsaPublicKey::NistP256(public) => {
314 let private = EcdsaPrivateKey::<32>::decode(reader)?;
315 Ok(Self::NistP256 { public, private })
316 }
317 EcdsaPublicKey::NistP384(public) => {
318 let private = EcdsaPrivateKey::<48>::decode(reader)?;
319 Ok(Self::NistP384 { public, private })
320 }
321 EcdsaPublicKey::NistP521(public) => {
322 let private = EcdsaPrivateKey::<66>::decode(reader)?;
323 Ok(Self::NistP521 { public, private })
324 }
325 }
326 }
327}
328
329impl Encode for EcdsaKeypair {
330 fn encoded_len(&self) -> encoding::Result<usize> {
331 let public_len = EcdsaPublicKey::from(self).encoded_len()?;
332
333 let private_len = match self {
334 Self::NistP256 { private, .. } => private.encoded_len()?,
335 Self::NistP384 { private, .. } => private.encoded_len()?,
336 Self::NistP521 { private, .. } => private.encoded_len()?,
337 };
338
339 [public_len, private_len].checked_sum()
340 }
341
342 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
343 EcdsaPublicKey::from(self).encode(writer)?;
344
345 match self {
346 Self::NistP256 { private, .. } => private.encode(writer)?,
347 Self::NistP384 { private, .. } => private.encode(writer)?,
348 Self::NistP521 { private, .. } => private.encode(writer)?,
349 }
350
351 Ok(())
352 }
353}
354
355impl From<EcdsaKeypair> for EcdsaPublicKey {
356 fn from(keypair: EcdsaKeypair) -> EcdsaPublicKey {
357 EcdsaPublicKey::from(&keypair)
358 }
359}
360
361impl From<&EcdsaKeypair> for EcdsaPublicKey {
362 fn from(keypair: &EcdsaKeypair) -> EcdsaPublicKey {
363 match keypair {
364 EcdsaKeypair::NistP256 { public, .. } => EcdsaPublicKey::NistP256(*public),
365 EcdsaKeypair::NistP384 { public, .. } => EcdsaPublicKey::NistP384(*public),
366 EcdsaKeypair::NistP521 { public, .. } => EcdsaPublicKey::NistP521(*public),
367 }
368 }
369}