{-# LANGUAGE CPP #-} #ifndef MIN_VERSION_integer_gmp #define MIN_VERSION_integer_gmp(a,b,c) 0 #endif #if MIN_VERSION_integer_gmp(0,5,1) {-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns #-} #endif module ECDSA.Util (ECDSA.Util.pmul, lengthBytes) where import Crypto.Types.PubKey.ECC (Curve(CurveFP), CurvePrime(..), CurveCommon(..), Point(..)) import Codec.Crypto.ECC.Base as Hecc (EC(ECi), ECPF(ECPa), getx, gety, pmul) #if MIN_VERSION_integer_gmp(0,5,1) import GHC.Integer.GMP.Internals #else import Data.Bits #endif pmul :: (Curve, Point) -> Integer -> Point pmul (c,p) = hecc2point . Hecc.pmul (point2hecc c p) curve2hecc :: Curve -> EC Integer curve2hecc (CurveFP (CurvePrime p (CurveCommon a b _ n 1))) = ECi (8 * lengthBytes n) a b p n curve2hecc _ = error "TODO: binary curves" point2hecc :: Curve -> Point -> ECPF Integer point2hecc curve (Point x y) = ECPa (curve2hecc curve) x y point2hecc _ _ = error "Point at infinity cannot be represented" hecc2point :: ECPF Integer -> Point hecc2point p = Point (getx p) (gety p) -- crypto-numbers has this, but depends on crypto-random lengthBytes :: Integer -> Int #if MIN_VERSION_integer_gmp(0,5,1) lengthBytes n = I# (word2Int# (sizeInBaseInteger n 256#)) #else lengthBytes n | n < 256 = 1 | otherwise = 1 + lengthBytes (n `shiftR` 8) #endif