schnorrkel/keys.rs
1// -*- mode: rust; -*-
2//
3// This file is part of schnorrkel.
4// Copyright (c) 2019 isis lovecruft and Web 3 Foundation
5// See LICENSE for licensing information.
6//
7// Authors:
8// - isis agora lovecruft <isis@patternsinthevoid.net>
9// - Jeff Burdges <jeff@web3.foundation>
10
11//! ### Schnorr signatures on the 2-torsion free subgroup of ed25519, as provided by the Ristretto point compression.
12
13use core::convert::AsRef;
14use core::fmt::{Debug};
15
16use rand_core::{RngCore, CryptoRng};
17
18use curve25519_dalek::constants;
19use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
20use curve25519_dalek::scalar::Scalar;
21
22use subtle::{Choice, ConstantTimeEq};
23use zeroize::Zeroize;
24
25use crate::scalars;
26use crate::points::RistrettoBoth;
27use crate::errors::{SignatureError, SignatureResult};
28
29/// The length of a Ristretto Schnorr `MiniSecretKey`, in bytes.
30pub const MINI_SECRET_KEY_LENGTH: usize = 32;
31
32/// The length of a Ristretto Schnorr `PublicKey`, in bytes.
33pub const PUBLIC_KEY_LENGTH: usize = 32;
34
35/// The length of the "key" portion of a Ristretto Schnorr secret key, in bytes.
36const SECRET_KEY_KEY_LENGTH: usize = 32;
37
38/// The length of the "nonce" portion of a Ristretto Schnorr secret key, in bytes.
39const SECRET_KEY_NONCE_LENGTH: usize = 32;
40
41/// The length of a Ristretto Schnorr key, `SecretKey`, in bytes.
42pub const SECRET_KEY_LENGTH: usize = SECRET_KEY_KEY_LENGTH + SECRET_KEY_NONCE_LENGTH;
43
44/// The length of an Ristretto Schnorr `Keypair`, in bytes.
45pub const KEYPAIR_LENGTH: usize = SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH;
46
47/// Methods for expanding a `MiniSecretKey` into a `SecretKey`.
48///
49/// Our `SecretKey`s consist of a scalar and nonce seed, both 32 bytes,
50/// what EdDSA/Ed25519 calls an extended secret key. We normally create
51/// `SecretKey`s by expanding a `MiniSecretKey`, what Esd25519 calls
52/// a `SecretKey`. We provide two such methods, our suggested approach
53/// produces uniformly distribted secret key scalars, but another
54/// approach retains the bit clamping form Ed25519.
55pub enum ExpansionMode {
56 /// Expand the `MiniSecretKey` into a uniformly distributed
57 /// `SecretKey`.
58 ///
59 /// We produce the `SecretKey` using merlin and far more uniform
60 /// sampling, which might benefits some future protocols, and
61 /// might reduce binary size if used throughout.
62 ///
63 /// We slightly prefer this method, but some existing code uses
64 /// `Ed25519` mode, so users cannot necessarily use this mode
65 /// if they require compatability with existing systems.
66 Uniform,
67
68 /// Expand this `MiniSecretKey` into a `SecretKey` using
69 /// ed25519-style bit clamping.
70 ///
71 /// Ristretto points are represented by Ed25519 points internally
72 /// so conceivably some future standard might expose a mapping
73 /// from Ristretto to Ed25519, which makes this mode useful.
74 /// At present, there is no such exposed mapping however because
75 /// two such mappings actually exist, depending upon the branch of
76 /// the inverse square root chosen by a Ristretto implementation.
77 /// There is however a concern that such a mapping would remain
78 /// a second class citizen, meaning implementations differ and
79 /// create incompatibility.
80 ///
81 /// We weakly recommend against employing this method. We include
82 /// it primarily because early Ristretto documentation touted the
83 /// relationship with Ed25519, which led to some deployments adopting
84 /// this expansion method.
85 Ed25519,
86}
87
88/// An EdDSA-like "secret" key seed.
89///
90/// These are seeds from which we produce a real `SecretKey`, which
91/// EdDSA itself calls an extended secret key by hashing. We require
92/// homomorphic properties unavailable from these seeds, so we renamed
93/// these and reserve `SecretKey` for what EdDSA calls an extended
94/// secret key.
95#[derive(Clone, Zeroize)]
96#[zeroize(drop)]
97pub struct MiniSecretKey(pub(crate) [u8; MINI_SECRET_KEY_LENGTH]);
98
99impl Debug for MiniSecretKey {
100 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101 write!(f, "MiniSecretKey: {:?}", &self.0[..])
102 }
103}
104
105impl Eq for MiniSecretKey {}
106impl PartialEq for MiniSecretKey {
107 fn eq(&self, other: &Self) -> bool {
108 self.ct_eq(other).unwrap_u8() == 1u8
109 }
110}
111impl ConstantTimeEq for MiniSecretKey {
112 fn ct_eq(&self, other: &Self) -> Choice {
113 self.0.ct_eq(&other.0)
114 }
115}
116
117impl MiniSecretKey {
118 const DESCRIPTION: &'static str = "Analogous to ed25519 secret key as 32 bytes, see RFC8032.";
119
120 /// Avoids importing `ExpansionMode`
121 pub const UNIFORM_MODE: ExpansionMode = ExpansionMode::Uniform;
122
123 /// Avoids importing `ExpansionMode`
124 pub const ED25519_MODE: ExpansionMode = ExpansionMode::Ed25519;
125
126 /// Expand this `MiniSecretKey` into a `SecretKey`
127 ///
128 /// We produce a secret keys using merlin and more uniformly
129 /// with this method, which reduces binary size and benefits
130 /// some future protocols.
131 ///
132 /// # Examples
133 ///
134 /// ```compile_fail
135 /// # fn main() {
136 /// use rand::{Rng, rngs::OsRng};
137 /// use schnorrkel::{MiniSecretKey, SecretKey};
138 ///
139 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate_with(OsRng);
140 /// let secret_key: SecretKey = mini_secret_key.expand_uniform();
141 /// # }
142 /// ```
143 fn expand_uniform(&self) -> SecretKey {
144 let mut t = merlin::Transcript::new(b"ExpandSecretKeys");
145 t.append_message(b"mini", &self.0[..]);
146
147 let mut scalar_bytes = [0u8; 64];
148 t.challenge_bytes(b"sk", &mut scalar_bytes);
149 let key = Scalar::from_bytes_mod_order_wide(&scalar_bytes);
150
151 let mut nonce = [0u8; 32];
152 t.challenge_bytes(b"no", &mut nonce);
153
154 SecretKey { key, nonce }
155 }
156
157 /// Expand this `MiniSecretKey` into a `SecretKey` using
158 /// ed25519-style bit clamping.
159 ///
160 /// At present, there is no exposed mapping from Ristretto
161 /// to the underlying Edwards curve because Ristretto involves
162 /// an inverse square root, and thus two such mappings exist.
163 /// Ristretto could be made usable with Ed25519 keys by choosing
164 /// one mapping as standard, but doing so makes the standard more
165 /// complex, and possibly harder to implement. If anyone does
166 /// standardize the mapping to the curve then this method permits
167 /// compatible schnorrkel and ed25519 keys.
168 ///
169 /// # Examples
170 ///
171 /// ```compile_fail
172 /// # #[cfg(feature = "getrandom")]
173 /// # fn main() {
174 /// use rand::{Rng, rngs::OsRng};
175 /// use schnorrkel::{MiniSecretKey, SecretKey};
176 ///
177 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate_with(OsRng);
178 /// let secret_key: SecretKey = mini_secret_key.expand_ed25519();
179 /// # }
180 /// ```
181 fn expand_ed25519(&self) -> SecretKey {
182 use sha2::{
183 Sha512,
184 digest::{Update, FixedOutput},
185 };
186
187 let mut h = Sha512::default();
188 h.update(self.as_bytes());
189 let r = h.finalize_fixed();
190
191 // We need not clamp in a Schnorr group like Ristretto, but here
192 // we do so to improve Ed25519 comparability.
193 let mut key = [0u8; 32];
194 key.copy_from_slice(&r.as_slice()[0..32]);
195 key[0] &= 248;
196 key[31] &= 63;
197 key[31] |= 64;
198 // We then divide by the cofactor to internally keep a clean
199 // representation mod l.
200 scalars::divide_scalar_bytes_by_cofactor(&mut key);
201
202 #[allow(deprecated)] // Scalar's always reduced here, so this is OK.
203 let key = Scalar::from_bits(key);
204
205 let mut nonce = [0u8; 32];
206 nonce.copy_from_slice(&r.as_slice()[32..64]);
207
208 SecretKey { key, nonce }
209 }
210
211 /// Derive the `SecretKey` corresponding to this `MiniSecretKey`.
212 ///
213 /// We caution that `mode` must always be chosen consistently.
214 /// We slightly prefer `ExpansionMode::Uniform` here, but both
215 /// remain secure under almost all situations. There exists
216 /// deployed code using `ExpansionMode::Ed25519`, so you might
217 /// require that for compatability.
218 ///
219 /// ```
220 /// # fn main() {
221 /// use rand::{Rng, rngs::OsRng};
222 /// # #[cfg(feature = "getrandom")]
223 /// # {
224 /// use schnorrkel::{MiniSecretKey, SecretKey, ExpansionMode};
225 ///
226 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate_with(OsRng);
227 /// let secret_key: SecretKey = mini_secret_key.expand(ExpansionMode::Uniform);
228 /// # }
229 /// # }
230 /// ```
231 pub fn expand(&self, mode: ExpansionMode) -> SecretKey {
232 match mode {
233 ExpansionMode::Uniform => self.expand_uniform(),
234 ExpansionMode::Ed25519 => self.expand_ed25519(),
235 }
236 }
237
238 /// Derive the `Keypair` corresponding to this `MiniSecretKey`.
239 pub fn expand_to_keypair(&self, mode: ExpansionMode) -> Keypair {
240 self.expand(mode).into()
241 }
242
243 /// Derive the `PublicKey` corresponding to this `MiniSecretKey`.
244 pub fn expand_to_public(&self, mode: ExpansionMode) -> PublicKey {
245 self.expand(mode).to_public()
246 }
247
248 /// Convert this secret key to a byte array.
249 #[inline]
250 pub fn to_bytes(&self) -> [u8; MINI_SECRET_KEY_LENGTH] {
251 self.0
252 }
253
254 /// View this secret key as a byte array.
255 #[inline]
256 pub fn as_bytes(&self) -> &[u8; MINI_SECRET_KEY_LENGTH] {
257 &self.0
258 }
259
260 /// Construct a `MiniSecretKey` from a slice of bytes.
261 ///
262 /// # Example
263 ///
264 /// ```
265 /// use schnorrkel::{MiniSecretKey, MINI_SECRET_KEY_LENGTH};
266 ///
267 /// let secret_key_bytes: [u8; MINI_SECRET_KEY_LENGTH] = [
268 /// 157, 097, 177, 157, 239, 253, 090, 096,
269 /// 186, 132, 074, 244, 146, 236, 044, 196,
270 /// 068, 073, 197, 105, 123, 050, 105, 025,
271 /// 112, 059, 172, 003, 028, 174, 127, 096, ];
272 ///
273 /// let secret_key: MiniSecretKey = MiniSecretKey::from_bytes(&secret_key_bytes).unwrap();
274 /// ```
275 ///
276 /// # Returns
277 ///
278 /// A `Result` whose okay value is an EdDSA `MiniSecretKey` or whose error value
279 /// is an `SignatureError` wrapping the internal error that occurred.
280 #[inline]
281 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<MiniSecretKey> {
282 if bytes.len() != MINI_SECRET_KEY_LENGTH {
283 return Err(SignatureError::BytesLengthError {
284 name: "MiniSecretKey",
285 description: MiniSecretKey::DESCRIPTION,
286 length: MINI_SECRET_KEY_LENGTH,
287 });
288 }
289 let mut bits: [u8; 32] = [0u8; 32];
290 bits.copy_from_slice(&bytes[..32]);
291 Ok(MiniSecretKey(bits))
292 }
293
294 /// Generate a `MiniSecretKey` from a `csprng`.
295 ///
296 /// # Example
297 ///
298 /// ```
299 /// use rand::{Rng, rngs::OsRng};
300 /// use schnorrkel::{PublicKey, MiniSecretKey, Signature};
301 ///
302 /// let secret_key: MiniSecretKey = MiniSecretKey::generate_with(OsRng);
303 /// ```
304 ///
305 /// # Input
306 ///
307 /// A CSPRNG with a `fill_bytes()` method, e.g. `rand_chacha::ChaChaRng`
308 pub fn generate_with<R>(mut csprng: R) -> MiniSecretKey
309 where
310 R: CryptoRng + RngCore,
311 {
312 let mut sk: MiniSecretKey = MiniSecretKey([0u8; 32]);
313 csprng.fill_bytes(&mut sk.0);
314 sk
315 }
316
317 /// Generate a `MiniSecretKey` from rand's `thread_rng`.
318 ///
319 /// # Example
320 ///
321 /// ```
322 /// use schnorrkel::{PublicKey, MiniSecretKey, Signature};
323 ///
324 /// let secret_key: MiniSecretKey = MiniSecretKey::generate();
325 /// ```
326 ///
327 /// Afterwards, you can generate the corresponding public key.
328 ///
329 /// ```
330 /// # use rand::{Rng, SeedableRng};
331 /// # use rand_chacha::ChaChaRng;
332 /// # use schnorrkel::{PublicKey, MiniSecretKey, ExpansionMode, Signature};
333 /// #
334 /// # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
335 /// # let secret_key: MiniSecretKey = MiniSecretKey::generate_with(&mut csprng);
336 ///
337 /// let public_key: PublicKey = secret_key.expand_to_public(ExpansionMode::Ed25519);
338 /// ```
339 #[cfg(feature = "getrandom")]
340 pub fn generate() -> MiniSecretKey {
341 Self::generate_with(super::getrandom_or_panic())
342 }
343}
344
345serde_boilerplate!(MiniSecretKey);
346
347/// A secret key for use with Ristretto Schnorr signatures.
348///
349/// Internally, these consist of a scalar mod l along with a seed for
350/// nonce generation. In this way, we ensure all scalar arithmetic
351/// works smoothly in operations like threshold or multi-signatures,
352/// or hierarchical deterministic key derivations.
353///
354/// We keep our secret key serializaion "almost" compatable with EdDSA
355/// "expanded" secret key serializaion by multiplying the scalar by the
356/// cofactor 8, as integers, and dividing on deserializaion.
357/// We do not however attempt to keep the scalar's high bit set, especially
358/// not during hierarchical deterministic key derivations, so some Ed25519
359/// libraries might compute the public key incorrectly from our secret key.
360#[derive(Clone, Zeroize)]
361#[zeroize(drop)]
362pub struct SecretKey {
363 /// Actual public key represented as a scalar.
364 pub(crate) key: Scalar,
365 /// Seed for deriving the nonces used in signing.
366 ///
367 /// We require this be random and secret or else key compromise attacks will ensue.
368 /// Any modification here may disrupt some non-public key derivation techniques.
369 pub(crate) nonce: [u8; 32],
370}
371
372impl Debug for SecretKey {
373 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
374 write!(f, "SecretKey {{ key: {:?} nonce: {:?} }}", &self.key, &self.nonce)
375 }
376}
377
378impl Eq for SecretKey {}
379impl PartialEq for SecretKey {
380 fn eq(&self, other: &Self) -> bool {
381 self.ct_eq(other).unwrap_u8() == 1u8
382 }
383}
384impl ConstantTimeEq for SecretKey {
385 fn ct_eq(&self, other: &Self) -> Choice {
386 self.key.ct_eq(&other.key)
387 }
388}
389
390/*
391impl From<&MiniSecretKey> for SecretKey {
392 /// Construct an `SecretKey` from a `MiniSecretKey`.
393 ///
394 /// # Examples
395 ///
396 /// ```
397 /// # #[cfg(feature = "getrandom")
398 /// # fn main() {
399 /// use rand::{Rng, rngs::OsRng};
400 /// use schnorrkel::{MiniSecretKey, SecretKey};
401 ///
402 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate_with(OsRng);
403 /// let secret_key: SecretKey = SecretKey::from(&mini_secret_key);
404 /// # }
405 /// ```
406 fn from(msk: &MiniSecretKey) -> SecretKey {
407 msk.expand(ExpansionMode::Ed25519)
408 }
409}
410*/
411
412impl SecretKey {
413 const DESCRIPTION: &'static str =
414 "An ed25519-like expanded secret key as 64 bytes, as specified in RFC8032.";
415
416 /// Convert this `SecretKey` into an array of 64 bytes with.
417 ///
418 /// Returns an array of 64 bytes, with the first 32 bytes being
419 /// the secret scalar represented canonically, and the last
420 /// 32 bytes being the seed for nonces.
421 ///
422 /// # Examples
423 ///
424 /// ```
425 /// # #[cfg(feature = "getrandom")]
426 /// # {
427 /// use schnorrkel::{MiniSecretKey, SecretKey};
428 ///
429 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate();
430 /// let secret_key: SecretKey = mini_secret_key.expand(MiniSecretKey::UNIFORM_MODE);
431 /// # // was SecretKey::from(&mini_secret_key);
432 /// let secret_key_bytes: [u8; 64] = secret_key.to_bytes();
433 /// let bytes: [u8; 64] = secret_key.to_bytes();
434 /// let secret_key_again: SecretKey = SecretKey::from_bytes(&bytes[..]).unwrap();
435 /// assert_eq!(&bytes[..], & secret_key_again.to_bytes()[..]);
436 /// # }
437 /// ```
438 #[inline]
439 pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
440 let mut bytes: [u8; 64] = [0u8; 64];
441 bytes[..32].copy_from_slice(&self.key.to_bytes()[..]);
442 bytes[32..].copy_from_slice(&self.nonce[..]);
443 bytes
444 }
445
446 /// Construct an `SecretKey` from a slice of bytes.
447 ///
448 /// # Examples
449 ///
450 /// ```
451 /// use schnorrkel::{MiniSecretKey, SecretKey, ExpansionMode, SignatureError};
452 ///
453 /// # #[cfg(feature = "getrandom")]
454 /// # {
455 /// let mini_secret_key: MiniSecretKey = MiniSecretKey::generate();
456 /// let secret_key: SecretKey = mini_secret_key.expand(MiniSecretKey::ED25519_MODE);
457 /// # // was SecretKey::from(&mini_secret_key);
458 /// let bytes: [u8; 64] = secret_key.to_bytes();
459 /// let secret_key_again: SecretKey = SecretKey::from_bytes(&bytes[..]).unwrap();
460 /// assert_eq!(secret_key_again, secret_key);
461 /// # }
462 /// ```
463 #[inline]
464 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<SecretKey> {
465 if bytes.len() != SECRET_KEY_LENGTH {
466 return Err(SignatureError::BytesLengthError {
467 name: "SecretKey",
468 description: SecretKey::DESCRIPTION,
469 length: SECRET_KEY_LENGTH,
470 });
471 }
472
473 let mut key: [u8; 32] = [0u8; 32];
474 key.copy_from_slice(&bytes[00..32]);
475 let key =
476 crate::scalar_from_canonical_bytes(key).ok_or(SignatureError::ScalarFormatError)?;
477
478 let mut nonce: [u8; 32] = [0u8; 32];
479 nonce.copy_from_slice(&bytes[32..64]);
480
481 Ok(SecretKey { key, nonce })
482 }
483
484 /// Convert this `SecretKey` into an array of 64 bytes, corresponding to
485 /// an Ed25519 expanded secret key.
486 ///
487 /// Returns an array of 64 bytes, with the first 32 bytes being
488 /// the secret scalar shifted ed25519 style, and the last 32 bytes
489 /// being the seed for nonces.
490 #[inline]
491 pub fn to_ed25519_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
492 let mut bytes: [u8; 64] = [0u8; 64];
493 let mut key = self.key.to_bytes();
494 // We multiply by the cofactor to improve ed25519 compatability,
495 // while our internally using a scalar mod l.
496 scalars::multiply_scalar_bytes_by_cofactor(&mut key);
497 bytes[..32].copy_from_slice(&key[..]);
498 bytes[32..].copy_from_slice(&self.nonce[..]);
499 bytes
500 }
501
502 /* Unused tooling removed to reduce dependencies.
503 /// Convert this `SecretKey` into an Ed25519 expanded secret key.
504 #[cfg(feature = "ed25519_dalek")]
505 pub fn to_ed25519_expanded_secret_key(&self) -> ed25519_dalek::ExpandedSecretKey {
506 ed25519_dalek::ExpandedSecretKey::from_bytes(&self.to_ed25519_bytes()[..])
507 .expect("Improper serialisation of Ed25519 secret key!")
508 }
509 */
510
511 /// Construct an `SecretKey` from a slice of bytes, corresponding to
512 /// an Ed25519 expanded secret key.
513 ///
514 /// # Example
515 ///
516 /// ```
517 /// use schnorrkel::{SecretKey, SECRET_KEY_LENGTH};
518 /// use hex_literal::hex;
519 ///
520 /// let secret = hex!("28b0ae221c6bb06856b287f60d7ea0d98552ea5a16db16956849aa371db3eb51fd190cce74df356432b410bd64682309d6dedb27c76845daf388557cbac3ca34");
521 /// let public = hex!("46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a");
522 /// let secret_key = SecretKey::from_ed25519_bytes(&secret[..]).unwrap();
523 /// assert_eq!(secret_key.to_public().to_bytes(), public);
524 /// ```
525 #[inline]
526 pub fn from_ed25519_bytes(bytes: &[u8]) -> SignatureResult<SecretKey> {
527 if bytes.len() != SECRET_KEY_LENGTH {
528 return Err(SignatureError::BytesLengthError {
529 name: "SecretKey",
530 description: SecretKey::DESCRIPTION,
531 length: SECRET_KEY_LENGTH,
532 });
533 }
534
535 let mut key: [u8; 32] = [0u8; 32];
536 key.copy_from_slice(&bytes[00..32]);
537 // We divide by the cofactor to internally keep a clean
538 // representation mod l.
539 scalars::divide_scalar_bytes_by_cofactor(&mut key);
540
541 let key = Scalar::from_canonical_bytes(key);
542 if bool::from(key.is_none()) {
543 // This should never trigger for keys which come from `to_ed25519_bytes`.
544 return Err(SignatureError::InvalidKey);
545 }
546
547 let key = key.unwrap();
548 let mut nonce: [u8; 32] = [0u8; 32];
549 nonce.copy_from_slice(&bytes[32..64]);
550
551 Ok(SecretKey { key, nonce })
552 }
553
554 /// Generate an "unbiased" `SecretKey` directly from a user
555 /// suplied `csprng` uniformly, bypassing the `MiniSecretKey`
556 /// layer.
557 pub fn generate_with<R>(mut csprng: R) -> SecretKey
558 where
559 R: CryptoRng + RngCore,
560 {
561 let mut key: [u8; 64] = [0u8; 64];
562 csprng.fill_bytes(&mut key);
563 let mut nonce: [u8; 32] = [0u8; 32];
564 csprng.fill_bytes(&mut nonce);
565 SecretKey { key: Scalar::from_bytes_mod_order_wide(&key), nonce }
566 }
567
568 /// Generate an "unbiased" `SecretKey` directly,
569 /// bypassing the `MiniSecretKey` layer.
570 #[cfg(feature = "getrandom")]
571 pub fn generate() -> SecretKey {
572 Self::generate_with(super::getrandom_or_panic())
573 }
574
575 /// Derive the `PublicKey` corresponding to this `SecretKey`.
576 pub fn to_public(&self) -> PublicKey {
577 // No clamping necessary in the ristretto255 group
578 PublicKey::from_point(&self.key * constants::RISTRETTO_BASEPOINT_TABLE)
579 }
580
581 /// Derive the `PublicKey` corresponding to this `SecretKey`.
582 pub fn to_keypair(self) -> Keypair {
583 let public = self.to_public();
584 Keypair { secret: self, public }
585 }
586}
587
588serde_boilerplate!(SecretKey);
589
590/// A Ristretto Schnorr public key.
591///
592/// Internally, these are represented as a `RistrettoPoint`, meaning
593/// an Edwards point with a static guarantee to be 2-torsion free.
594///
595/// At present, we decompress `PublicKey`s into this representation
596/// during deserialization, which improves error handling, but costs
597/// a compression during signing and verification.
598#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
599pub struct PublicKey(pub(crate) RistrettoBoth);
600
601impl Debug for PublicKey {
602 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
603 write!(f, "PublicKey( {:?} )", self.0)
604 }
605}
606
607impl ConstantTimeEq for PublicKey {
608 fn ct_eq(&self, other: &PublicKey) -> Choice {
609 self.0.ct_eq(&other.0)
610 }
611}
612
613/*
614impl Zeroize for PublicKey {
615 fn zeroize(&mut self) {
616 self.0.zeroize()
617 }
618}
619*/
620
621// We should imho drop this impl but it benifits users who start with ring.
622impl AsRef<[u8]> for PublicKey {
623 fn as_ref(&self) -> &[u8] {
624 self.as_compressed().as_bytes()
625 }
626}
627
628#[rustfmt::skip]
629impl PublicKey {
630 const DESCRIPTION: &'static str = "A Ristretto Schnorr public key represented as a 32-byte Ristretto compressed point";
631
632 /// Access the compressed Ristretto form
633 pub fn as_compressed(&self) -> &CompressedRistretto { self.0.as_compressed() }
634
635 /// Extract the compressed Ristretto form
636 pub fn into_compressed(self) -> CompressedRistretto { self.0.into_compressed() }
637
638 /// Access the point form
639 pub fn as_point(&self) -> &RistrettoPoint { self.0.as_point() }
640
641 /// Extract the point form
642 pub fn into_point(self) -> RistrettoPoint { self.0.into_point() }
643
644 /// Decompress into the `PublicKey` format that also retains the
645 /// compressed form.
646 pub fn from_compressed(compressed: CompressedRistretto) -> SignatureResult<PublicKey> {
647 Ok(PublicKey(RistrettoBoth::from_compressed(compressed) ?))
648 }
649
650 /// Compress into the `PublicKey` format that also retains the
651 /// uncompressed form.
652 pub fn from_point(point: RistrettoPoint) -> PublicKey {
653 PublicKey(RistrettoBoth::from_point(point))
654 }
655
656 /// Convert this public key to a byte array.
657 /// # Example
658 ///
659 /// ```
660 /// # #[cfg(feature = "getrandom")]
661 /// # {
662 /// use schnorrkel::{SecretKey, PublicKey, PUBLIC_KEY_LENGTH, SignatureError};
663 ///
664 /// let public_key: PublicKey = SecretKey::generate().to_public();
665 /// let public_key_bytes = public_key.to_bytes();
666 /// let public_key_again: PublicKey = PublicKey::from_bytes(&public_key_bytes[..]).unwrap();
667 /// assert_eq!(public_key_bytes, public_key_again.to_bytes());
668 /// # }
669 /// ```
670 #[inline]
671 pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] {
672 self.as_compressed().to_bytes()
673 }
674
675 /// Construct a `PublicKey` from a slice of bytes.
676 ///
677 /// # Example
678 ///
679 /// ```
680 /// use schnorrkel::{PublicKey, PUBLIC_KEY_LENGTH, SignatureError};
681 ///
682 /// let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [
683 /// 208, 120, 140, 129, 177, 179, 237, 159,
684 /// 252, 160, 028, 013, 206, 005, 211, 241,
685 /// 192, 218, 001, 097, 130, 241, 020, 169,
686 /// 119, 046, 246, 029, 079, 080, 077, 084];
687 ///
688 /// let public_key = PublicKey::from_bytes(&public_key_bytes).unwrap();
689 /// assert_eq!(public_key.to_bytes(), public_key_bytes);
690 /// ```
691 ///
692 /// # Returns
693 ///
694 /// A `Result` whose okay value is an EdDSA `PublicKey` or whose error value
695 /// is an `SignatureError` describing the error that occurred.
696 #[inline]
697 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<PublicKey> {
698 Ok(PublicKey(RistrettoBoth::from_bytes_ser("PublicKey",PublicKey::DESCRIPTION,bytes) ?))
699 }
700}
701
702impl From<SecretKey> for PublicKey {
703 fn from(source: SecretKey) -> PublicKey {
704 source.to_public()
705 }
706}
707
708serde_boilerplate!(PublicKey);
709
710/// A Ristretto Schnorr keypair.
711#[derive(Clone, Debug)]
712// #[derive(Clone,Zeroize)]
713// #[zeroize(drop)]
714pub struct Keypair {
715 /// The secret half of this keypair.
716 pub secret: SecretKey,
717 /// The public half of this keypair.
718 pub public: PublicKey,
719}
720
721impl Zeroize for Keypair {
722 fn zeroize(&mut self) {
723 self.secret.zeroize();
724 }
725}
726impl Drop for Keypair {
727 fn drop(&mut self) {
728 self.zeroize();
729 }
730}
731
732impl From<SecretKey> for Keypair {
733 fn from(secret: SecretKey) -> Keypair {
734 let public = secret.to_public();
735 Keypair { secret, public }
736 }
737}
738
739impl Keypair {
740 const DESCRIPTION: &'static str = "A 96 bytes Ristretto Schnorr keypair";
741 /*
742 const DESCRIPTION_LONG : &'static str =
743 "An ristretto schnorr keypair, 96 bytes in total, where the \
744 first 64 bytes contains the secret key represented as an \
745 ed25519 expanded secret key, as specified in RFC8032, and \
746 the subsequent 32 bytes gives the public key as a compressed \
747 ristretto point.";
748 */
749
750 /// Serialize `Keypair` to bytes.
751 ///
752 /// # Returns
753 ///
754 /// A byte array `[u8; KEYPAIR_LENGTH]` consisting of first a
755 /// `SecretKey` serialized canonically, and next the Ristterro
756 /// `PublicKey`
757 ///
758 /// # Examples
759 ///
760 /// ```
761 /// # #[cfg(feature = "getrandom")]
762 /// # {
763 /// use schnorrkel::{Keypair, KEYPAIR_LENGTH};
764 ///
765 /// let keypair: Keypair = Keypair::generate();
766 /// let bytes: [u8; KEYPAIR_LENGTH] = keypair.to_bytes();
767 /// let keypair_too = Keypair::from_bytes(&bytes[..]).unwrap();
768 /// assert_eq!(&bytes[..], & keypair_too.to_bytes()[..]);
769 /// # }
770 /// ```
771 pub fn to_bytes(&self) -> [u8; KEYPAIR_LENGTH] {
772 let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH];
773
774 bytes[..SECRET_KEY_LENGTH].copy_from_slice(&self.secret.to_bytes());
775 bytes[SECRET_KEY_LENGTH..].copy_from_slice(&self.public.to_bytes());
776 bytes
777 }
778
779 /// Deserialize a `Keypair` from bytes.
780 ///
781 /// # Inputs
782 ///
783 /// * `bytes`: an `&[u8]` consisting of byte representations of
784 /// first a `SecretKey` and then the corresponding ristretto
785 /// `PublicKey`.
786 ///
787 /// # Examples
788 ///
789 /// ```
790 /// use schnorrkel::{Keypair, KEYPAIR_LENGTH};
791 /// use hex_literal::hex;
792 ///
793 /// // TODO: Fix test vector
794 /// // let keypair_bytes = hex!("28b0ae221c6bb06856b287f60d7ea0d98552ea5a16db16956849aa371db3eb51fd190cce74df356432b410bd64682309d6dedb27c76845daf388557cbac3ca3446ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a");
795 /// // let keypair: Keypair = Keypair::from_bytes(&keypair_bytes[..]).unwrap();
796 /// // assert_eq!(&keypair_bytes[..], & keypair.to_bytes()[..]);
797 /// ```
798 ///
799 /// # Returns
800 ///
801 /// A `Result` whose okay value is an EdDSA `Keypair` or whose error value
802 /// is an `SignatureError` describing the error that occurred.
803 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<Keypair> {
804 if bytes.len() != KEYPAIR_LENGTH {
805 return Err(SignatureError::BytesLengthError {
806 name: "Keypair",
807 description: Keypair::DESCRIPTION,
808 length: KEYPAIR_LENGTH,
809 });
810 }
811 let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?;
812 let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?;
813
814 Ok(Keypair { secret, public })
815 }
816
817 /// Serialize `Keypair` to bytes with Ed25519 secret key format.
818 ///
819 /// # Returns
820 ///
821 /// A byte array `[u8; KEYPAIR_LENGTH]` consisting of first a
822 /// `SecretKey` serialized like Ed25519, and next the Ristterro
823 /// `PublicKey`
824 ///
825 ///
826 pub fn to_half_ed25519_bytes(&self) -> [u8; KEYPAIR_LENGTH] {
827 let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH];
828
829 bytes[..SECRET_KEY_LENGTH].copy_from_slice(&self.secret.to_ed25519_bytes());
830 bytes[SECRET_KEY_LENGTH..].copy_from_slice(&self.public.to_bytes());
831 bytes
832 }
833
834 /// Deserialize a `Keypair` from bytes with Ed25519 style `SecretKey` format.
835 ///
836 /// # Inputs
837 ///
838 /// * `bytes`: an `&[u8]` representing the scalar for the secret key, and a
839 /// compressed Ristretto point, both as bytes.
840 ///
841 /// # Examples
842 ///
843 /// ```
844 /// use schnorrkel::{Keypair, KEYPAIR_LENGTH};
845 /// use hex_literal::hex;
846 ///
847 /// let keypair_bytes = hex!("28b0ae221c6bb06856b287f60d7ea0d98552ea5a16db16956849aa371db3eb51fd190cce74df356432b410bd64682309d6dedb27c76845daf388557cbac3ca3446ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a");
848 /// let keypair: Keypair = Keypair::from_half_ed25519_bytes(&keypair_bytes[..]).unwrap();
849 /// assert_eq!(&keypair_bytes[..], & keypair.to_half_ed25519_bytes()[..]);
850 /// ```
851 ///
852 /// # Returns
853 ///
854 /// A `Result` whose okay value is an EdDSA `Keypair` or whose error value
855 /// is an `SignatureError` describing the error that occurred.
856 pub fn from_half_ed25519_bytes(bytes: &[u8]) -> SignatureResult<Keypair> {
857 if bytes.len() != KEYPAIR_LENGTH {
858 return Err(SignatureError::BytesLengthError {
859 name: "Keypair",
860 description: Keypair::DESCRIPTION,
861 length: KEYPAIR_LENGTH,
862 });
863 }
864 let secret = SecretKey::from_ed25519_bytes(&bytes[..SECRET_KEY_LENGTH])?;
865 let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?;
866
867 Ok(Keypair { secret, public })
868 }
869
870 /// Generate a Ristretto Schnorr `Keypair` directly,
871 /// bypassing the `MiniSecretKey` layer.
872 ///
873 /// # Example
874 ///
875 /// ```
876 /// # fn main() {
877 ///
878 /// use rand::{Rng, rngs::OsRng};
879 /// # #[cfg(feature = "getrandom")]
880 /// use schnorrkel::Keypair;
881 /// use schnorrkel::Signature;
882 ///
883 /// # #[cfg(feature = "getrandom")]
884 /// let keypair: Keypair = Keypair::generate_with(OsRng);
885 ///
886 /// # }
887 /// ```
888 ///
889 /// # Input
890 ///
891 /// A CSPRNG with a `fill_bytes()` method, e.g. `rand_chacha::ChaChaRng`.
892 ///
893 /// We generate a `SecretKey` directly bypassing `MiniSecretKey`,
894 /// so our secret keys do not satisfy the high bit "clamping"
895 /// imposed on Ed25519 keys.
896 pub fn generate_with<R>(csprng: R) -> Keypair
897 where
898 R: CryptoRng + RngCore,
899 {
900 let secret: SecretKey = SecretKey::generate_with(csprng);
901 let public: PublicKey = secret.to_public();
902
903 Keypair { public, secret }
904 }
905
906 /// Generate a Ristretto Schnorr `Keypair` directly, from a user
907 /// suplied `csprng`, bypassing the `MiniSecretKey` layer.
908 #[cfg(feature = "getrandom")]
909 pub fn generate() -> Keypair {
910 Self::generate_with(super::getrandom_or_panic())
911 }
912}
913
914serde_boilerplate!(Keypair);
915
916#[cfg(test)]
917mod test {
918 // use std::vec::Vec;
919 use super::*;
920
921 /*
922 TODO: Use some Ristretto point to do this test correctly.
923 use curve25519_dalek::edwards::{CompressedEdwardsY}; // EdwardsPoint
924 #[test]
925 fn public_key_from_bytes() {
926 #[rustfmt::skip]
927 static ED25519_PUBLIC_KEY : CompressedEdwardsY = CompressedEdwardsY([
928 215, 090, 152, 001, 130, 177, 010, 183,
929 213, 075, 254, 211, 201, 100, 007, 058,
930 014, 225, 114, 243, 218, 166, 035, 037,
931 175, 002, 026, 104, 247, 007, 081, 026, ]);
932 let pk = ED25519_PUBLIC_KEY.decompress().unwrap();
933 // let pk = unsafe { std::mem::transmute::<EdwardsPoint,RistrettoPoint>(pk) };
934 let point = super::super::ed25519::edwards_to_ristretto(pk).unwrap();
935 let ristretto_public_key = PublicKey::from_point(point);
936
937 assert_eq!(
938 ristretto_public_key.to_ed25519_public_key_bytes(),
939 pk.mul_by_cofactor().compress().0
940 );
941
942 // Make another function so that we can test the ? operator.
943 fn do_the_test(s: &[u8]) -> Result<PublicKey, SignatureError> {
944 let public_key = PublicKey::from_bytes(s) ?;
945 Ok(public_key)
946 }
947 assert_eq!(
948 do_the_test(ristretto_public_key.as_ref()),
949 Ok(ristretto_public_key)
950 );
951 assert_eq!(
952 do_the_test(&ED25519_PUBLIC_KEY.0), // Not a Ristretto public key
953 Err(SignatureError::PointDecompressionError)
954 );
955 }
956 */
957
958 #[test]
959 fn derives_from_core() {
960 let pk_d = PublicKey::default();
961 debug_assert_eq!(pk_d.as_point().compress(), CompressedRistretto::default());
962 debug_assert_eq!(pk_d.as_compressed().decompress().unwrap(), RistrettoPoint::default());
963 }
964
965 #[cfg(feature = "getrandom")]
966 #[test]
967 fn keypair_zeroize() {
968 let mut csprng = rand_core::OsRng;
969
970 let mut keypair = Keypair::generate_with(&mut csprng);
971
972 keypair.zeroize();
973
974 fn as_bytes<T>(x: &T) -> &[u8] {
975 use core::mem;
976 use core::slice;
977
978 unsafe { slice::from_raw_parts(x as *const T as *const u8, mem::size_of_val(x)) }
979 }
980
981 assert!(!as_bytes(&keypair).iter().all(|x| *x == 0u8));
982 }
983
984 #[cfg(feature = "getrandom")]
985 #[test]
986 fn pubkey_from_mini_secret_and_expanded_secret() {
987 let mut csprng = rand_core::OsRng;
988
989 let mini_secret: MiniSecretKey = MiniSecretKey::generate_with(&mut csprng);
990 let secret: SecretKey = mini_secret.expand(ExpansionMode::Ed25519);
991 let public_from_mini_secret: PublicKey =
992 mini_secret.expand_to_public(ExpansionMode::Ed25519);
993 let public_from_secret: PublicKey = secret.to_public();
994 assert!(public_from_mini_secret == public_from_secret);
995 let secret: SecretKey = mini_secret.expand(ExpansionMode::Uniform);
996 let public_from_mini_secret: PublicKey =
997 mini_secret.expand_to_public(ExpansionMode::Uniform);
998 let public_from_secret: PublicKey = secret.to_public();
999 assert!(public_from_mini_secret == public_from_secret);
1000 }
1001
1002 #[cfg(feature = "getrandom")]
1003 #[test]
1004 fn secret_key_can_be_converted_to_ed25519_bytes_and_back() {
1005 let count = if cfg!(debug_assertions) { 200000 } else { 2000000 };
1006
1007 for _ in 0..count {
1008 let key = SecretKey::generate();
1009 let bytes = key.to_ed25519_bytes();
1010 let key_deserialized = SecretKey::from_ed25519_bytes(&bytes).unwrap();
1011 assert_eq!(key_deserialized, key);
1012 }
1013 }
1014}