|
| 1 | +// Copyright (c) 2022, Mysten Labs, Inc. |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +use std::fmt::Debug; |
| 5 | +use std::ops::{Div, Mul}; |
| 6 | + |
| 7 | +use ark_bn254::{Bn254, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; |
| 8 | +use ark_ec::pairing::{Pairing as ArkworksPairing, PairingOutput}; |
| 9 | +use ark_ec::{AffineRepr, Group}; |
| 10 | +use ark_ff::{Field, One, UniformRand, Zero}; |
| 11 | +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; |
| 12 | +use derive_more::{Add, Neg, Sub}; |
| 13 | +use once_cell::sync::OnceCell; |
| 14 | +use serde::{de, Deserialize}; |
| 15 | + |
| 16 | +use fastcrypto_derive::GroupOpsExtend; |
| 17 | + |
| 18 | +use crate::error::{FastCryptoError, FastCryptoResult}; |
| 19 | +use crate::groups::{FromTrustedByteArray, GroupElement, Pairing, Scalar as ScalarType}; |
| 20 | +use crate::serde_helpers::ToFromByteArray; |
| 21 | +use crate::traits::AllowedRng; |
| 22 | +use crate::{groups, serialize_deserialize_with_to_from_byte_array}; |
| 23 | + |
| 24 | +/// Elements of the group G_1 in BN254. |
| 25 | +#[derive(Clone, Copy, Eq, PartialEq, Debug, Add, Sub, Neg, GroupOpsExtend)] |
| 26 | +#[repr(transparent)] |
| 27 | +pub struct G1Element(G1Projective); |
| 28 | + |
| 29 | +/// Elements of the group G_2 in BN254. |
| 30 | +#[derive(Clone, Copy, Eq, PartialEq, Debug, Add, Sub, Neg, GroupOpsExtend)] |
| 31 | +#[repr(transparent)] |
| 32 | +pub struct G2Element(G2Projective); |
| 33 | + |
| 34 | +/// Elements of the subgroup G_T of F_q^{12} in BN254. Note that it is written in additive notation here. |
| 35 | +#[derive(Clone, Copy, Eq, PartialEq, Debug, Add, Sub, Neg, GroupOpsExtend)] |
| 36 | +pub struct GTElement(PairingOutput<Bn254>); |
| 37 | + |
| 38 | +/// This represents a scalar modulo r = 21888242871839275222246405745257275088548364400416034343698204186575808495617 |
| 39 | +/// which is the order of the groups G1, G2 and GT. Note that r is a 254 bit prime. |
| 40 | +#[derive(Clone, Copy, Eq, PartialEq, Debug, Add, Sub, Neg, GroupOpsExtend)] |
| 41 | +pub struct Scalar(Fr); |
| 42 | + |
| 43 | +pub const SCALAR_LENGTH: usize = 32; |
| 44 | +pub const G1_ELEMENT_BYTE_LENGTH: usize = 32; |
| 45 | +pub const G2_ELEMENT_BYTE_LENGTH: usize = 64; |
| 46 | +pub const GT_ELEMENT_BYTE_LENGTH: usize = 384; |
| 47 | + |
| 48 | +impl Div<Self> for Scalar { |
| 49 | + type Output = FastCryptoResult<Self>; |
| 50 | + |
| 51 | + fn div(self, rhs: Self) -> FastCryptoResult<Self> { |
| 52 | + if rhs.0.is_zero() { |
| 53 | + return Err(FastCryptoError::InvalidInput); |
| 54 | + } |
| 55 | + Ok(Self(self.0.div(rhs.0))) |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +impl Mul<Scalar> for Scalar { |
| 60 | + type Output = Self; |
| 61 | + |
| 62 | + fn mul(self, rhs: Scalar) -> Self::Output { |
| 63 | + Self(self.0.mul(rhs.0)) |
| 64 | + } |
| 65 | +} |
| 66 | + |
| 67 | +impl GroupElement for Scalar { |
| 68 | + type ScalarType = Scalar; |
| 69 | + |
| 70 | + fn zero() -> Self { |
| 71 | + Self(Fr::zero()) |
| 72 | + } |
| 73 | + |
| 74 | + fn generator() -> Self { |
| 75 | + Self(Fr::one()) |
| 76 | + } |
| 77 | +} |
| 78 | + |
| 79 | +impl GroupElement for G1Element { |
| 80 | + type ScalarType = Scalar; |
| 81 | + |
| 82 | + fn zero() -> Self { |
| 83 | + G1Element(G1Projective::zero()) |
| 84 | + } |
| 85 | + |
| 86 | + fn generator() -> Self { |
| 87 | + G1Element(G1Projective::generator()) |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +impl Div<Scalar> for G1Element { |
| 92 | + type Output = FastCryptoResult<Self>; |
| 93 | + |
| 94 | + fn div(self, rhs: Scalar) -> Self::Output { |
| 95 | + let inverse = rhs.inverse()?; |
| 96 | + Ok(self.mul(inverse)) |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +impl Mul<Scalar> for G1Element { |
| 101 | + type Output = Self; |
| 102 | + |
| 103 | + fn mul(self, rhs: Scalar) -> Self::Output { |
| 104 | + Self(self.0.mul(rhs.0)) |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +impl ToFromByteArray<32> for G1Element { |
| 109 | + fn from_byte_array(bytes: &[u8; 32]) -> Result<Self, FastCryptoError> { |
| 110 | + let point = G1Affine::deserialize_compressed(bytes.as_slice()) |
| 111 | + .map_err(|_| FastCryptoError::InvalidInput)?; |
| 112 | + |
| 113 | + // Arkworks only checks the infinty flag, but we require all-zeros to have unique serialization |
| 114 | + if point.is_zero() && bytes[0..31].iter().any(|x| !x.is_zero()) { |
| 115 | + return Err(FastCryptoError::InvalidInput); |
| 116 | + } |
| 117 | + |
| 118 | + Ok(Self(G1Projective::from(point))) |
| 119 | + } |
| 120 | + |
| 121 | + fn to_byte_array(&self) -> [u8; 32] { |
| 122 | + let mut bytes = [0u8; 32]; |
| 123 | + self.0 |
| 124 | + .serialize_compressed(bytes.as_mut_slice()) |
| 125 | + .expect("Never fails"); |
| 126 | + bytes |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +serialize_deserialize_with_to_from_byte_array!(G1Element); |
| 131 | + |
| 132 | +impl FromTrustedByteArray<32> for G1Element { |
| 133 | + fn from_trusted_byte_array(bytes: &[u8; 32]) -> FastCryptoResult<Self> { |
| 134 | + G1Projective::deserialize_compressed_unchecked(bytes.as_slice()) |
| 135 | + .map_err(|_| FastCryptoError::InvalidInput) |
| 136 | + .map(G1Element) |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +impl GroupElement for G2Element { |
| 141 | + type ScalarType = Scalar; |
| 142 | + |
| 143 | + fn zero() -> Self { |
| 144 | + G2Element(G2Projective::zero()) |
| 145 | + } |
| 146 | + |
| 147 | + fn generator() -> Self { |
| 148 | + G2Element(G2Projective::generator()) |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +impl Div<Scalar> for G2Element { |
| 153 | + type Output = FastCryptoResult<Self>; |
| 154 | + |
| 155 | + fn div(self, rhs: Scalar) -> Self::Output { |
| 156 | + let inverse = rhs.inverse()?; |
| 157 | + Ok(self.mul(inverse)) |
| 158 | + } |
| 159 | +} |
| 160 | + |
| 161 | +impl Mul<Scalar> for G2Element { |
| 162 | + type Output = Self; |
| 163 | + |
| 164 | + fn mul(self, rhs: Scalar) -> Self::Output { |
| 165 | + Self(self.0.mul(rhs.0)) |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +impl ToFromByteArray<64> for G2Element { |
| 170 | + fn from_byte_array(bytes: &[u8; 64]) -> Result<Self, FastCryptoError> { |
| 171 | + let point = G2Affine::deserialize_compressed(bytes.as_slice()) |
| 172 | + .map_err(|_| FastCryptoError::InvalidInput)?; |
| 173 | + |
| 174 | + // Arkworks only checks the infinty flag, but we require all-zeros to have unique serialization |
| 175 | + if point.is_zero() && bytes[0..63].iter().any(|x| !x.is_zero()) { |
| 176 | + return Err(FastCryptoError::InvalidInput); |
| 177 | + } |
| 178 | + |
| 179 | + Ok(Self(G2Projective::from(point))) |
| 180 | + } |
| 181 | + |
| 182 | + fn to_byte_array(&self) -> [u8; 64] { |
| 183 | + let mut bytes = [0u8; 64]; |
| 184 | + self.0 |
| 185 | + .serialize_compressed(bytes.as_mut_slice()) |
| 186 | + .expect("Never fails"); |
| 187 | + bytes |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +serialize_deserialize_with_to_from_byte_array!(G2Element); |
| 192 | + |
| 193 | +impl FromTrustedByteArray<64> for G2Element { |
| 194 | + fn from_trusted_byte_array(bytes: &[u8; 64]) -> FastCryptoResult<Self> { |
| 195 | + G2Projective::deserialize_compressed_unchecked(bytes.as_slice()) |
| 196 | + .map_err(|_| FastCryptoError::InvalidInput) |
| 197 | + .map(G2Element) |
| 198 | + } |
| 199 | +} |
| 200 | + |
| 201 | +impl From<u128> for Scalar { |
| 202 | + fn from(value: u128) -> Self { |
| 203 | + Self(Fr::from(value)) |
| 204 | + } |
| 205 | +} |
| 206 | + |
| 207 | +impl groups::Scalar for Scalar { |
| 208 | + fn rand<R: AllowedRng>(rng: &mut R) -> Self { |
| 209 | + Self(Fr::rand(rng)) |
| 210 | + } |
| 211 | + |
| 212 | + fn inverse(&self) -> FastCryptoResult<Self> { |
| 213 | + Ok(Self(self.0.inverse().ok_or(FastCryptoError::InvalidInput)?)) |
| 214 | + } |
| 215 | +} |
| 216 | + |
| 217 | +impl ToFromByteArray<32> for Scalar { |
| 218 | + fn from_byte_array(bytes: &[u8; Self::BYTE_LENGTH]) -> Result<Self, FastCryptoError> { |
| 219 | + // Arkworks uses little-endian byte order for serialization, but we use big-endian. |
| 220 | + let mut reversed = *bytes; |
| 221 | + reversed.reverse(); |
| 222 | + Fr::deserialize_compressed(reversed.as_slice()) |
| 223 | + .map_err(|_| FastCryptoError::InvalidInput) |
| 224 | + .map(Scalar) |
| 225 | + } |
| 226 | + |
| 227 | + fn to_byte_array(&self) -> [u8; Self::BYTE_LENGTH] { |
| 228 | + let mut bytes = [0u8; Self::BYTE_LENGTH]; |
| 229 | + self.0 |
| 230 | + .serialize_compressed(bytes.as_mut_slice()) |
| 231 | + .expect("Never fails"); |
| 232 | + // Arkworks uses little-endian byte order for serialization, but we use big-endian. |
| 233 | + bytes.reverse(); |
| 234 | + bytes |
| 235 | + } |
| 236 | +} |
| 237 | + |
| 238 | +serialize_deserialize_with_to_from_byte_array!(Scalar); |
| 239 | + |
| 240 | +impl Pairing for G1Element { |
| 241 | + type Other = G2Element; |
| 242 | + type Output = GTElement; |
| 243 | + |
| 244 | + fn pairing(&self, other: &Self::Other) -> <Self as Pairing>::Output { |
| 245 | + GTElement(Bn254::pairing(self.0, other.0)) |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +#[allow(clippy::suspicious_arithmetic_impl)] |
| 250 | +impl Div<Scalar> for GTElement { |
| 251 | + type Output = FastCryptoResult<GTElement>; |
| 252 | + |
| 253 | + fn div(self, rhs: Scalar) -> Self::Output { |
| 254 | + let inverse = rhs.inverse()?; |
| 255 | + Ok(self * inverse) |
| 256 | + } |
| 257 | +} |
| 258 | + |
| 259 | +impl Mul<Scalar> for GTElement { |
| 260 | + type Output = GTElement; |
| 261 | + |
| 262 | + fn mul(self, rhs: Scalar) -> Self::Output { |
| 263 | + Self(self.0.mul(rhs.0)) |
| 264 | + } |
| 265 | +} |
| 266 | + |
| 267 | +impl GroupElement for GTElement { |
| 268 | + type ScalarType = Scalar; |
| 269 | + |
| 270 | + fn zero() -> Self { |
| 271 | + GTElement(PairingOutput::zero()) |
| 272 | + } |
| 273 | + |
| 274 | + fn generator() -> Self { |
| 275 | + static G: OnceCell<PairingOutput<Bn254>> = OnceCell::new(); |
| 276 | + Self(*G.get_or_init(Self::compute_generator)) |
| 277 | + } |
| 278 | +} |
| 279 | + |
| 280 | +impl GTElement { |
| 281 | + fn compute_generator() -> PairingOutput<Bn254> { |
| 282 | + G1Element::generator().pairing(&G2Element::generator()).0 |
| 283 | + } |
| 284 | +} |
| 285 | + |
| 286 | +impl FromTrustedByteArray<384> for GTElement { |
| 287 | + fn from_trusted_byte_array(bytes: &[u8; 384]) -> FastCryptoResult<Self> { |
| 288 | + PairingOutput::<Bn254>::deserialize_compressed_unchecked(bytes.as_ref()) |
| 289 | + .map_err(|_| FastCryptoError::InvalidInput) |
| 290 | + .map(GTElement) |
| 291 | + } |
| 292 | +} |
| 293 | + |
| 294 | +impl ToFromByteArray<384> for GTElement { |
| 295 | + fn from_byte_array(bytes: &[u8; 384]) -> Result<Self, FastCryptoError> { |
| 296 | + PairingOutput::<Bn254>::deserialize_compressed(bytes.as_ref()) |
| 297 | + .map_err(|_| FastCryptoError::InvalidInput) |
| 298 | + .map(GTElement) |
| 299 | + } |
| 300 | + |
| 301 | + fn to_byte_array(&self) -> [u8; 384] { |
| 302 | + let mut bytes = [0u8; 384]; |
| 303 | + self.0 |
| 304 | + .serialize_compressed(bytes.as_mut_slice()) |
| 305 | + .expect("Never fails"); |
| 306 | + bytes |
| 307 | + } |
| 308 | +} |
| 309 | + |
| 310 | +serialize_deserialize_with_to_from_byte_array!(GTElement); |
0 commit comments