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
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Scheme defined in 2018 paper, CT-RSA 2018 (eprint 2017/1197), section 4.2.

use crate::{SignatureGroup, VerkeyGroupVec, ate_2_pairing};
use amcl_wrapper::field_elem::{FieldElement, FieldElementVector};
use crate::keys::{Sigkey, Params, Verkey};
use crate::errors::PSError;
use crate::signature::Signature as Sig16;
use amcl_wrapper::group_elem::{GroupElement, GroupElementVector};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Signature {
    pub m_prime: FieldElement,
    pub sig: Sig16
}

impl Signature {
    /// Create a new signature. The signature generation involves generating random values for `m'`
    /// and `sigma_1` so different calls to this method with same messages and signing key will give
    /// different value
    pub fn new(messages: &[FieldElement], sigkey: &Sigkey) -> Result<Self, PSError> {
        let m_prime = FieldElement::random();
        let sigma_1 = SignatureGroup::random();
        let sigma_2 = Self::sign_with_given_sigma_1(messages, &m_prime, sigkey, 0, &sigma_1)?;
        Ok(Self { m_prime, sig: Sig16 {sigma_1, sigma_2} })
    }

    /// Create a new signature. The signature generation involves generating `m'` by hashing the messages
    /// but generating a random value for `sigma_1` so different calls to this method with same messages
    /// and signing key will give different value
    pub fn new_with_deterministic_m(messages: &[FieldElement], sigkey: &Sigkey) -> Result<Self, PSError> {
        let m_prime = Self::generate_m_prime_from_messages(messages);
        let sigma_1 = SignatureGroup::random();
        let sigma_2 = Self::sign_with_given_sigma_1(messages, &m_prime, sigkey, 0, &sigma_1)?;
        Ok(Self { m_prime, sig: Sig16 {sigma_1, sigma_2} })
    }

    /// Create a new signature. The signature generation doesn't involve generating any random value
    /// but the messages are hashed to get a pseudorandom values for `m'` and `sigma_1`. Hence different
    /// calls to this method with same messages and signing key will give same value
    pub fn new_deterministic(messages: &[FieldElement], sigkey: &Sigkey) -> Result<Self, PSError> {
        let (m_prime, sigma_1) = Self::generate_m_prime_and_sigma_1_from_messages(messages);
        let sigma_2 = Self::sign_with_given_sigma_1(messages, &m_prime, sigkey, 0, &sigma_1)?;
        Ok(Self { m_prime, sig: Sig16 {sigma_1, sigma_2} })
    }

    /// Verify a signature. Most of the logic is same as from the 2016 scheme
    pub fn verify(
        &self,
        mut messages: Vec<FieldElement>,
        vk: &Verkey,
        params: &Params,
    ) -> Result<bool, PSError> {
        if vk.Y_tilde.len() != (messages.len() + 1) {
            return Err(PSError::UnsupportedNoOfMessages {
                expected: vk.Y_tilde.len(),
                given: messages.len() + 1
            });
        }
        if self.sig.is_identity() {
            return Ok(false);
        }

        messages.push(self.m_prime.clone());

        Ok(Sig16::pairing_check(&self.sig, messages, vk, params))
    }

    /// Byte representation of the signature
    pub fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = vec![];
        bytes.append(&mut self.m_prime.to_bytes());
        bytes.append(&mut self.sig.to_bytes());
        bytes
    }

    /// Generate signature when first element of signature tuple is given
    fn sign_with_given_sigma_1(messages: &[FieldElement],
                                   m_prime: &FieldElement,
                                   sigkey: &Sigkey,
                                   offset: usize,
                                   h: &SignatureGroup) -> Result<SignatureGroup, PSError> {
        if sigkey.y.len() != (offset + messages.len() + 1) {
            return Err(PSError::UnsupportedNoOfMessages {
                expected: offset + messages.len() + 1,
                given: sigkey.y.len()
            });
        }
        // h^(x + y_j*m_j + y_{j+1}*m_{j+1} + y_{j+2}*m_{j+2} + ... + y_last*m') = g^{u * (x + y_j*m_j + y_{j+1}*m_{j+1} + y_{j+2}*m_{j+2} + ... + y_last*m')}
        let mut exp = sigkey.x.clone();
        for i in 0..messages.len() {
            exp += &sigkey.y[offset + i] * &messages[i];
        }
        exp += &sigkey.y[offset + messages.len()] * m_prime;
        let h_exp = h * &exp;
        Ok(h_exp)
    }

    /// Generate m' by hashing the messages. Since all messages are of
    /// same size, the is no need of a delimiter between the byte representation of the messages.
    fn generate_m_prime_from_messages(messages: &[FieldElement]) -> FieldElement {
        let mut msg_bytes = vec![];
        for i in messages {
            msg_bytes.append(&mut i.to_bytes());
        }
        FieldElement::from_msg_hash(&msg_bytes)
    }

    /// Generate m' and sigma_1, by hashing the messages. Since all messages are of
    /// same size, the is no need of a delimiter between the byte representation of the messages.
    fn generate_m_prime_and_sigma_1_from_messages(messages: &[FieldElement]) -> (FieldElement, SignatureGroup) {
        let mut msg_bytes = vec![];
        for i in messages {
            msg_bytes.append(&mut i.to_bytes());
        }
        // TODO: Hashing twice is inefficient. Expose API (a macro probably) in the wrapper to return any
        // number of group or field elements. The macro would take types like G1, G2, etc as args and count
        // them to decide the number of bytes the XOF should return and then call iterate over them and call
        // the type's from_msg_hash on the appropriate byte slice
        let m_prime = FieldElement::from_msg_hash(&msg_bytes);
        let sigma_1 = SignatureGroup::from_msg_hash(&msg_bytes);
        (m_prime, sigma_1)
    }

    pub fn check_verkey_and_messages_compat(
        messages: &[FieldElement],
        verkey: &Verkey,
    ) -> Result<(), PSError> {
        // `Y_tilde` would have a value corresponding to `m'` as well
        if (messages.len() + 1) != verkey.Y_tilde.len() {
            return Err(PSError::UnsupportedNoOfMessages {
                expected: messages.len() + 1,
                given: verkey.Y_tilde.len(),
            });
        }
        Ok(())
    }

    pub fn check_sigkey_and_messages_compat(
        messages: &[FieldElement],
        sigkey: &Sigkey,
    ) -> Result<(), PSError> {
        // `y` would have a value corresponding to `m'` as well
        if sigkey.y.len() != (messages.len() + 1) {
            return Err(PSError::UnsupportedNoOfMessages {
                expected: messages.len() + 1,
                given: sigkey.y.len(),
            });
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::keys::keygen_2018;

    #[test]
    fn test_signature_all_known_messages() {
        let params = Params::new("test".as_bytes());
        for i in 0..10 {
            let count_msgs = (i % 5) + 1;
            let (sk, vk) = keygen_2018(count_msgs, &params);
            let msgs = (0..count_msgs).map(|_| FieldElement::random()).collect::<Vec<FieldElement>>();
            let sig = Signature::new(msgs.as_slice(), &sk).unwrap();
            assert!(sig.verify(msgs, &vk, &params).unwrap());
        }
    }

    #[test]
    fn test_signature_deterministic_m_all_known_messages() {
        let params = Params::new("test".as_bytes());
        for i in 0..10 {
            let count_msgs = (i % 5) + 1;
            let (sk, vk) = keygen_2018(count_msgs, &params);
            let msgs = (0..count_msgs).map(|_| FieldElement::random()).collect::<Vec<FieldElement>>();
            let sig = Signature::new_with_deterministic_m(msgs.as_slice(), &sk).unwrap();
            assert!(sig.verify(msgs, &vk, &params).unwrap());
        }
    }

    #[test]
    fn test_deterministic_signature_all_known_messages() {
        let params = Params::new("test".as_bytes());
        for i in 0..10 {
            let count_msgs = (i % 5) + 1;
            let (sk, vk) = keygen_2018(count_msgs, &params);
            let msgs = (0..count_msgs).map(|_| FieldElement::random()).collect::<Vec<FieldElement>>();
            let sig = Signature::new_deterministic(msgs.as_slice(), &sk).unwrap();
            assert!(sig.verify(msgs, &vk, &params).unwrap());
        }
    }
}