1use core::fmt::{Debug};
15
16use curve25519_dalek::constants;
17use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
18use curve25519_dalek::scalar::Scalar;
19
20use super::*;
21use crate::context::{SigningTranscript, SigningContext};
22
23pub const SIGNATURE_LENGTH: usize = 64;
27
28#[allow(non_snake_case)]
33#[derive(Clone, Copy, Eq, PartialEq)]
34pub struct Signature {
35 pub(crate) R: CompressedRistretto,
45
46 pub(crate) s: Scalar,
56}
57
58impl Debug for Signature {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s)
61 }
62}
63
64pub(crate) fn check_scalar(bytes: [u8; 32]) -> SignatureResult<Scalar> {
65 if bytes[31] & 0b11110000 == 0 {
74 #[allow(deprecated)] return Ok(Scalar::from_bits(bytes));
76 }
77
78 crate::scalar_from_canonical_bytes(bytes).ok_or(SignatureError::ScalarFormatError)
79}
80
81impl Signature {
82 const DESCRIPTION: &'static str = "A 64 byte Ristretto Schnorr signature";
83 #[inline]
92 pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
93 let mut bytes: [u8; SIGNATURE_LENGTH] = [0u8; SIGNATURE_LENGTH];
94 bytes[..32].copy_from_slice(&self.R.as_bytes()[..]);
95 bytes[32..].copy_from_slice(&self.s.as_bytes()[..]);
96 bytes[63] |= 128;
97 bytes
98 }
99
100 #[inline]
115 pub fn from_bytes(bytes: &[u8]) -> SignatureResult<Signature> {
116 if bytes.len() != SIGNATURE_LENGTH {
117 return Err(SignatureError::BytesLengthError {
118 name: "Signature",
119 description: Signature::DESCRIPTION,
120 length: SIGNATURE_LENGTH,
121 });
122 }
123
124 let mut lower: [u8; 32] = [0u8; 32];
125 let mut upper: [u8; 32] = [0u8; 32];
126 lower.copy_from_slice(&bytes[..32]);
127 upper.copy_from_slice(&bytes[32..]);
128 if upper[31] & 128 == 0 {
129 return Err(SignatureError::NotMarkedSchnorrkel);
130 }
131 upper[31] &= 127;
132
133 Ok(Signature { R: CompressedRistretto(lower), s: check_scalar(upper)? })
134 }
135
136 #[cfg(feature = "preaudit_deprecated")]
139 #[inline]
140 pub fn from_bytes_not_distinguished_from_ed25519(bytes: &[u8]) -> SignatureResult<Signature> {
141 if bytes.len() != SIGNATURE_LENGTH {
142 return Err(SignatureError::BytesLengthError {
143 name: "Signature",
144 description: Signature::DESCRIPTION,
145 length: SIGNATURE_LENGTH,
146 });
147 }
148 let mut bytes0: [u8; SIGNATURE_LENGTH] = [0u8; SIGNATURE_LENGTH];
149 bytes0.copy_from_slice(bytes);
150 bytes0[63] |= 128;
151 Signature::from_bytes(&bytes0[..])
152 }
153}
154
155serde_boilerplate!(Signature);
156
157impl SecretKey {
160 #[allow(non_snake_case)]
172 pub fn sign<T: SigningTranscript>(&self, mut t: T, public_key: &PublicKey) -> Signature {
173 t.proto_name(b"Schnorr-sig");
174 t.commit_point(b"sign:pk", public_key.as_compressed());
175
176 let mut r = t.witness_scalar(b"signing", &[&self.nonce]); let R = (&r * constants::RISTRETTO_BASEPOINT_TABLE).compress();
178
179 t.commit_point(b"sign:R", &R);
180
181 let k: Scalar = t.challenge_scalar(b"sign:c"); let s: Scalar = k * self.key + r;
183
184 zeroize::Zeroize::zeroize(&mut r);
185
186 Signature { R, s }
187 }
188
189 pub fn sign_doublecheck<T>(&self, t: T, public_key: &PublicKey) -> SignatureResult<Signature>
191 where
192 T: SigningTranscript + Clone,
193 {
194 let sig = self.sign(t.clone(), public_key);
195 let sig = Signature::from_bytes(&sig.to_bytes())?;
196 PublicKey::from_bytes(&public_key.to_bytes())?.verify(t, &sig).map(|()| sig)
197 }
198
199 pub fn sign_simple(&self, ctx: &[u8], msg: &[u8], public_key: &PublicKey) -> Signature {
201 let t = SigningContext::new(ctx).bytes(msg);
202 self.sign(t, public_key)
203 }
204
205 pub fn sign_simple_doublecheck(
207 &self,
208 ctx: &[u8],
209 msg: &[u8],
210 public_key: &PublicKey,
211 ) -> SignatureResult<Signature> {
212 let t = SigningContext::new(ctx).bytes(msg);
213 let sig = self.sign(t, public_key);
214 let sig = Signature::from_bytes(&sig.to_bytes())?;
215 PublicKey::from_bytes(&public_key.to_bytes())?
216 .verify_simple(ctx, msg, &sig)
217 .map(|()| sig)
218 }
219}
220
221impl PublicKey {
222 #[allow(non_snake_case)]
228 pub fn verify<T: SigningTranscript>(
229 &self,
230 mut t: T,
231 signature: &Signature,
232 ) -> SignatureResult<()> {
233 let A: &RistrettoPoint = self.as_point();
234
235 t.proto_name(b"Schnorr-sig");
236 t.commit_point(b"sign:pk", self.as_compressed());
237 t.commit_point(b"sign:R", &signature.R);
238
239 let k: Scalar = t.challenge_scalar(b"sign:c"); let R = RistrettoPoint::vartime_double_scalar_mul_basepoint(&k, &(-A), &signature.s);
241
242 if R.compress() == signature.R {
243 Ok(())
244 } else {
245 Err(SignatureError::EquationFalse)
246 }
247 }
248
249 pub fn verify_simple(
251 &self,
252 ctx: &[u8],
253 msg: &[u8],
254 signature: &Signature,
255 ) -> SignatureResult<()> {
256 let t = SigningContext::new(ctx).bytes(msg);
257 self.verify(t, signature)
258 }
259
260 #[cfg(feature = "preaudit_deprecated")]
262 #[allow(non_snake_case)]
263 pub fn verify_simple_preaudit_deprecated(
264 &self,
265 ctx: &'static [u8],
266 msg: &[u8],
267 sig: &[u8],
268 ) -> SignatureResult<()> {
269 let t = SigningContext::new(ctx).bytes(msg);
270
271 if let Ok(signature) = Signature::from_bytes(sig) {
272 return self.verify(t, &signature);
273 }
274
275 let signature = Signature::from_bytes_not_distinguished_from_ed25519(sig)?;
276
277 let mut t = merlin::Transcript::new(ctx);
278 t.append_message(b"sign-bytes", msg);
279
280 let A: &RistrettoPoint = self.as_point();
281
282 t.proto_name(b"Schnorr-sig");
283 t.commit_point(b"pk", self.as_compressed());
284 t.commit_point(b"no", &signature.R);
285
286 let k: Scalar = t.challenge_scalar(b""); let R = RistrettoPoint::vartime_double_scalar_mul_basepoint(&k, &(-A), &signature.s);
288
289 if R.compress() == signature.R {
290 Ok(())
291 } else {
292 Err(SignatureError::EquationFalse)
293 }
294 }
295}
296
297impl Keypair {
298 pub fn sign<T: SigningTranscript>(&self, t: T) -> Signature {
359 self.secret.sign(t, &self.public)
360 }
361
362 pub fn sign_simple(&self, ctx: &[u8], msg: &[u8]) -> Signature {
364 self.secret.sign_simple(ctx, msg, &self.public)
365 }
366
367 pub fn verify<T: SigningTranscript>(&self, t: T, signature: &Signature) -> SignatureResult<()> {
395 self.public.verify(t, signature)
396 }
397
398 pub fn verify_simple(
400 &self,
401 ctx: &[u8],
402 msg: &[u8],
403 signature: &Signature,
404 ) -> SignatureResult<()> {
405 self.public.verify_simple(ctx, msg, signature)
406 }
407
408 pub fn sign_doublecheck<T>(&self, t: T) -> SignatureResult<Signature>
410 where
411 T: SigningTranscript + Clone,
412 {
413 let sig = self.sign(t.clone());
414 let sig = Signature::from_bytes(&sig.to_bytes())?;
415 PublicKey::from_bytes(&self.public.to_bytes())?.verify(t, &sig).map(|()| sig)
416 }
417
418 pub fn sign_simple_doublecheck(&self, ctx: &[u8], msg: &[u8]) -> SignatureResult<Signature> {
420 let t = SigningContext::new(ctx).bytes(msg);
421 let sig = self.sign(t);
422 let sig = Signature::from_bytes(&sig.to_bytes())?;
423 PublicKey::from_bytes(&self.public.to_bytes())?
424 .verify_simple(ctx, msg, &sig)
425 .map(|()| sig)
426 }
427}
428
429#[cfg(test)]
430mod test {
431 use sha3::Shake128;
432 use curve25519_dalek::digest::{Update};
433
434 use super::super::*;
435
436 #[cfg(feature = "getrandom")]
437 #[test]
438 fn sign_verify_bytes() {
439 let good_sig: Signature;
440 let bad_sig: Signature;
441
442 let ctx = signing_context(b"good");
443
444 let good: &[u8] = "test message".as_bytes();
445 let bad: &[u8] = "wrong message".as_bytes();
446
447 let mut csprng = rand_core::OsRng;
448
449 let keypair = Keypair::generate_with(&mut csprng);
450 good_sig = keypair.sign(ctx.bytes(&good));
451 bad_sig = keypair.sign(ctx.bytes(&bad));
452
453 let good_sig = Signature::from_bytes(&good_sig.to_bytes()[..]).unwrap();
454 let bad_sig = Signature::from_bytes(&bad_sig.to_bytes()[..]).unwrap();
455
456 assert!(
457 keypair.verify(ctx.bytes(&good), &good_sig).is_ok(),
458 "Verification of a valid signature failed!"
459 );
460 assert!(
461 !keypair.verify(ctx.bytes(&good), &bad_sig).is_ok(),
462 "Verification of a signature on a different message passed!"
463 );
464 assert!(
465 !keypair.verify(ctx.bytes(&bad), &good_sig).is_ok(),
466 "Verification of a signature on a different message passed!"
467 );
468 assert!(
469 !keypair.verify(signing_context(b"bad").bytes(&good), &good_sig).is_ok(),
470 "Verification of a signature on a different message passed!"
471 );
472 }
473
474 #[cfg(feature = "getrandom")]
475 #[test]
476 fn sign_verify_xof() {
477 let good_sig: Signature;
478 let bad_sig: Signature;
479
480 let ctx = signing_context(b"testing testing 1 2 3");
481
482 let good: &[u8] = b"test message";
483 let bad: &[u8] = b"wrong message";
484
485 let prehashed_good: Shake128 = Shake128::default().chain(good);
486 let prehashed_bad: Shake128 = Shake128::default().chain(bad);
487 let mut csprng = rand_core::OsRng;
490
491 let keypair = Keypair::generate_with(&mut csprng);
492 good_sig = keypair.sign(ctx.xof(prehashed_good.clone()));
493 bad_sig = keypair.sign(ctx.xof(prehashed_bad.clone()));
494
495 let good_sig_d = Signature::from_bytes(&good_sig.to_bytes()[..]).unwrap();
496 let bad_sig_d = Signature::from_bytes(&bad_sig.to_bytes()[..]).unwrap();
497 assert_eq!(good_sig, good_sig_d);
498 assert_eq!(bad_sig, bad_sig_d);
499
500 assert!(
501 keypair.verify(ctx.xof(prehashed_good.clone()), &good_sig).is_ok(),
502 "Verification of a valid signature failed!"
503 );
504 assert!(
505 !keypair.verify(ctx.xof(prehashed_good.clone()), &bad_sig).is_ok(),
506 "Verification of a signature on a different message passed!"
507 );
508 assert!(
509 !keypair.verify(ctx.xof(prehashed_bad.clone()), &good_sig).is_ok(),
510 "Verification of a signature on a different message passed!"
511 );
512 assert!(
513 !keypair.verify(signing_context(b"oops").xof(prehashed_good), &good_sig).is_ok(),
514 "Verification of a signature on a different message passed!"
515 );
516 }
517
518 #[cfg(feature = "preaudit_deprecated")]
519 #[test]
520 fn can_verify_know_preaudit_deprecated_message() {
521 use hex_literal::hex;
522 const SIGNING_CTX: &'static [u8] = b"substrate";
523 let message = b"Verifying that I am the owner of 5G9hQLdsKQswNPgB499DeA5PkFBbgkLPJWkkS6FAM6xGQ8xD. Hash: 221455a3\n";
524 let public = hex!("b4bfa1f7a5166695eb75299fd1c4c03ea212871c342f2c5dfea0902b2c246918");
525 let public = PublicKey::from_bytes(&public[..]).unwrap();
526 let signature = hex!("5a9755f069939f45d96aaf125cf5ce7ba1db998686f87f2fb3cbdea922078741a73891ba265f70c31436e18a9acd14d189d73c12317ab6c313285cd938453202");
527 assert!(public
528 .verify_simple_preaudit_deprecated(SIGNING_CTX, message, &signature[..])
529 .is_ok());
530 }
531}