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
// -*- mode: rust; -*-

//! A secret key

use super::{
    errors::{InternalError::SecretKeyLengthError, *},
    known_message::*,
    signature::*,
    unknown_message::*,
};
use crate::{common::*, curve_arithmetic::*};

use ff::Field;

use rand::*;

/// A secret key
#[derive(Debug, Serialize)]
pub struct SecretKey<C: Pairing> {
    /// Generator of the first pairing group. Not secret, but needed for various
    /// operations.
    pub g:       C::G1,
    /// Generator of the second pairing group. Not secret, but needed for
    /// various operations.
    pub g_tilda: C::G2,
    #[size_length = 4]
    pub ys:      Vec<C::ScalarField>,
    pub x:       C::ScalarField,
}

impl<C: Pairing> PartialEq for SecretKey<C> {
    fn eq(&self, other: &Self) -> bool { self.ys == other.ys && self.x == other.x }
}

impl<C: Pairing> Eq for SecretKey<C> {}

impl<C: Pairing> SecretKey<C> {
    /// Generate a secret key from a `csprng`. NB: This fixes the generators to
    /// be those defined by the library.
    pub fn generate<T>(n: usize, csprng: &mut T) -> SecretKey<C>
    where
        T: Rng, {
        let mut ys: Vec<C::ScalarField> = Vec::with_capacity(n);
        for _i in 0..n {
            ys.push(C::generate_scalar(csprng));
        }

        SecretKey {
            g: C::G1::one_point(),
            g_tilda: C::G2::one_point(),
            ys,
            x: C::generate_scalar(csprng),
        }
    }

    pub fn sign_known_message<T>(
        &self,
        message: &KnownMessage<C>,
        csprng: &mut T,
    ) -> Result<Signature<C>, SignatureError>
    where
        T: Rng, {
        let ys = &self.ys;
        let ms = &message.0;
        if ms.len() > ys.len() {
            return Err(SignatureError(SecretKeyLengthError));
        }

        let mut z =
            ms.iter()
                .zip(ys.iter())
                .fold(<C::ScalarField as Field>::zero(), |mut acc, (m, y)| {
                    let mut r = *m;
                    r.mul_assign(y);
                    acc.add_assign(&r);
                    acc
                });
        z.add_assign(&self.x);
        let h = self.g.mul_by_scalar(&C::generate_scalar(csprng));

        Ok(Signature(h, h.mul_by_scalar(&z)))
    }

    // FIXME: Should this not require also a AggregateDLog proof that the user knows
    // the values being commited to?
    pub fn sign_unknown_message<T>(
        &self,
        message: &UnknownMessage<C>,
        csprng: &mut T,
    ) -> Signature<C>
    where
        T: Rng, {
        let sk = self.g.mul_by_scalar(&self.x);
        let r = C::generate_non_zero_scalar(csprng);
        let a = self.g.mul_by_scalar(&r);
        let xmr = sk.plus_point(message).mul_by_scalar(&r);
        Signature(a, xmr)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use pairing::bls12_381::Bls12;

    macro_rules! macro_test_secret_key_to_byte_conversion {
        ($function_name:ident, $pairing_type:path) => {
            #[test]
            pub fn $function_name() {
                let mut csprng = thread_rng();
                for i in 0..20 {
                    let val = SecretKey::<$pairing_type>::generate(i, &mut csprng);
                    let res_val2 = serialize_deserialize(&val);
                    assert!(res_val2.is_ok());
                    let val2 = res_val2.unwrap();
                    assert_eq!(val2, val);
                }
            }
        };
    }

    macro_test_secret_key_to_byte_conversion!(secret_key_to_byte_conversion_bls12_381, Bls12);
}