{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Definitions of the groups the pairing is defined on module Pairing.Group ( CyclicGroup(..), G1, G2, GT, isOnCurveG1, isOnCurveG2, isInGT, g1, g2, b1, b2, hashToG1, groupFromX, fromByteStringG1, fromByteStringG2, fromByteStringGT ) where import Protolude import Data.Semigroup import Pairing.Fq as Fq import Pairing.Fq2 as Fq2 import Pairing.Fq12 as Fq12 import Pairing.Fr as Fr import Pairing.Point import Pairing.Params import Pairing.CyclicGroup import Test.QuickCheck import Pairing.Hash import Crypto.Random (MonadRandom) import Pairing.Modular import System.Random import Pairing.Serialize import Pairing.ByteRepr -- | G1 is E(Fq) defined by y^2 = x^3 + b type G1 = Point Fq -- | G2 is E'(Fq2) defined by y^2 = x^3 + b / xi type G2 = Point Fq2 -- | GT is subgroup of _r-th roots of unity of the multiplicative -- group of Fq12 type GT = Fq12 instance Semigroup G1 where (<>) = gAdd instance Semigroup G2 where (<>) = gAdd instance Semigroup GT where (<>) = (*) instance Monoid G1 where mappend = gAdd mempty = Infinity instance CyclicGroup G1 where generator = g1 order _ = _r expn a b = gMul a (asInteger b) inverse = gNeg random _ = randomG1 instance Validate G1 where isValidElement = isOnCurveG1 instance ToCompressedForm G1 where serializeCompressed = fmap toS . toCompressedForm instance ToUncompressedForm G1 where serializeUncompressed = fmap toS . toUncompressedForm instance Monoid G2 where mappend = gAdd mempty = Infinity instance CyclicGroup G2 where generator = g2 order _ = _r expn a b = gMul a (asInteger b) inverse = gNeg random _ = randomG2 instance Validate G2 where isValidElement = isOnCurveG2 instance ToCompressedForm G2 where serializeCompressed = fmap toS . toCompressedForm instance ToUncompressedForm G2 where serializeUncompressed = fmap toS . toUncompressedForm instance Monoid GT where mappend = (*) mempty = 1 instance CyclicGroup GT where generator = notImplemented -- this should be the _r-th primitive root of unity order = notImplemented -- should be a factor of _r expn a b = a ^ asInteger b inverse = recip random _ = Fq12.random instance ToUncompressedForm GT where serializeUncompressed = fmap toS . elementToUncompressedForm instance Validate GT where isValidElement = isInGT -- | Generator for G1 g1 :: G1 g1 = Point 1 2 -- | Generator for G2 g2 :: G2 g2 = Point x y where x = Fq2 10857046999023057135944570762232829481370756359578518086990519993285655852781 11559732032986387107991004021392285783925812861821192530917403151452391805634 y = Fq2 8495653923123431417604973247489272438418190587263600148770280649306958101930 4082367875863433681332203403145435568316851327593401208105741076214120093531 -- | Test whether a value in G1 satisfies the corresponding curve -- equation isOnCurveG1 :: G1 -> Bool isOnCurveG1 Infinity = True isOnCurveG1 (Point x y) = (y `fqPow` 2 == x `fqPow` 3 + Fq _b) -- | Test whether a value in G2 satisfies the corresponding curve -- equation isOnCurveG2 :: G2 -> Bool isOnCurveG2 Infinity = True isOnCurveG2 (Point x y) = y `fq2pow` 2 == x `fq2pow` 3 + Fq2 (b * inv_xi_a) (b * inv_xi_b) where (Fq2 inv_xi_a inv_xi_b) = Fq2.fq2inv Fq2.xi b = Fq _b -- | Test whether a value is an _r-th root of unity isInGT :: GT -> Bool isInGT f = f ^ _r == Fq12.fq12one -- | Parameter for curve on Fq b1 :: Fq b1 = Fq.new _b -- | Parameter for twisted curve over Fq2 b2 :: Fq2 b2 = Fq2 b1 0 / Fq2.xi ------------------------------------------------------------------------------- -- Generators ------------------------------------------------------------------------------- instance Arbitrary (Point Fq) where -- G1 arbitrary = gMul g1 . abs <$> (arbitrary :: Gen Integer) instance Arbitrary (Point Fq2) where -- G2 arbitrary = gMul g2 . abs <$> (arbitrary :: Gen Integer) hashToG1 :: MonadRandom m => ByteString -> m (Maybe G1) hashToG1 = swEncBN randomG1 :: (MonadRandom m) => m G1 randomG1 = do Fq r <- Fq.random pure (gMul g1 r) randomG2 :: (MonadRandom m) => m G2 randomG2 = do Fq r <- Fq.random pure (gMul g2 r) groupFromX :: (Validate (Point a), FromX a) => Bool -> a -> Maybe (Point a) groupFromX largestY x = do y <- yFromX x largestY if isValidElement (Point x y) then Just (Point x y) else Nothing fromByteStringG1 :: ByteString -> Either Text G1 fromByteStringG1 = pointFromByteString fqOne . toSL fromByteStringG2 :: ByteString -> Either Text G2 fromByteStringG2 = pointFromByteString fq2one . toSL fromByteStringGT :: ByteString -> Either Text GT fromByteStringGT = elementReadUncompressed fq12one . toSL