1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use secp256kfun::{marker::*, Point, Scalar};

/// A one-time encrypted Schnorr signature or "adaptor signature".
///
/// Sometimes also called a "pre-signature".

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
    feature = "serde",
    derive(crate::fun::serde::Deserialize, crate::fun::serde::Serialize),
    serde(crate = "crate::fun::serde")
)]
#[cfg_attr(
    feature = "bincode",
    derive(crate::fun::bincode::Encode, crate::fun::bincode::Decode),
    bincode(crate = "crate::fun::bincode")
)]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct EncryptedSignature<S = Public> {
    /// The `R` point in the signature
    pub R: Point<EvenY, Public>,
    /// The _one-time encrypted_ `s` value of the signature.
    pub s_hat: Scalar<S, Zero>,
    /// Whether the decryptor should negate their decryption key prior to decryption.
    /// This exists as a side effect of using "x-only" (EvenY) signature nonces.
    pub needs_negation: bool,
}

impl<OldSec> EncryptedSignature<OldSec> {
    /// Marks the encrypted signature with a [`Secrecy`]. If it is marked as `Secret` the operations
    /// (e.g. verification) on the signature encryption should be done in constant time.
    ///
    /// [`Secrecy`]: secp256kfun::marker::Secrecy
    #[must_use]
    pub fn set_secrecy<NewSec: Secrecy>(self) -> EncryptedSignature<NewSec> {
        EncryptedSignature {
            R: self.R,
            s_hat: self.s_hat.set_secrecy::<NewSec>(),
            needs_negation: self.needs_negation,
        }
    }
}

#[cfg(test)]
mod test {
    #[cfg(feature = "serde")]
    #[test]
    fn encrypted_signature_serialization_roundtrip() {
        use super::*;
        use crate::{adaptor::*, fun::Scalar, Message};
        let schnorr = crate::test_instance!();
        let kp = schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
        let encryption_key = Point::random(&mut rand::thread_rng());
        let encrypted_signature = schnorr.encrypted_sign(
            &kp,
            &encryption_key,
            Message::<Public>::plain("test", b"foo"),
        );
        let serialized = bincode::serialize(&encrypted_signature).unwrap();
        assert_eq!(serialized.len(), 65);
        let deserialized = bincode::deserialize::<EncryptedSignature>(&serialized).unwrap();
        assert_eq!(encrypted_signature, deserialized);
    }
}