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
//! ed25519 secret key types.

use super::{constants::*, errors::*, public::*};
use crate::common::*;
use core::fmt::Debug;
use curve25519_dalek::{
    constants,
    scalar::{clamp_integer, Scalar},
};
use rand::{CryptoRng, Rng};
use sha2::{digest::Digest, Sha512};
use subtle::{Choice, ConstantTimeEq};
use zeroize::Zeroize;

/// An EdDSA secret key.
pub struct SecretKey(pub(crate) [u8; SECRET_KEY_LENGTH]);

impl ConstantTimeEq for SecretKey {
    fn ct_eq(&self, other: &Self) -> Choice { self.0.ct_eq(&other.0) }
}

impl Serial for SecretKey {
    #[inline]
    fn serial<B: Buffer>(&self, x: &mut B) {
        x.write_all(&self.0)
            .expect("Writing to buffer should succeed.")
    }
}

/// Construct a `SecretKey` from a slice of bytes.
impl Deserial for SecretKey {
    #[inline]
    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
        let mut buf = [0u8; SECRET_KEY_LENGTH];
        source.read_exact(&mut buf)?;
        Ok(SecretKey(buf))
    }
}

impl Debug for SecretKey {
    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
        write!(f, "SecretKey: {:?}", &self.0[..])
    }
}

/// Overwrite secret key material with null bytes when it goes out of scope.
impl Drop for SecretKey {
    fn drop(&mut self) { self.0.zeroize(); }
}

impl AsRef<[u8]> for SecretKey {
    fn as_ref(&self) -> &[u8] { self.as_bytes() }
}

impl SecretKey {
    /// Convert this secret key to a byte array.
    #[inline]
    pub fn to_bytes(&self) -> Box<[u8]> { Box::new(self.0) }

    /// View this secret key as a byte array.
    #[inline]
    pub fn as_bytes(&self) -> &'_ [u8; SECRET_KEY_LENGTH] { &self.0 }

    /// Construct a `SecretKey` from a slice of bytes.
    ///
    /// A `Result` whose okay value is an EdDSA `SecretKey` or whose error value
    /// is an `ProofError` wrapping the internal error that occurred.
    #[inline]
    pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, ProofError> {
        if bytes.len() != SECRET_KEY_LENGTH {
            return Err(ProofError(InternalError::BytesLength {
                name:   "SecretKey",
                length: SECRET_KEY_LENGTH,
            }));
        }
        let mut bits: [u8; 32] = [0u8; 32];
        bits.copy_from_slice(&bytes[..32]);

        Ok(SecretKey(bits))
    }

    /// Construct a VRF proof seeded by the given message.
    pub fn prove(&self, public_key: &PublicKey, message: &[u8]) -> Proof {
        ExpandedSecretKey::from(self).prove(public_key, message)
    }

    /// Generate a `SecretKey` from a `csprng`.
    pub fn generate<T>(csprng: &mut T) -> SecretKey
    where
        T: CryptoRng + Rng, {
        let mut sk: SecretKey = SecretKey([0u8; 32]);

        csprng.fill_bytes(&mut sk.0);

        sk
    }
}

/// An "expanded" secret key used internally as a step from a secret key to
/// signing.
pub(crate) struct ExpandedSecretKey {
    pub(crate) key:   Scalar,
    pub(crate) nonce: [u8; 32],
}

/// Overwrite secret key material with null bytes when it goes out of scope.
impl Drop for ExpandedSecretKey {
    fn drop(&mut self) {
        self.key.zeroize();
        self.nonce.zeroize();
    }
}

impl From<&SecretKey> for ExpandedSecretKey {
    /// Construct an `ExpandedSecretKey` from a `SecretKey`.
    /// Implements <https://tools.ietf.org/html/rfc8032#section-5.1.5>
    fn from(secret_key: &SecretKey) -> ExpandedSecretKey {
        let mut h: Sha512 = Sha512::new();
        let mut hash: [u8; 64] = [0u8; 64];
        let mut lower: [u8; 32] = [0u8; 32];
        let mut upper: [u8; 32] = [0u8; 32];

        h.update(secret_key.as_bytes());
        hash.copy_from_slice(h.finalize().as_slice());

        lower.copy_from_slice(&hash[00..32]);
        upper.copy_from_slice(&hash[32..64]);

        ExpandedSecretKey {
            key:   Scalar::from_bytes_mod_order(clamp_integer(lower)),
            nonce: upper,
        }
    }
}
use super::proof::*;

impl ExpandedSecretKey {
    /// VRF proof with expanded secret key
    /// Implements <https://tools.ietf.org/html/draft-irtf-cfrg-vrf-07.html#section-5.1>
    pub fn prove(&self, public_key: &PublicKey, alpha: &[u8]) -> Proof {
        let x = self.key;
        let h = public_key
            .hash_to_curve(alpha)
            .expect("Failure should not happen for non-maliciously crafted input.");
        let h_string = h.compress().to_bytes();
        let k = self.nonce_generation(&h_string);

        let gamma = x * h;

        let c = hash_points(&[
            h.compress(),
            gamma.compress(),
            (k * constants::ED25519_BASEPOINT_POINT).compress(), // b^k
            (k * h).compress(),                                  // h^k
        ]);

        let k_plus_cx = k + c * x;

        Proof(gamma, c, k_plus_cx)
    }

    /// Implements <https://tools.ietf.org/html/draft-irtf-cfrg-vrf-07.html#section-5.4.2.2>
    fn nonce_generation(&self, h_string: &[u8]) -> Scalar {
        let digest = Sha512::new()
            .chain_update(self.nonce)
            .chain_update(h_string)
            .finalize();
        Scalar::from_bytes_mod_order_wide(&digest.into())
    }
}