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 194 195 196 197 198
//! Manage the blindly signed message use curve25519_dalek::{ constants::RISTRETTO_BASEPOINT_POINT, ristretto::{CompressedRistretto, RistrettoPoint}, scalar::Scalar, }; use Error::{WiredRistrettoPointMalformed, WiredScalarMalformed}; use subtle::ConstantTimeEq; use typenum::U64; use digest::Digest; use request; /// The data required for authenticating the unblinded signature, /// /// * 'e' is H(R || msg), the unblinded version of e' upon which the blind /// signature S' is created. /// /// * 'S' is the unblinded version of blind signature S'. S' is a blind /// signature on the blind messag||R hash value e', S is the unblinded // signature on the unblinded R||message hash value e. /// /// * 'R' is the unblinded version of protocol initiation value R', which is /// the original Ristretto Point sent to the requester in response to /// protocol initiation. /// /// All of these components are required to authenticate a blind signature /// created by the signer. The value S can be authenticated against the /// coupled R and e value when provided with the public ECC key that is /// associated with the private ECC key the blind signature S' was ostensibly /// created with on e'. /// /// The actual message content is not included in this structure, though the /// input message can be validated against the signed e value of this struct as /// e = H(R || msg). #[derive(Copy, Clone, Debug)] pub struct UnblindedSigData { // The H(R || msg) value, which is the unblinded version of e', // which is the value that is blindly signed producing S' from which // S on E is derived. e: Scalar, // The unblinded signature S, valid on E, derived from S' valid on e'. s: Scalar, // The unblinded R value r: RistrettoPoint, } impl UnblindedSigData { /// Creates a new UnblindedSigData object, which consists of values e, S, and /// R. /// /// # Arguments /// /// * 'e' - H(msg||R), the unblinded variant of e'. /// * 's' - The unblinded signature (S' unblinded) /// * 'r' - The unblinded R' value received from the signer in step one /// of the protocol pub fn new(e: Scalar, s: Scalar, r: RistrettoPoint) -> Self { Self { e, s, r } } /// Authenticates that the signature value S on e is valid with R and the /// provided public key (ie: that S' was created on e' with the private key /// associated with the provided public key, in the session that was /// initiated with the R' value). /// /// # Arguments /// /// 'pub_key' - The public key associated with the private key that /// ostensibly created the signature value S' on e', to authenticate that /// S is authentic on e (given R). /// /// # Returns /// /// * True to indicate that the values S is authentic on e and R with the /// provided pub_key, or in other words that the signature is valid. /// /// * False to indicate that the value S on e and R isn't authentic, or in /// other words that the signature is invalid. /// /// # Mathematics /// /// * SP == e*Qs + R /// * S = Unblinded signature value /// * P = ECC generator point /// * Qs = Public key of the signer /// * e = H(msg || R) /// * R = Unblinded version of the R' value from the signer /// /// # Notes /// /// * (SP == e*Qs + R) is **not** done in constant time, however neither half /// of this equation contains any secret information so this should be fine. /// /// * This method only verifies that the signature S on e is valid given /// R and pub_key, it does **not** verify that e is correlated to any given /// msg value. pub fn authenticate(&self, pub_key: RistrettoPoint) -> bool { self.s * RISTRETTO_BASEPOINT_POINT == self.e * pub_key + self.r } /// The same as authenticate but with a constant time comparison. pub fn const_authenticate(&self, pub_key: RistrettoPoint) -> bool { (self.s * RISTRETTO_BASEPOINT_POINT) .ct_eq( &(self.e * pub_key + self.r) ) .unwrap_u8() == 1 } /// The same as authenticate, but rather than using the internal e value /// compute the e value e = H(R||Msg) from the provided msg value. This /// function is useful if the actual value of the signed message is /// important. /// /// # Note /// /// The internal e value is not used at all, and is not guaranteed to match /// H(R||msg) for the provided msg. pub fn msg_authenticate<H, M>(&self, pub_key: RistrettoPoint, msg: M) -> bool where H: Digest<OutputSize = U64> + Default, M: AsRef<[u8]>, { let e = request::generate_e::<H>(self.r, msg.as_ref()); self.s * RISTRETTO_BASEPOINT_POINT == e * pub_key + self.r } /// The same as const_authenticate, but rather than using the internal e value /// compute the e value e = H(R||Msg) from the provided msg value. This /// function is useful if the actual value of the signed message is /// important. /// /// # Note /// /// The internal e value is not used at all, and is not guaranteed to match /// H(R||msg) for the provided msg. pub fn msg_const_authenticate<H, M>(&self, pub_key: RistrettoPoint, msg: M) -> bool where H: Digest<OutputSize = U64> + Default, M: AsRef<[u8]>, { let e = request::generate_e::<H>(self.r, msg.as_ref()); (self.s * RISTRETTO_BASEPOINT_POINT) .ct_eq( &(e * pub_key + self.r) ) .unwrap_u8() == 1 } } /// The UnblindedSigData in wired form capable of being sent over the network. /// The wired form consists of e || S || R, with each component consisting of /// 32 bytes. pub struct WiredUnblindedSigData(pub [u8; 96]); impl From<UnblindedSigData> for WiredUnblindedSigData { fn from(usd: UnblindedSigData) -> Self { let mut arr = [0; 96]; arr[0..32].copy_from_slice(usd.e.as_bytes()); arr[32..64].copy_from_slice(usd.s.as_bytes()); arr[64..96].copy_from_slice(usd.r.compress().as_bytes()); WiredUnblindedSigData(arr) } } impl WiredUnblindedSigData { /// Converts WiredUnblindedSigData into UnblindedSigData. /// /// # Returns /// /// * Ok(UnblindedSigData) on success /// /// * Err(::Error) on failure, which could be due to any component of the /// internal [u8; 96] being malformed. pub fn to_internal_format(&self) -> ::Result<UnblindedSigData> { let mut e_arr = [0; 32]; let mut s_arr = [0; 32]; let mut r_arr = [0; 32]; e_arr.copy_from_slice(&self.0[0..32]); s_arr.copy_from_slice(&self.0[32..64]); r_arr.copy_from_slice(&self.0[64..96]); Ok(UnblindedSigData { e: Scalar::from_canonical_bytes(e_arr).ok_or(WiredScalarMalformed)?, s: Scalar::from_canonical_bytes(s_arr).ok_or(WiredScalarMalformed)?, r: CompressedRistretto(r_arr) .decompress() .ok_or(WiredRistrettoPointMalformed)?, }) } /// Returns a reference to the internal [u8; 96] pub fn as_bytes(&self) -> &[u8; 96] { &self.0 } /// Returns a copy of the internal [u8; 96] pub fn to_bytes(&self) -> [u8; 96] { self.0 } }