-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added the Shallue van de Woestijne encoding for curve hashing (#1)
* Added the Shallue van de Woestijne encoding for curve hashing * Added stack extras, comments, and hash zero bytestring
- Loading branch information
Showing
9 changed files
with
242 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,5 @@ pairing.cabal | |
*~ | ||
*.hi | ||
*.o | ||
.ghc.environment.* | ||
dist*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
module Pairing.Hash ( | ||
swEncBN | ||
) where | ||
|
||
import Protolude | ||
import Pairing.Params | ||
import Pairing.Point | ||
import Pairing.Modular as M | ||
import Pairing.Fq as Fq | ||
import Math.NumberTheory.Moduli.Class | ||
import Math.NumberTheory.Moduli.Sqrt | ||
import Crypto.Random (MonadRandom) | ||
import Data.List | ||
|
||
sqrtOfMinusThree :: forall m . KnownNat m => Proxy m -> Mod m | ||
sqrtOfMinusThree mName = sqrtOf mName (-3) | ||
|
||
-- | | ||
-- Picks the postive square root only | ||
-- | | ||
|
||
sqrtOf :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m | ||
sqrtOf mName i = case sqrtsMod i of | ||
[] -> panic ("Could not calculate sqrt " <> show i) | ||
(x:_) -> x | ||
|
||
w :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m -> Mod m | ||
w mname sq3 t = (sq3 * t) / (1 + (b mname) + (t `powMod` 2)) | ||
|
||
b :: forall m . KnownNat m => Proxy m -> Mod m | ||
b mName = fromInteger @(Mod m) _b | ||
|
||
x1 :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m -> Mod m | ||
x1 mName t w = ((sqrtOfMinusThree mName) - 1) / 2 - (t * w) | ||
|
||
x2 :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m | ||
x2 mName x1' = (-1) - x1' | ||
|
||
x3 :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m | ||
x3 mName w = 1 + (1 / (w `powMod` 2)) | ||
|
||
chi :: forall m . KnownNat m => Proxy m -> Mod m -> Integer | ||
chi mName a | ||
| a == 0 = 0 | ||
| isSquare mName a = 1 | ||
| otherwise = -1 | ||
|
||
alphaBeta :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m -> Integer | ||
alphaBeta mName pr px = chi mName ((pr * pr) * ((px `powMod` 3) + (b mName))) | ||
|
||
i :: Integer -> Integer -> Integer | ||
i pa pb = (((pa - 1) * pb) `mod` 3) + 1 | ||
|
||
swy :: forall m . KnownNat m => Proxy m -> Mod m -> Mod m -> Mod m -> Mod m -> Integer | ||
swy mn pr3 pt pxi pb = ch * y | ||
where | ||
ch = chi mn ((pr3 `powMod` 2) * pt) | ||
y = getVal $ sqrtOf mn ((pxi `powMod` 3) + pb) | ||
|
||
-- | Encodes a given byte string to a point on the BN curve. | ||
-- The implemenation uses the Shallue van de Woestijne encoding to BN curves as specifed | ||
-- in Section 6 of Indifferentiable Hashing to Barreto Naehrig Curves | ||
-- by Pierre-Alain Fouque and Mehdi Tibouchi. | ||
-- This function evaluates an empty bytestring or one that contains \NUL to zero | ||
-- which according to Definiton 2 of the paper is sent to an arbitrary point on the curve | ||
-- | ||
swEncBN :: (MonadIO m, MonadRandom m) => ByteString -> m (Point Fq) | ||
swEncBN bs = withQM $ \mn -> do | ||
let t = M.fromBytes bs mn | ||
let sq3 = sqrtOfMinusThree mn | ||
let w' = w mn sq3 t | ||
let x1' = x1 mn t w' | ||
if (t == 0) then | ||
pure $ (Point (Fq.new (getVal x1')) (Fq.new (getVal $ sqrtOf mn (1 + (b mn))))) | ||
else do | ||
let x2' = x2 mn x1' | ||
let x3' = x3 mn w' | ||
let lst = [x1', x2', x3'] | ||
r1 <- randomMod mn | ||
r2 <- randomMod mn | ||
r3 <- randomMod mn | ||
let al = alphaBeta mn r1 x1' | ||
let bet = alphaBeta mn r2 x2' | ||
let i' = i al bet | ||
let swy' = swy mn r3 t (genericIndex lst (i' - 1)) (b mn) | ||
pure (Point (Fq.new (getVal $ genericIndex lst (i' - 1))) (Fq.new swy')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
module Pairing.Modular where | ||
|
||
import Protolude | ||
import Math.NumberTheory.Moduli.Class | ||
import Math.NumberTheory.Moduli.Sqrt | ||
import Math.NumberTheory.UniqueFactorisation | ||
import Pairing.Params | ||
import Crypto.Random (MonadRandom) | ||
import Crypto.Number.Generate (generateMax) | ||
import qualified Data.ByteString as BS | ||
|
||
-- Mod conversion and management | ||
withQ :: (forall m . KnownNat m => Proxy m -> r) -> r | ||
withQ cont = case someNatVal _q of | ||
Nothing -> panic ("Somehow " <> show _q <> " was not a Nat") | ||
Just (SomeNat mName) -> cont mName | ||
|
||
-- Mod conversion and management | ||
withQM :: (forall n. KnownNat n => Proxy n -> m r) -> m r | ||
withQM cont = case someNatVal _q of | ||
Nothing -> panic ("Somehow " <> show _q <> " was not a Nat") | ||
Just (SomeNat mName) -> cont mName | ||
|
||
newMod :: forall m . KnownNat m => Integer -> Proxy m -> Mod m | ||
newMod n mName = fromInteger @(Mod m) n | ||
|
||
toInteger :: Mod m -> Integer | ||
toInteger = getVal | ||
|
||
modUnOp :: forall m . KnownNat m => Integer -> (Mod m -> Mod m) -> Proxy m -> Integer | ||
modUnOp n f mName = getVal $ f (fromInteger @(Mod m) n) | ||
|
||
modBinOp :: forall m . KnownNat m => Integer -> Integer -> (Mod m -> Mod m -> Mod m) -> Proxy m -> Integer | ||
modBinOp r s f mName = getVal $ f (fromInteger @(Mod m) r) (fromInteger @(Mod m) s) | ||
|
||
multInverse :: KnownNat m => Mod m -> Maybe (Mod m) | ||
multInverse n = do | ||
m <- isMultElement n | ||
let mm = invertGroup m | ||
pure (multElement mm) | ||
|
||
modUnOpM :: forall m a . (KnownNat m, Monad a) => Integer -> (Mod m -> a (Mod m)) -> Proxy m -> a Integer | ||
modUnOpM n f mName = do | ||
a <- f (fromInteger @(Mod m) n) | ||
pure (getVal a) | ||
|
||
modPow :: Integral p => Integer -> p -> Integer | ||
modPow a b = withQ (modUnOp a (flip powMod b)) | ||
|
||
modSqrt :: Integer -> [Integer] | ||
modSqrt a = withQ (modUnOpM a sqrtsMod) | ||
|
||
threeModFourCongruence :: Integer -> Bool | ||
threeModFourCongruence q = q `mod` 4 == 3 `mod` 4 | ||
|
||
isSquare :: forall m . KnownNat m => Proxy m -> Mod m -> Bool | ||
isSquare _ a = if (threeModFourCongruence _q) then (length kp > 0) else False | ||
where | ||
kp = sqrtsMod a | ||
|
||
isSquareIn3Mod4 :: Integer -> Integer | ||
isSquareIn3Mod4 a = if (threeModFourCongruence _q) then sq else 0 | ||
where | ||
sq = withQ (modUnOp a f) | ||
f m = m `powMod` p2 | ||
p2 = (_q + 1) `quot` 4 | ||
|
||
legendre :: Integer -> Integer | ||
legendre a = if conv > 1 then (-1) else conv | ||
where | ||
conv = withQ (modUnOp a f) | ||
f m = m `powMod` p2 | ||
p2 = (_q - 1) `quot` 2 | ||
|
||
randomMod :: forall n m. (MonadRandom m, KnownNat n) => Proxy n -> m (Mod n) | ||
randomMod mName = do | ||
seed <- generateMax _q | ||
pure (fromInteger @(Mod n) seed) | ||
|
||
fromBytes :: forall n. (KnownNat n) => ByteString -> Proxy n -> Mod n | ||
fromBytes bs mn = newMod (fromBytes' bs) mn | ||
where | ||
fromBytes' :: ByteString -> Integer | ||
fromBytes' = BS.foldl' f 0 | ||
f a b = a `shiftL` 8 .|. fromIntegral b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters