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