pairing-0.5.0: src/Pairing/Curve.hs
module Pairing.Curve
(
-- * Galois fields
Fq
, Fq2
, Fq6
, Fq12
, Fr
-- * Elliptic curves
, G1
, G2
, G2'
, GT
, gG1
, gG2
, gGT
, rG1
, rG2
, rGT
-- * Parameters
, _a
, _a'
, _b
, _b'
, _k
, _nqr
, _q
, _r
, _t
, _xi
-- * Miscellaneous functions
, conj
, getYfromX
, scale
, mulXi
, fq12Frobenius
, isRootOfUnity
, isPrimitiveRootOfUnity
, primitiveRootOfUnity
, precompRootOfUnity
-- , fromByteStringG1
-- , fromByteStringG2
-- , fromByteStringGT
) where
import Protolude
import Curve (Curve(..))
import qualified Curve.Weierstrass.BN254 as BN254
import qualified Curve.Weierstrass.BN254T as BN254T
import ExtensionField (ExtensionField, IrreducibleMonic, fromField, toField)
import GaloisField (GaloisField(..))
import qualified Group.Field.BN254TF as BN254TF
-- import Pairing.Serialize.Types
-------------------------------------------------------------------------------
-- Galois fields
-------------------------------------------------------------------------------
-- | Prime field @Fq@.
type Fq = BN254.Fq
-- | Quadratic extension field of @Fq@ defined as @Fq2 = Fq[u]/<u^2 + 1>@.
type Fq2 = BN254T.Fq2
-- | Cubic extension field of @Fq2@ defined as @Fq6 = Fq2[v]/<v^3 - (9 + u)>@.
type Fq6 = BN254TF.Fq6
-- | Quadratic extension field of @Fq6@ defined as @Fq12 = Fq6[w]/<w^2 - v>@.
type Fq12 = BN254TF.Fq12
-- | Prime field @Fr@.
type Fr = BN254.Fr
-------------------------------------------------------------------------------
-- Elliptic curves
-------------------------------------------------------------------------------
-- | G1 is @E(Fq)@ defined by @y^2 = x^3 + b@.
type G1 = BN254.PA
-- | G2 is @E'(Fq2)@ defined by @y^2 = x^3 + b / xi@.
type G2 = BN254T.PA
-- | G2' is G2 in Jacobian coordinates.
type G2' = BN254T.PJ
-- | GT is subgroup of @r@-th roots of unity of the multiplicative group of @Fq12@.
type GT = BN254TF.P
-- | Generator of G1.
gG1 :: G1
gG1 = BN254.gA
-- | Generator of G2.
gG2 :: G2
gG2 = BN254T.gA
-- | Generator of GT.
gGT :: GT
gGT = BN254TF.g_
-- | Order of G1.
rG1 :: Integer
rG1 = BN254._r
-- | Order of G2.
rG2 :: Integer
rG2 = BN254T._r
-- | Order of GT.
rGT :: Integer
rGT = BN254TF._r
-------------------------------------------------------------------------------
-- Parameters
-------------------------------------------------------------------------------
-- | Elliptic curve @E(Fq)@ coefficient @A@, with @y = x^3 + Ax + B@.
_a :: Fq
_a = BN254._a
-- | Elliptic curve @E(Fq2)@ coefficient @A'@, with @y = x^3 + A'x + B'@.
_a' :: Fq2
_a' = BN254T._a
-- | Elliptic curve @E(Fq)@ coefficient @B@, with @y = x^3 + Ax + B@.
_b :: Fq
_b = BN254._b
-- | Elliptic curve @E(Fq2)@ coefficient @B'@, with @y = x^3 + A'x + B'@.
_b' :: Fq2
_b' = BN254T._b
-- | Embedding degree.
_k :: Integer
_k = 12
-- | Quadratic nonresidue in @Fq@.
_nqr :: Integer
_nqr = 21888242871839275222246405745257275088696311157297823662689037894645226208582
-- | Characteristic of finite fields.
_q :: Integer
_q = BN254._q
-- | Order of G1 and characteristic of prime field of exponents.
_r :: Integer
_r = BN254._r
-- | BN parameter that determines the prime @_q@.
_t :: Integer
_t = 4965661367192848881
-- | Parameter of twisted curve over @Fq@.
_xi :: Fq2
_xi = toField [9, 1]
-------------------------------------------------------------------------------
-- Miscellaneous functions
-------------------------------------------------------------------------------
-- | Conjugation.
conj :: forall k im . IrreducibleMonic k im
=> ExtensionField k im -> ExtensionField k im
conj x
| deg x /= 2 * deg (witness :: k) = panic "conj: extension degree is not two."
| otherwise = case fromField x of
[y, z] -> toField [y, negate z]
[y] -> toField [y]
[] -> 0
_ -> panic "conj: unreachable."
{-# INLINABLE conj #-}
-- | Get Y coordinate from X coordinate given a curve and a choice function.
getYfromX :: Curve f c e q r => Point f c e q r -> (q -> q -> q) -> q -> Maybe q
getYfromX curve choose x = choose <*> negate <$> yX curve x
{-# INLINABLE getYfromX #-}
-- | Scalar multiplication.
scale :: IrreducibleMonic k im => k -> ExtensionField k im -> ExtensionField k im
scale = (*) . toField . return
{-# INLINABLE scale #-}
-------------------------------------------------------------------------------
-- Miscellaneous functions (temporary)
-------------------------------------------------------------------------------
-- | Multiply by @_xi@ (cubic nonresidue in @Fq2@) and reorder coefficients.
mulXi :: Fq6 -> Fq6
mulXi w = case fromField w of
[x, y, z] -> toField [z * _xi, x, y]
[x, y] -> toField [0, x, y]
[x] -> toField [0, x]
[] -> toField []
_ -> panic "mulXi: not exhaustive."
{-# INLINE mulXi #-}
-- | Iterated Frobenius automorphism in @Fq12@.
fq12Frobenius :: Int -> Fq12 -> Fq12
fq12Frobenius i a
| i == 0 = a
| i == 1 = fastFrobenius a
| i > 1 = let prev = fq12Frobenius (i - 1) a in fastFrobenius prev
| otherwise = panic "fq12Frobenius: not defined for negative values of i."
{-# INLINABLE fq12Frobenius #-}
-- | Fast Frobenius automorphism in @Fq12@.
fastFrobenius :: Fq12 -> Fq12
fastFrobenius = coll . conv [[0,2,4],[1,3,5]] . cong
where
cong :: Fq12 -> [[Fq2]]
cong = map (map conj . fromField) . fromField
conv :: [[Integer]] -> [[Fq2]] -> [[Fq2]]
conv = zipWith (zipWith (\x y -> pow _xi ((x * (_q - 1)) `div` 6) * y))
coll :: [[Fq2]] -> Fq12
coll = toField . map toField
{-# INLINABLE fastFrobenius #-}
-- | Check if an element is a root of unity.
isRootOfUnity :: Integer -> Fr -> Bool
isRootOfUnity n x
| n > 0 = pow x n == 1
| otherwise = panic "isRootOfUnity: negative powers not supported."
{-# INLINABLE isRootOfUnity #-}
-- | Check if an element is a primitive root of unity.
isPrimitiveRootOfUnity :: Integer -> Fr -> Bool
isPrimitiveRootOfUnity n x
| n > 0 = isRootOfUnity n x && all (\m -> not $ isRootOfUnity m x) [1 .. n - 1]
| otherwise = panic "isPrimitiveRootOfUnity: negative powers not supported."
{-# INLINABLE isPrimitiveRootOfUnity #-}
-- | Compute primitive roots of unity for 2^0, 2^1, ..., 2^28. (2^28
-- is the largest power of two that divides _r - 1, therefore there
-- are no primitive roots of unity for higher powers of 2 in Fr.)
primitiveRootOfUnity :: Int -> Fr
primitiveRootOfUnity k
| 0 <= k && k <= 28 = 5^((_r - 1) `div` (2^k))
| otherwise = panic "primitiveRootOfUnity: no primitive root for given power of 2."
{-# INLINABLE primitiveRootOfUnity #-}
-- | Precompute roots of unity.
precompRootOfUnity :: Int -> Fr
precompRootOfUnity 0 = 1
precompRootOfUnity 1 = 21888242871839275222246405745257275088548364400416034343698204186575808495616
precompRootOfUnity 2 = 21888242871839275217838484774961031246007050428528088939761107053157389710902
precompRootOfUnity 3 = 19540430494807482326159819597004422086093766032135589407132600596362845576832
precompRootOfUnity 4 = 14940766826517323942636479241147756311199852622225275649687664389641784935947
precompRootOfUnity 5 = 4419234939496763621076330863786513495701855246241724391626358375488475697872
precompRootOfUnity 6 = 9088801421649573101014283686030284801466796108869023335878462724291607593530
precompRootOfUnity 7 = 10359452186428527605436343203440067497552205259388878191021578220384701716497
precompRootOfUnity 8 = 3478517300119284901893091970156912948790432420133812234316178878452092729974
precompRootOfUnity 9 = 6837567842312086091520287814181175430087169027974246751610506942214842701774
precompRootOfUnity 10 = 3161067157621608152362653341354432744960400845131437947728257924963983317266
precompRootOfUnity 11 = 1120550406532664055539694724667294622065367841900378087843176726913374367458
precompRootOfUnity 12 = 4158865282786404163413953114870269622875596290766033564087307867933865333818
precompRootOfUnity 13 = 197302210312744933010843010704445784068657690384188106020011018676818793232
precompRootOfUnity 14 = 20619701001583904760601357484951574588621083236087856586626117568842480512645
precompRootOfUnity 15 = 20402931748843538985151001264530049874871572933694634836567070693966133783803
precompRootOfUnity 16 = 421743594562400382753388642386256516545992082196004333756405989743524594615
precompRootOfUnity 17 = 12650941915662020058015862023665998998969191525479888727406889100124684769509
precompRootOfUnity 18 = 11699596668367776675346610687704220591435078791727316319397053191800576917728
precompRootOfUnity 19 = 15549849457946371566896172786938980432421851627449396898353380550861104573629
precompRootOfUnity 20 = 17220337697351015657950521176323262483320249231368149235373741788599650842711
precompRootOfUnity 21 = 13536764371732269273912573961853310557438878140379554347802702086337840854307
precompRootOfUnity 22 = 12143866164239048021030917283424216263377309185099704096317235600302831912062
precompRootOfUnity 23 = 934650972362265999028062457054462628285482693704334323590406443310927365533
precompRootOfUnity 24 = 5709868443893258075976348696661355716898495876243883251619397131511003808859
precompRootOfUnity 25 = 19200870435978225707111062059747084165650991997241425080699860725083300967194
precompRootOfUnity 26 = 7419588552507395652481651088034484897579724952953562618697845598160172257810
precompRootOfUnity 27 = 2082940218526944230311718225077035922214683169814847712455127909555749686340
precompRootOfUnity 28 = 19103219067921713944291392827692070036145651957329286315305642004821462161904
precompRootOfUnity _ = panic "precompRootOfUnity: exponent too big for Fr / negative"
{-# INLINABLE precompRootOfUnity #-}
-- fromByteStringG1 :: FromSerialisedForm u => u -> LByteString -> Either Text G1
-- fromByteStringG1 unser = unserializePoint unser generatorG1 . toSL
-- fromByteStringG2 :: FromSerialisedForm u => u -> LByteString -> Either Text G2
-- fromByteStringG2 unser = unserializePoint unser generatorG2 . toSL
-- fromByteStringGT :: FromUncompressedForm u => u -> LByteString -> Either Text GT
-- fromByteStringGT unser = unserialize unser 1 . toSL