1use crate::{sign::expanded::ExpandedSecretKey, *};
5use core::fmt::{self, Debug, Formatter};
6use elliptic_curve::{
7 common::Generate,
8 rand_core::TryCryptoRng,
9 zeroize::{Zeroize, ZeroizeOnDrop},
10};
11use shake::digest::{
12 Digest, ExtendableOutput, FixedOutput, FixedOutputReset, HashMarker, Update, XofReader,
13 common::BlockSizeUser, consts::U64, typenum::IsEqual,
14};
15use signature::Error;
16use subtle::{Choice, ConstantTimeEq};
17
18#[cfg(feature = "pkcs8")]
19use ::ed448::pkcs8::{KeypairBytes, PublicKeyBytes};
20
21pub type SecretKey = EdwardsScalarBytes;
25
26pub trait PreHash {
28 fn fill_bytes(&mut self, out: &mut [u8]);
30}
31
32#[derive(Debug)]
34pub struct PreHasherXmd<HashT>
35where
36 HashT: BlockSizeUser + Default + FixedOutput + FixedOutputReset + Update + HashMarker,
37 HashT::OutputSize: IsEqual<U64>,
38{
39 hasher: HashT,
40}
41
42impl<HashT> From<HashT> for PreHasherXmd<HashT>
43where
44 HashT: BlockSizeUser + Default + FixedOutput + FixedOutputReset + Update + HashMarker,
45 HashT::OutputSize: IsEqual<U64>,
46{
47 fn from(hasher: HashT) -> Self {
48 Self::new(hasher)
49 }
50}
51
52impl<HashT> PreHasherXmd<HashT>
53where
54 HashT: BlockSizeUser + Default + FixedOutput + FixedOutputReset + Update + HashMarker,
55 HashT::OutputSize: IsEqual<U64>,
56{
57 pub fn new(hasher: HashT) -> Self {
59 Self { hasher }
60 }
61}
62
63impl<HashT> PreHash for PreHasherXmd<HashT>
64where
65 HashT: BlockSizeUser + Default + FixedOutput + FixedOutputReset + Update + HashMarker,
66 HashT::OutputSize: IsEqual<U64>,
67{
68 fn fill_bytes(&mut self, out: &mut [u8]) {
69 out.copy_from_slice(self.hasher.finalize_reset().as_slice());
70 }
71}
72
73pub struct PreHasherXof<HashT>
75where
76 HashT: Default + ExtendableOutput + Update,
77{
78 reader: <HashT as ExtendableOutput>::Reader,
79}
80
81impl<HashT> Debug for PreHasherXof<HashT>
82where
83 HashT: Default + ExtendableOutput + Update,
84{
85 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86 f.debug_struct("SigningPreHasherXof")
87 .finish_non_exhaustive()
88 }
89}
90
91impl<HashT> PreHash for PreHasherXof<HashT>
92where
93 HashT: Default + ExtendableOutput + Update,
94{
95 fn fill_bytes(&mut self, out: &mut [u8]) {
96 self.reader.read(out);
97 }
98}
99
100impl<HashT> From<HashT> for PreHasherXof<HashT>
101where
102 HashT: Default + ExtendableOutput + Update,
103{
104 fn from(hasher: HashT) -> Self {
105 Self::new(hasher)
106 }
107}
108
109impl<HashT> PreHasherXof<HashT>
110where
111 HashT: Default + ExtendableOutput + Update,
112{
113 pub fn new(hasher: HashT) -> Self {
115 Self {
116 reader: hasher.finalize_xof(),
117 }
118 }
119}
120
121#[derive(Clone)]
123pub struct SigningKey {
124 pub(crate) secret: ExpandedSecretKey,
125}
126
127impl Debug for SigningKey {
128 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
129 f.debug_struct("SigningKey")
130 .field("verifying_key", &self.secret.public_key)
131 .finish_non_exhaustive()
132 }
133}
134
135impl Generate for SigningKey {
136 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
137 let mut secret_scalar = SecretKey::default();
138 rng.try_fill_bytes(secret_scalar.as_mut())?;
139 assert!(!secret_scalar.iter().all(|&v| v == 0));
140 Ok(Self {
141 secret: ExpandedSecretKey::from(&secret_scalar),
142 })
143 }
144}
145
146impl Zeroize for SigningKey {
147 fn zeroize(&mut self) {
148 self.secret.zeroize();
149 }
150}
151
152impl Drop for SigningKey {
153 fn drop(&mut self) {
154 self.secret.zeroize();
155 }
156}
157
158impl ZeroizeOnDrop for SigningKey {}
159
160impl ConstantTimeEq for SigningKey {
161 fn ct_eq(&self, other: &Self) -> Choice {
162 self.secret.seed.ct_eq(&other.secret.seed)
163 }
164}
165
166impl Eq for SigningKey {}
167
168impl PartialEq for SigningKey {
169 fn eq(&self, other: &Self) -> bool {
170 self.ct_eq(other).into()
171 }
172}
173
174impl From<SecretKey> for SigningKey {
175 fn from(secret_scalar: SecretKey) -> Self {
176 Self::from(&secret_scalar)
177 }
178}
179
180impl From<&SecretKey> for SigningKey {
181 fn from(secret_scalar: &SecretKey) -> Self {
182 Self {
183 secret: ExpandedSecretKey::from(secret_scalar),
184 }
185 }
186}
187
188#[cfg(feature = "alloc")]
189impl TryFrom<Vec<u8>> for SigningKey {
190 type Error = &'static str;
191
192 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
193 Self::try_from(value.as_slice())
194 }
195}
196
197#[cfg(feature = "alloc")]
198impl TryFrom<&Vec<u8>> for SigningKey {
199 type Error = &'static str;
200
201 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
202 Self::try_from(value.as_slice())
203 }
204}
205
206impl TryFrom<&[u8]> for SigningKey {
207 type Error = &'static str;
208
209 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
210 if value.len() != SECRET_KEY_LENGTH {
211 return Err("Invalid length for a signing key");
212 }
213 Ok(Self::from(
214 EdwardsScalarBytes::try_from(value).expect("Invalid length"),
215 ))
216 }
217}
218
219#[cfg(feature = "alloc")]
220impl TryFrom<Box<[u8]>> for SigningKey {
221 type Error = &'static str;
222
223 fn try_from(value: Box<[u8]>) -> Result<Self, Self::Error> {
224 Self::try_from(value.as_ref())
225 }
226}
227
228impl<D> signature::DigestSigner<D, Signature> for SigningKey
229where
230 D: Default + FixedOutput + HashMarker + Update,
231{
232 fn try_sign_digest<F: Fn(&mut D) -> Result<(), Error>>(
233 &self,
234 f: F,
235 ) -> Result<Signature, Error> {
236 let mut digest = D::new();
237 f(&mut digest)?;
238 let sig = self.secret.sign_prehashed(&[], &digest.finalize())?;
239 Ok(sig.into())
240 }
241}
242
243impl signature::hazmat::PrehashSigner<Signature> for SigningKey {
244 fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature, Error> {
245 let sig = self.secret.sign_prehashed(&[], prehash)?;
246 Ok(sig.into())
247 }
248}
249
250impl signature::Signer<Signature> for SigningKey {
251 fn try_sign(&self, msg: &[u8]) -> Result<Signature, Error> {
252 let sig = self.secret.sign_raw(msg)?;
253 Ok(sig.into())
254 }
255}
256
257impl<D> signature::DigestSigner<D, Signature> for Context<'_, '_, SigningKey>
258where
259 D: Default + FixedOutput + HashMarker + Update,
260{
261 fn try_sign_digest<F: Fn(&mut D) -> Result<(), Error>>(
262 &self,
263 f: F,
264 ) -> Result<Signature, Error> {
265 let mut digest = D::new();
266 f(&mut digest)?;
267 let sig = self
268 .key
269 .secret
270 .sign_prehashed(self.value, &digest.finalize())?;
271 Ok(sig.into())
272 }
273}
274
275impl signature::hazmat::PrehashSigner<Signature> for Context<'_, '_, SigningKey> {
276 fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature, Error> {
277 let sig = self.key.secret.sign_prehashed(self.value, prehash)?;
278 Ok(sig.into())
279 }
280}
281
282impl signature::Signer<Signature> for Context<'_, '_, SigningKey> {
283 fn try_sign(&self, msg: &[u8]) -> Result<Signature, Error> {
284 let sig = self.key.secret.sign_ctx(self.value, msg)?;
285 Ok(sig.into())
286 }
287}
288
289impl<D> signature::DigestVerifier<D, Signature> for SigningKey
290where
291 D: Default + FixedOutput + HashMarker + Update,
292{
293 fn verify_digest<F: Fn(&mut D) -> Result<(), Error>>(
294 &self,
295 f: F,
296 signature: &Signature,
297 ) -> Result<(), Error> {
298 <VerifyingKey as signature::DigestVerifier<D, Signature>>::verify_digest(
299 &self.secret.public_key,
300 f,
301 signature,
302 )
303 }
304}
305
306impl signature::Verifier<Signature> for SigningKey {
307 fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
308 self.secret.public_key.verify_raw(signature, msg)
309 }
310}
311
312#[cfg(all(feature = "alloc", feature = "pkcs8"))]
313impl pkcs8::EncodePrivateKey for SigningKey {
314 fn to_pkcs8_der(&self) -> pkcs8::Result<pkcs8::SecretDocument> {
315 KeypairBytes::from(self).to_pkcs8_der()
316 }
317}
318
319#[cfg(all(feature = "alloc", feature = "pkcs8"))]
320impl pkcs8::spki::DynSignatureAlgorithmIdentifier for SigningKey {
321 fn signature_algorithm_identifier(
322 &self,
323 ) -> pkcs8::spki::Result<pkcs8::spki::AlgorithmIdentifierOwned> {
324 Ok(pkcs8::spki::AlgorithmIdentifier {
326 oid: super::ALGORITHM_OID,
327 parameters: None,
328 })
329 }
330}
331
332#[cfg(feature = "pkcs8")]
333impl TryFrom<KeypairBytes> for SigningKey {
334 type Error = pkcs8::Error;
335
336 fn try_from(value: KeypairBytes) -> Result<Self, Self::Error> {
337 Self::try_from(&value)
338 }
339}
340
341#[cfg(feature = "pkcs8")]
342impl TryFrom<&KeypairBytes> for SigningKey {
343 type Error = pkcs8::Error;
344
345 fn try_from(value: &KeypairBytes) -> Result<Self, Self::Error> {
346 let signing_key =
347 SigningKey::from(SecretKey::try_from(&value.secret_key[..]).expect("invalid length"));
348
349 if let Some(public_bytes) = &value.public_key {
350 let verifying_key = VerifyingKey::from_bytes(public_bytes.as_ref())
351 .map_err(|_| pkcs8::KeyError::Invalid)?;
352 if signing_key.verifying_key() != verifying_key {
353 return Err(pkcs8::KeyError::Invalid.into());
354 }
355 }
356 Ok(signing_key)
357 }
358}
359
360#[cfg(feature = "pkcs8")]
361impl From<&SigningKey> for KeypairBytes {
362 fn from(signing_key: &SigningKey) -> Self {
363 KeypairBytes {
364 secret_key: signing_key.to_bytes().into(),
365 public_key: Some(PublicKeyBytes(signing_key.verifying_key().to_bytes())),
366 }
367 }
368}
369
370#[cfg(feature = "pkcs8")]
371impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for SigningKey {
372 type Error = pkcs8::Error;
373
374 fn try_from(value: pkcs8::PrivateKeyInfoRef<'_>) -> Result<Self, Self::Error> {
375 KeypairBytes::try_from(value)?.try_into()
376 }
377}
378
379#[cfg(feature = "serde")]
380impl serdect::serde::Serialize for SigningKey {
381 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
382 where
383 S: serdect::serde::Serializer,
384 {
385 serdect::array::serialize_hex_lower_or_bin(&self.secret.seed, s)
386 }
387}
388
389#[cfg(feature = "serde")]
390impl<'de> serdect::serde::Deserialize<'de> for SigningKey {
391 fn deserialize<D>(d: D) -> Result<Self, D::Error>
392 where
393 D: serdect::serde::Deserializer<'de>,
394 {
395 let mut bytes = SecretKey::default();
396 serdect::array::deserialize_hex_or_bin(&mut bytes, d)?;
397 Ok(SigningKey::from(bytes))
398 }
399}
400
401impl SigningKey {
402 pub fn to_bytes(&self) -> SecretKey {
404 self.secret.seed
405 }
406
407 pub fn as_bytes(&self) -> &SecretKey {
409 &self.secret.seed
410 }
411
412 pub fn to_scalar(&self) -> EdwardsScalar {
417 self.secret.scalar
418 }
419
420 pub fn verifying_key(&self) -> VerifyingKey {
422 self.secret.public_key
423 }
424
425 pub fn with_context<'k, 'v>(&'k self, context: &'v [u8]) -> Context<'k, 'v, Self> {
428 Context {
429 key: self,
430 value: context,
431 }
432 }
433
434 pub fn sign_raw(&self, message: &[u8]) -> Signature {
437 let sig = self
438 .secret
439 .sign_raw(message)
440 .expect("to succeed since no context is provided");
441 sig.into()
442 }
443
444 pub fn sign_ctx(&self, context: &[u8], message: &[u8]) -> Result<Signature, Error> {
447 let sig = self.secret.sign_ctx(context, message)?;
448 Ok(sig.into())
449 }
450
451 pub fn sign_prehashed<D>(
454 &self,
455 context: Option<&[u8]>,
456 mut prehashed_message: D,
457 ) -> Result<Signature, Error>
458 where
459 D: PreHash,
460 {
461 let mut m = [0u8; 64];
462 prehashed_message.fill_bytes(&mut m);
463 let sig = self
464 .secret
465 .sign_prehashed(context.unwrap_or_default(), &m)?;
466 Ok(sig.into())
467 }
468}
469
470#[cfg(all(feature = "getrandom", feature = "serde"))]
471#[test]
472fn serialization() {
473 let signing_key = SigningKey::generate();
474
475 let bytes = serde_bare::to_vec(&signing_key).unwrap();
476 let signing_key2: SigningKey = serde_bare::from_slice(&bytes).unwrap();
477 assert_eq!(signing_key, signing_key2);
478
479 let string = serde_json::to_string(&signing_key).unwrap();
480 let signing_key3: SigningKey = serde_json::from_str(&string).unwrap();
481 assert_eq!(signing_key, signing_key3);
482}