1use crate::{public::EcdsaPublicKey, Algorithm, EcdsaCurve, Error, Result};
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::CryptoRngCore;
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 if reader.remaining_len() == SIZE.checked_add(1).ok_or(encoding::Error::Length)? {
43 if u8::decode(reader)? != 0 {
46 return Err(Error::FormatEncoding);
47 }
48 }
49
50 let mut bytes = [0u8; SIZE];
51 reader.read(&mut bytes)?;
52 Ok(Self { bytes })
53 })
54 }
55}
56
57impl<const SIZE: usize> Encode for EcdsaPrivateKey<SIZE> {
58 fn encoded_len(&self) -> encoding::Result<usize> {
59 [4, self.needs_leading_zero().into(), SIZE].checked_sum()
60 }
61
62 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
63 [self.needs_leading_zero().into(), SIZE]
64 .checked_sum()?
65 .encode(writer)?;
66
67 if self.needs_leading_zero() {
68 writer.write(&[0])?;
69 }
70
71 writer.write(&self.bytes)?;
72 Ok(())
73 }
74}
75
76impl<const SIZE: usize> AsRef<[u8; SIZE]> for EcdsaPrivateKey<SIZE> {
77 fn as_ref(&self) -> &[u8; SIZE] {
78 &self.bytes
79 }
80}
81
82impl<const SIZE: usize> ConstantTimeEq for EcdsaPrivateKey<SIZE> {
83 fn ct_eq(&self, other: &Self) -> Choice {
84 self.as_ref().ct_eq(other.as_ref())
85 }
86}
87
88impl<const SIZE: usize> PartialEq for EcdsaPrivateKey<SIZE> {
89 fn eq(&self, other: &Self) -> bool {
90 self.ct_eq(other).into()
91 }
92}
93
94impl<const SIZE: usize> Eq for EcdsaPrivateKey<SIZE> {}
95
96impl<const SIZE: usize> fmt::Debug for EcdsaPrivateKey<SIZE> {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f.debug_struct("EcdsaPrivateKey").finish_non_exhaustive()
99 }
100}
101
102impl<const SIZE: usize> fmt::LowerHex for EcdsaPrivateKey<SIZE> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 for byte in self.as_ref() {
105 write!(f, "{byte:02x}")?;
106 }
107 Ok(())
108 }
109}
110
111impl<const SIZE: usize> fmt::UpperHex for EcdsaPrivateKey<SIZE> {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 for byte in self.as_ref() {
114 write!(f, "{byte:02X}")?;
115 }
116 Ok(())
117 }
118}
119
120impl<const SIZE: usize> Drop for EcdsaPrivateKey<SIZE> {
121 fn drop(&mut self) {
122 self.bytes.zeroize();
123 }
124}
125
126#[cfg(feature = "p256")]
127impl From<p256::SecretKey> for EcdsaPrivateKey<32> {
128 fn from(sk: p256::SecretKey) -> EcdsaPrivateKey<32> {
129 EcdsaPrivateKey {
130 bytes: sk.to_bytes().into(),
131 }
132 }
133}
134
135#[cfg(feature = "p384")]
136impl From<p384::SecretKey> for EcdsaPrivateKey<48> {
137 fn from(sk: p384::SecretKey) -> EcdsaPrivateKey<48> {
138 EcdsaPrivateKey {
139 bytes: sk.to_bytes().into(),
140 }
141 }
142}
143
144#[cfg(feature = "p521")]
145impl From<p521::SecretKey> for EcdsaPrivateKey<66> {
146 fn from(sk: p521::SecretKey) -> EcdsaPrivateKey<66> {
147 let mut bytes = [0u8; 66];
149 bytes.copy_from_slice(&sk.to_bytes());
150 EcdsaPrivateKey { bytes }
151 }
152}
153
154#[derive(Clone, Debug)]
156pub enum EcdsaKeypair {
157 NistP256 {
159 public: sec1::EncodedPoint<U32>,
161
162 private: EcdsaPrivateKey<32>,
164 },
165
166 NistP384 {
168 public: sec1::EncodedPoint<U48>,
170
171 private: EcdsaPrivateKey<48>,
173 },
174
175 NistP521 {
177 public: sec1::EncodedPoint<U66>,
179
180 private: EcdsaPrivateKey<66>,
182 },
183}
184
185impl EcdsaKeypair {
186 #[cfg(feature = "rand_core")]
188 #[allow(unused_variables)]
189 pub fn random(rng: &mut impl CryptoRngCore, curve: EcdsaCurve) -> Result<Self> {
190 match curve {
191 #[cfg(feature = "p256")]
192 EcdsaCurve::NistP256 => {
193 let private = p256::SecretKey::random(rng);
194 let public = private.public_key();
195 Ok(EcdsaKeypair::NistP256 {
196 private: private.into(),
197 public: public.into(),
198 })
199 }
200 #[cfg(feature = "p384")]
201 EcdsaCurve::NistP384 => {
202 let private = p384::SecretKey::random(rng);
203 let public = private.public_key();
204 Ok(EcdsaKeypair::NistP384 {
205 private: private.into(),
206 public: public.into(),
207 })
208 }
209 #[cfg(feature = "p521")]
210 EcdsaCurve::NistP521 => {
211 let private = p521::SecretKey::random(rng);
212 let public = private.public_key();
213 Ok(EcdsaKeypair::NistP521 {
214 private: private.into(),
215 public: public.into(),
216 })
217 }
218 #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
219 _ => Err(Error::AlgorithmUnknown),
220 }
221 }
222
223 pub fn algorithm(&self) -> Algorithm {
225 Algorithm::Ecdsa {
226 curve: self.curve(),
227 }
228 }
229
230 pub fn curve(&self) -> EcdsaCurve {
232 match self {
233 Self::NistP256 { .. } => EcdsaCurve::NistP256,
234 Self::NistP384 { .. } => EcdsaCurve::NistP384,
235 Self::NistP521 { .. } => EcdsaCurve::NistP521,
236 }
237 }
238
239 pub fn public_key_bytes(&self) -> &[u8] {
241 match self {
242 Self::NistP256 { public, .. } => public.as_ref(),
243 Self::NistP384 { public, .. } => public.as_ref(),
244 Self::NistP521 { public, .. } => public.as_ref(),
245 }
246 }
247
248 pub fn private_key_bytes(&self) -> &[u8] {
250 match self {
251 Self::NistP256 { private, .. } => private.as_ref(),
252 Self::NistP384 { private, .. } => private.as_ref(),
253 Self::NistP521 { private, .. } => private.as_ref(),
254 }
255 }
256}
257
258impl ConstantTimeEq for EcdsaKeypair {
259 fn ct_eq(&self, other: &Self) -> Choice {
260 let public_eq =
261 Choice::from((EcdsaPublicKey::from(self) == EcdsaPublicKey::from(other)) as u8);
262
263 let private_key_a = match self {
264 Self::NistP256 { private, .. } => private.as_slice(),
265 Self::NistP384 { private, .. } => private.as_slice(),
266 Self::NistP521 { private, .. } => private.as_slice(),
267 };
268
269 let private_key_b = match other {
270 Self::NistP256 { private, .. } => private.as_slice(),
271 Self::NistP384 { private, .. } => private.as_slice(),
272 Self::NistP521 { private, .. } => private.as_slice(),
273 };
274
275 public_eq & private_key_a.ct_eq(private_key_b)
276 }
277}
278
279impl Eq for EcdsaKeypair {}
280
281impl PartialEq for EcdsaKeypair {
282 fn eq(&self, other: &Self) -> bool {
283 self.ct_eq(other).into()
284 }
285}
286
287impl Decode for EcdsaKeypair {
288 type Error = Error;
289
290 fn decode(reader: &mut impl Reader) -> Result<Self> {
291 match EcdsaPublicKey::decode(reader)? {
292 EcdsaPublicKey::NistP256(public) => {
293 let private = EcdsaPrivateKey::<32>::decode(reader)?;
294 Ok(Self::NistP256 { public, private })
295 }
296 EcdsaPublicKey::NistP384(public) => {
297 let private = EcdsaPrivateKey::<48>::decode(reader)?;
298 Ok(Self::NistP384 { public, private })
299 }
300 EcdsaPublicKey::NistP521(public) => {
301 let private = EcdsaPrivateKey::<66>::decode(reader)?;
302 Ok(Self::NistP521 { public, private })
303 }
304 }
305 }
306}
307
308impl Encode for EcdsaKeypair {
309 fn encoded_len(&self) -> encoding::Result<usize> {
310 let public_len = EcdsaPublicKey::from(self).encoded_len()?;
311
312 let private_len = match self {
313 Self::NistP256 { private, .. } => private.encoded_len()?,
314 Self::NistP384 { private, .. } => private.encoded_len()?,
315 Self::NistP521 { private, .. } => private.encoded_len()?,
316 };
317
318 [public_len, private_len].checked_sum()
319 }
320
321 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
322 EcdsaPublicKey::from(self).encode(writer)?;
323
324 match self {
325 Self::NistP256 { private, .. } => private.encode(writer)?,
326 Self::NistP384 { private, .. } => private.encode(writer)?,
327 Self::NistP521 { private, .. } => private.encode(writer)?,
328 }
329
330 Ok(())
331 }
332}
333
334impl From<EcdsaKeypair> for EcdsaPublicKey {
335 fn from(keypair: EcdsaKeypair) -> EcdsaPublicKey {
336 EcdsaPublicKey::from(&keypair)
337 }
338}
339
340impl From<&EcdsaKeypair> for EcdsaPublicKey {
341 fn from(keypair: &EcdsaKeypair) -> EcdsaPublicKey {
342 match keypair {
343 EcdsaKeypair::NistP256 { public, .. } => EcdsaPublicKey::NistP256(*public),
344 EcdsaKeypair::NistP384 { public, .. } => EcdsaPublicKey::NistP384(*public),
345 EcdsaKeypair::NistP521 { public, .. } => EcdsaPublicKey::NistP521(*public),
346 }
347 }
348}