miden_crypto/dsa/ecdsa_k256_keccak/
mod.rs1use alloc::{string::ToString, vec::Vec};
5use core::fmt;
6
7use k256::{
8 ecdh::diffie_hellman,
9 ecdsa,
10 ecdsa::{RecoveryId, VerifyingKey, signature::hazmat::PrehashVerifier},
11 elliptic_curve::{Generate, scalar::IsHigh},
12 pkcs8::DecodePublicKey,
13};
14use miden_crypto_derive::{SilentDebug, SilentDisplay};
15use rand::CryptoRng;
16use thiserror::Error;
17
18use crate::{
19 Felt, SequentialCommit, Word,
20 ecdh::k256::{EphemeralPublicKey, SharedSecret},
21 utils::{
22 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
23 bytes_to_packed_u32_elements,
24 zeroize::{Zeroize, ZeroizeOnDrop},
25 },
26};
27
28mod tests;
29
30const SECRET_KEY_BYTES: usize = 32;
35pub(crate) const PUBLIC_KEY_BYTES: usize = 33;
37const SIGNATURE_BYTES: usize = 65;
39const SIGNATURE_STANDARD_BYTES: usize = 64;
41const SCALARS_SIZE_BYTES: usize = 32;
43
44#[derive(Clone, SilentDebug, SilentDisplay)]
49struct SecretKey {
50 inner: ecdsa::SigningKey,
51}
52
53impl SecretKey {
54 fn with_rng<R: CryptoRng>(rng: &mut R) -> Self {
56 let signing_key = ecdsa::SigningKey::generate_from_rng(rng);
57
58 Self { inner: signing_key }
59 }
60
61 fn public_key(&self) -> PublicKey {
63 let verifying_key = self.inner.verifying_key();
64 PublicKey { inner: *verifying_key }
65 }
66
67 fn sign(&self, message: Word) -> Signature {
69 let message_digest = hash_message(message);
70 self.sign_prehash(message_digest)
71 }
72
73 fn sign_prehash(&self, message_digest: [u8; 32]) -> Signature {
75 let (signature_inner, recovery_id) = self
76 .inner
77 .sign_prehash_recoverable(&message_digest)
78 .expect("failed to generate signature");
79
80 let (r, s) = signature_inner.split_scalars();
81
82 Signature {
83 r: r.to_bytes().into(),
84 s: s.to_bytes().into(),
85 v: recovery_id.into(),
86 }
87 }
88
89 fn get_shared_secret(&self, pk_e: EphemeralPublicKey) -> SharedSecret {
92 let shared_secret_inner = diffie_hellman(self.inner.as_nonzero_scalar(), pk_e.as_affine());
93
94 SharedSecret::new(shared_secret_inner)
95 }
96}
97
98impl ZeroizeOnDrop for SecretKey {}
101
102impl PartialEq for SecretKey {
103 fn eq(&self, other: &Self) -> bool {
104 use subtle::ConstantTimeEq;
105 self.to_bytes().ct_eq(&other.to_bytes()).into()
106 }
107}
108
109impl Eq for SecretKey {}
110
111#[derive(Clone, Eq, PartialEq, SilentDebug, SilentDisplay)] pub struct SigningKey(SecretKey);
117
118impl SigningKey {
119 #[cfg(feature = "std")]
123 #[allow(clippy::new_without_default)]
124 pub fn new() -> Self {
125 let mut rng = rand::rng();
126 Self::with_rng(&mut rng)
127 }
128
129 pub fn with_rng<R: CryptoRng>(rng: &mut R) -> Self {
131 Self(SecretKey::with_rng(rng))
132 }
133
134 pub fn public_key(&self) -> PublicKey {
136 self.0.public_key()
137 }
138
139 pub fn sign(&self, message: Word) -> Signature {
141 self.0.sign(message)
142 }
143
144 pub fn sign_prehash(&self, message_digest: [u8; 32]) -> Signature {
146 self.0.sign_prehash(message_digest)
147 }
148}
149
150impl From<SecretKey> for SigningKey {
151 fn from(secret_key: SecretKey) -> Self {
152 Self(secret_key)
153 }
154}
155
156impl ZeroizeOnDrop for SigningKey {}
159
160impl Serializable for SigningKey {
161 fn write_into<W: ByteWriter>(&self, target: &mut W) {
162 self.0.write_into(target);
163 }
164}
165
166impl Deserializable for SigningKey {
167 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
168 Ok(Self(SecretKey::read_from(source)?))
169 }
170}
171
172#[derive(Clone, Eq, PartialEq, SilentDebug, SilentDisplay)] pub struct KeyExchangeKey(SecretKey);
178
179impl KeyExchangeKey {
180 #[cfg(feature = "std")]
184 #[allow(clippy::new_without_default)]
185 pub fn new() -> Self {
186 let mut rng = rand::rng();
187 Self::with_rng(&mut rng)
188 }
189
190 pub fn with_rng<R: CryptoRng>(rng: &mut R) -> Self {
192 Self(SecretKey::with_rng(rng))
193 }
194
195 pub fn public_key(&self) -> PublicKey {
197 self.0.public_key()
198 }
199
200 pub fn get_shared_secret(&self, pk_e: EphemeralPublicKey) -> SharedSecret {
203 self.0.get_shared_secret(pk_e)
204 }
205}
206
207impl From<SecretKey> for KeyExchangeKey {
208 fn from(value: SecretKey) -> Self {
209 Self(value)
210 }
211}
212
213impl ZeroizeOnDrop for KeyExchangeKey {}
216
217impl Serializable for KeyExchangeKey {
218 fn write_into<W: ByteWriter>(&self, target: &mut W) {
219 self.0.write_into(target);
220 }
221}
222
223impl Deserializable for KeyExchangeKey {
224 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
225 Ok(Self(SecretKey::read_from(source)?))
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
234pub struct PublicKey {
235 pub(crate) inner: VerifyingKey,
236}
237
238impl PublicKey {
239 pub fn to_commitment(&self) -> Word {
244 <Self as SequentialCommit>::to_commitment(self)
245 }
246
247 pub fn verify(&self, message: Word, signature: &Signature) -> bool {
249 let message_digest = hash_message(message);
250 self.verify_prehash(message_digest, signature)
251 }
252
253 pub fn verify_prehash(&self, message_digest: [u8; 32], signature: &Signature) -> bool {
255 let signature_inner = ecdsa::Signature::from_scalars(*signature.r(), *signature.s());
256
257 match signature_inner {
258 Ok(signature) => self.inner.verify_prehash(&message_digest, &signature).is_ok(),
259 Err(_) => false,
260 }
261 }
262
263 pub fn recover_from(message: Word, signature: &Signature) -> Result<Self, PublicKeyError> {
266 let message_digest = hash_message(message);
267 let signature_data = ecdsa::Signature::from_scalars(*signature.r(), *signature.s())
268 .map_err(|_| PublicKeyError::RecoveryFailed)?;
269
270 let verifying_key = VerifyingKey::recover_from_prehash(
271 &message_digest,
272 &signature_data,
273 RecoveryId::from_byte(signature.v()).ok_or(PublicKeyError::RecoveryFailed)?,
274 )
275 .map_err(|_| PublicKeyError::RecoveryFailed)?;
276
277 Ok(Self { inner: verifying_key })
278 }
279
280 pub fn from_der(bytes: &[u8]) -> Result<Self, DeserializationError> {
285 let verifying_key = VerifyingKey::from_public_key_der(bytes)
286 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
287 Ok(PublicKey { inner: verifying_key })
288 }
289}
290
291impl SequentialCommit for PublicKey {
292 type Commitment = Word;
293
294 fn to_elements(&self) -> Vec<Felt> {
295 bytes_to_packed_u32_elements(&self.to_bytes())
296 }
297}
298
299#[derive(Debug, Error)]
300pub enum PublicKeyError {
301 #[error("Could not recover the public key from the message and signature")]
302 RecoveryFailed,
303}
304
305#[derive(Debug, Clone, PartialEq, Eq)]
350pub struct Signature {
351 r: [u8; SCALARS_SIZE_BYTES],
352 s: [u8; SCALARS_SIZE_BYTES],
353 v: u8,
354}
355
356impl Signature {
357 pub fn r(&self) -> &[u8; SCALARS_SIZE_BYTES] {
359 &self.r
360 }
361
362 pub fn s(&self) -> &[u8; SCALARS_SIZE_BYTES] {
364 &self.s
365 }
366
367 pub fn v(&self) -> u8 {
369 self.v
370 }
371
372 pub fn verify(&self, message: Word, pub_key: &PublicKey) -> bool {
374 pub_key.verify(message, self)
375 }
376
377 pub fn to_sec1_bytes(&self) -> [u8; SIGNATURE_STANDARD_BYTES] {
381 let mut bytes = [0u8; 2 * SCALARS_SIZE_BYTES];
382 bytes[0..SCALARS_SIZE_BYTES].copy_from_slice(self.r());
383 bytes[SCALARS_SIZE_BYTES..2 * SCALARS_SIZE_BYTES].copy_from_slice(self.s());
384 bytes
385 }
386
387 pub fn from_sec1_bytes_and_recovery_id(
393 bytes: [u8; SIGNATURE_STANDARD_BYTES],
394 recovery_id: u8,
395 ) -> Result<Self, DeserializationError> {
396 let mut r = [0u8; SCALARS_SIZE_BYTES];
397 let mut s = [0u8; SCALARS_SIZE_BYTES];
398 r.copy_from_slice(&bytes[0..SCALARS_SIZE_BYTES]);
399 s.copy_from_slice(&bytes[SCALARS_SIZE_BYTES..2 * SCALARS_SIZE_BYTES]);
400
401 if recovery_id > 3 {
402 return Err(DeserializationError::InvalidValue(r#"Invalid recovery ID"#.to_string()));
403 }
404
405 Ok(Signature { r, s, v: recovery_id })
406 }
407
408 pub fn from_der(bytes: &[u8], mut recovery_id: u8) -> Result<Self, DeserializationError> {
414 if recovery_id > 3 {
415 return Err(DeserializationError::InvalidValue(r#"Invalid recovery ID"#.to_string()));
416 }
417
418 let sig = ecdsa::Signature::from_der(bytes)
419 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
420
421 let high_s = sig.s().is_high();
424 if bool::from(high_s) {
425 recovery_id ^= 1;
430 }
431 let sig = sig.normalize_s();
432
433 let (r, s) = sig.split_scalars();
434
435 Ok(Signature {
436 r: <[u8; SCALARS_SIZE_BYTES]>::from(r.to_bytes()),
437 s: <[u8; SCALARS_SIZE_BYTES]>::from(s.to_bytes()),
438 v: recovery_id,
439 })
440 }
441}
442
443impl Serializable for SecretKey {
447 fn write_into<W: ByteWriter>(&self, target: &mut W) {
448 let mut buffer = Vec::with_capacity(SECRET_KEY_BYTES);
449 let sk_bytes: [u8; SECRET_KEY_BYTES] = self.inner.to_bytes().into();
450 buffer.extend_from_slice(&sk_bytes);
451
452 target.write_bytes(&buffer);
453 }
454}
455
456impl Deserializable for SecretKey {
457 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
458 let mut bytes: [u8; SECRET_KEY_BYTES] = source.read_array()?;
459
460 let signing_key = ecdsa::SigningKey::from_slice(&bytes)
461 .map_err(|_| DeserializationError::InvalidValue("Invalid secret key".to_string()))?;
462 bytes.zeroize();
463
464 Ok(Self { inner: signing_key })
465 }
466}
467
468impl Serializable for PublicKey {
469 fn write_into<W: ByteWriter>(&self, target: &mut W) {
470 let encoded = self.inner.to_sec1_point(true);
472
473 target.write_bytes(encoded.as_bytes());
474 }
475}
476
477impl Deserializable for PublicKey {
478 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
479 let bytes: [u8; PUBLIC_KEY_BYTES] = source.read_array()?;
480
481 let verifying_key = VerifyingKey::from_sec1_bytes(&bytes)
482 .map_err(|_| DeserializationError::InvalidValue("Invalid public key".to_string()))?;
483
484 Ok(Self { inner: verifying_key })
485 }
486}
487
488impl fmt::Display for PublicKey {
489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490 crate::utils::write_hex(f, &self.to_bytes())
491 }
492}
493
494impl Serializable for Signature {
495 fn write_into<W: ByteWriter>(&self, target: &mut W) {
496 let mut bytes = [0u8; SIGNATURE_BYTES];
497 bytes[0..SCALARS_SIZE_BYTES].copy_from_slice(self.r());
498 bytes[SCALARS_SIZE_BYTES..2 * SCALARS_SIZE_BYTES].copy_from_slice(self.s());
499 bytes[2 * SCALARS_SIZE_BYTES] = self.v();
500 target.write_bytes(&bytes);
501 }
502}
503
504impl Deserializable for Signature {
505 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
506 let r: [u8; SCALARS_SIZE_BYTES] = source.read_array()?;
507 let s: [u8; SCALARS_SIZE_BYTES] = source.read_array()?;
508 let v: u8 = source.read_u8()?;
509
510 if v > 3 {
511 Err(DeserializationError::InvalidValue(r#"Invalid recovery ID"#.to_string()))
512 } else {
513 Ok(Signature { r, s, v })
514 }
515 }
516}
517
518impl fmt::Display for Signature {
519 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520 crate::utils::write_hex(f, &self.to_bytes())
521 }
522}
523
524fn hash_message(message: Word) -> [u8; 32] {
529 use sha3::{Digest, Keccak256};
530 let mut hasher = Keccak256::new();
531 let message_bytes: [u8; 32] = message.into();
532 hasher.update(message_bytes);
533 hasher.finalize().into()
534}