eccrypto-0.0: src/Crypto/Fi.hs
-----------------------------------------------------------------------------
-- |
-- Module : Crypto.Fi
-- Copyright : (c) Marcel Fourné 20[14..]
-- License : BSD3
-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)
-- Stability : beta
-- Portability : Good
--
-- This is a thin wrapper around Integer to ease transition toward FPrime
-- WARNING! Re Timing-Attacks: This backend is not fully timing attack resistant.
--
-----------------------------------------------------------------------------
{-# OPTIONS_GHC -O2 -feager-blackholing #-}
{-# LANGUAGE BangPatterns #-}
module Crypto.Fi ( FPrime
, eq
, add
, addr
, sub
, subr
, neg
, shift
, mul
, mulr
, redc
, square
, pow
, inv
, fromInteger
, toInteger
, testBit
, condBit
)
where
import Prelude (Eq,Show,(==),(&&),Integer,Int,show,Bool(False,True),(++),($),fail,undefined,(+),(-),(*),(^),mod,Integral,otherwise,(<),div,not,String,flip,takeWhile,length,iterate,(>),(<=),(>=),maxBound,rem,quot,quotRem,error)
import qualified Prelude as P (fromInteger,toInteger)
import qualified Data.Bits as B (Bits(..),testBit,shift,(.&.),(.|.))
import Crypto.Common (log2len)
-- | a simple wrapper to ease transition
type FPrime = Integer
-- | most trivial (==) wrapper
eq :: FPrime -> FPrime -> Bool
eq !a !b = a == b
{-# INLINABLE eq #-}
-- | (+) in the field
add :: FPrime -> FPrime -> FPrime
add !a !b = a + b
{-# INLINABLE add #-}
-- | (+) in the field
addr :: FPrime -> FPrime -> FPrime -> FPrime
addr !p !a !b = redc p $ a + b
{-# INLINABLE addr #-}
-- | (-) in the field
sub :: FPrime -> FPrime -> FPrime
sub a b = a - b
{-# INLINABLE sub #-}
-- | (-) in the field
subr :: FPrime -> FPrime -> FPrime -> FPrime
subr p a b = redc p (a - b)
{-# INLINABLE subr #-}
-- | negation in the field
neg :: FPrime -> FPrime -> FPrime
neg !p !a = redc p (-a)
{-# INLINABLE neg #-}
-- | bitshift wrapper
shift :: FPrime -> Int -> FPrime
shift = B.shift
-- | modular reduction, a simple wrapper around mod
redc :: FPrime -> FPrime -> FPrime
redc !p !a = a `mod` p
{-# INLINABLE redc #-}
-- | field multiplication, a * b
mul :: FPrime -> FPrime -> FPrime
mul !a !b = a * b
{-# INLINABLE mul #-}
-- | field multiplication, a * b `mod` p
mulr :: FPrime -> FPrime -> FPrime -> FPrime
mulr !p !a !b = redc p $ a * b
{-# INLINABLE mulr #-}
-- | simple squaring in the field
square :: FPrime -> FPrime -> FPrime
square p a = redc p (a ^ (2::Int))
{-# INLINABLE square #-}
-- | the power function in the field
pow :: (B.Bits a, Integral a) => FPrime -> FPrime -> a -> FPrime
pow !p !a !k = let binlog = log2len k
ex p1 p2 i
| i < 0 = p1
| not (B.testBit k i) = redc p $ ex (square p p1) (mulr p p1 p2) (i - 1)
| otherwise = redc p $ ex (mulr p p1 p2) (square p p2) (i - 1)
in redc p $ ex a (square p a) (binlog - 2)
-- | field inversion
inv :: FPrime -> FPrime -> FPrime
inv !p !a = pow p a (toInteger p - 2)
-- | conversion wrapper with a limit
fromInteger :: Int -> FPrime -> Integer
fromInteger l !a = P.fromInteger (a `mod` (2^l))
{-# INLINABLE fromInteger #-}
-- | a most simple conversion wrapper
toInteger :: FPrime -> Integer
toInteger = P.toInteger
{-# INLINABLE toInteger #-}
-- | a testBit wrapper
testBit :: FPrime -> Int -> Bool
testBit = B.testBit
{-# INLINABLE testBit #-}
-- | like testBit, but give either 0 or 1
condBit :: FPrime -> Int -> FPrime
condBit a i = shift (a B..&. (fromInteger (i+1) ((2^(i+1)-1)::Integer))) (-i)
{-# INLINABLE condBit #-}