eccrypto 0.0.1 → 0.1.0
raw patch · 29 files changed
+2622/−827 lines, 29 filesdep +Cabaldep +MonadRandomdep +base16-bytestringdep −cerealdep −vectorsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: Cabal, MonadRandom, base16-bytestring, criterion, eccrypto, integer-gmp
Dependencies removed: cereal, vector
API changes (from Hackage documentation)
- Crypto.Common: one :: Int -> Vector Word
- Crypto.Common: three :: Int -> Vector Word
- Crypto.Common: two :: Int -> Vector Word
- Crypto.Common: zero :: Int -> Vector Word
- Crypto.ECC.Ed25519.EdDSA: Point :: (FPrime, FPrime) -> Point
- Crypto.ECC.Ed25519.EdDSA: SigBad :: VerifyResult
- Crypto.ECC.Ed25519.EdDSA: SigOK :: VerifyResult
- Crypto.ECC.Ed25519.EdDSA: a :: SecKey -> Either String SecFPrime
- Crypto.ECC.Ed25519.EdDSA: alleeins :: FPrime
- Crypto.ECC.Ed25519.EdDSA: b :: Int
- Crypto.ECC.Ed25519.EdDSA: bPoint :: Point
- Crypto.ECC.Ed25519.EdDSA: bstopoint :: ByteString -> Either String Point
- Crypto.ECC.Ed25519.EdDSA: by :: FPrime
- Crypto.ECC.Ed25519.EdDSA: d :: FPrime
- Crypto.ECC.Ed25519.EdDSA: data Point
- Crypto.ECC.Ed25519.EdDSA: data VerifyResult
- Crypto.ECC.Ed25519.EdDSA: eins :: FPrime
- Crypto.ECC.Ed25519.EdDSA: genkeys :: (CryptoRandomGen g) => g -> (Either String (SecKey, PubKey))
- Crypto.ECC.Ed25519.EdDSA: genkeys_simple :: IO (Either String (SecKey, PubKey))
- Crypto.ECC.Ed25519.EdDSA: getFPrime :: Get FPrime
- Crypto.ECC.Ed25519.EdDSA: h :: ByteString -> ByteString
- Crypto.ECC.Ed25519.EdDSA: i :: FPrime
- Crypto.ECC.Ed25519.EdDSA: inf :: Point
- Crypto.ECC.Ed25519.EdDSA: instance GHC.Classes.Eq Crypto.ECC.Ed25519.EdDSA.Point
- Crypto.ECC.Ed25519.EdDSA: instance GHC.Classes.Eq Crypto.ECC.Ed25519.EdDSA.VerifyResult
- Crypto.ECC.Ed25519.EdDSA: instance GHC.Show.Show Crypto.ECC.Ed25519.EdDSA.Point
- Crypto.ECC.Ed25519.EdDSA: instance GHC.Show.Show Crypto.ECC.Ed25519.EdDSA.VerifyResult
- Crypto.ECC.Ed25519.EdDSA: ison :: Point -> Bool
- Crypto.ECC.Ed25519.EdDSA: keyPoint :: SecFPrime -> PubKeyPoint
- Crypto.ECC.Ed25519.EdDSA: l :: FPrime
- Crypto.ECC.Ed25519.EdDSA: listofbits :: FPrime -> [FPrime]
- Crypto.ECC.Ed25519.EdDSA: null :: FPrime
- Crypto.ECC.Ed25519.EdDSA: padd :: Point -> Point -> Point
- Crypto.ECC.Ed25519.EdDSA: pmul :: Point -> FPrime -> Point
- Crypto.ECC.Ed25519.EdDSA: pointtobs :: Point -> ByteString
- Crypto.ECC.Ed25519.EdDSA: putFPrime :: FPrime -> Put
- Crypto.ECC.Ed25519.EdDSA: q :: FPrime
- Crypto.ECC.Ed25519.EdDSA: sign :: SecKey -> Message -> Either String Signature
- Crypto.ECC.Ed25519.EdDSA: sign_detached :: SecKey -> Message -> Either String Signature
- Crypto.ECC.Ed25519.EdDSA: type Message = ByteString
- Crypto.ECC.Ed25519.EdDSA: type PubKey = ByteString
- Crypto.ECC.Ed25519.EdDSA: type PubKeyPoint = Point
- Crypto.ECC.Ed25519.EdDSA: type SecFPrime = FPrime
- Crypto.ECC.Ed25519.EdDSA: type SecKey = ByteString
- Crypto.ECC.Ed25519.EdDSA: type Signature = ByteString
- Crypto.ECC.Ed25519.EdDSA: xrecover :: FPrime -> Integer -> FPrime
- Crypto.ECC.NIST.Base: [ECPpF2] :: F2 -> F2 -> F2 -> ECPF F2
- Crypto.ECC.NIST.Base: [ECPp] :: FPrime -> FPrime -> FPrime -> ECPF FPrime
- Crypto.ECC.NIST.Base: [ECb] :: Int -> Int -> F2 -> F2 -> FPrime -> EC F2
- Crypto.ECC.NIST.Base: [ECi] :: Int -> FPrime -> FPrime -> FPrime -> EC FPrime
- Crypto.ECC.NIST.Base: affine :: EC a -> ECPF a -> (a, a)
- Crypto.ECC.NIST.Base: data EC a
- Crypto.ECC.NIST.Base: data ECPF a
- Crypto.ECC.NIST.Base: data F2
- Crypto.ECC.NIST.Base: export :: EC a -> ECPF a -> (Integer, Integer)
- Crypto.ECC.NIST.Base: instance GHC.Classes.Eq (Crypto.ECC.NIST.Base.EC a)
- Crypto.ECC.NIST.Base: instance GHC.Classes.Eq (Crypto.ECC.NIST.Base.ECPF a)
- Crypto.ECC.NIST.Base: instance GHC.Show.Show (Crypto.ECC.NIST.Base.EC a)
- Crypto.ECC.NIST.Base: instance GHC.Show.Show (Crypto.ECC.NIST.Base.ECPF a)
- Crypto.ECC.NIST.Base: ison :: EC a -> ECPF a -> Bool
- Crypto.ECC.NIST.Base: padd :: EC a -> ECPF a -> ECPF a -> ECPF a
- Crypto.ECC.NIST.Base: pdouble :: EC a -> ECPF a -> ECPF a
- Crypto.ECC.NIST.Base: pmul :: EC a -> ECPF a -> FPrime -> ECPF a
- Crypto.ECC.NIST.Base: type FPrime = Integer
- Crypto.ECC.NIST.ECDH: basicecdh :: EC Integer -> Integer -> ECPF Integer -> Integer
- Crypto.ECC.NIST.StandardCurves: StandardCurve :: Int -> FPrime -> FPrime -> FPrime -> FPrime -> FPrime -> StandardCurve
- Crypto.ECC.NIST.StandardCurves: StandardCurveF2 :: Int -> F2 -> FPrime -> Int -> F2 -> F2 -> F2 -> StandardCurve
- Crypto.ECC.NIST.StandardCurves: [stdcF_a] :: StandardCurve -> Int
- Crypto.ECC.NIST.StandardCurves: [stdcF_b] :: StandardCurve -> F2
- Crypto.ECC.NIST.StandardCurves: [stdcF_l] :: StandardCurve -> Int
- Crypto.ECC.NIST.StandardCurves: [stdcF_p] :: StandardCurve -> F2
- Crypto.ECC.NIST.StandardCurves: [stdcF_r] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: [stdcF_xp] :: StandardCurve -> F2
- Crypto.ECC.NIST.StandardCurves: [stdcF_yp] :: StandardCurve -> F2
- Crypto.ECC.NIST.StandardCurves: [stdc_b] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: [stdc_l] :: StandardCurve -> Int
- Crypto.ECC.NIST.StandardCurves: [stdc_p] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: [stdc_r] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: [stdc_xp] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: [stdc_yp] :: StandardCurve -> FPrime
- Crypto.ECC.NIST.StandardCurves: b283 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: data StandardCurve
- Crypto.ECC.NIST.StandardCurves: k283 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: p192 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: p224 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: p256 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: p384 :: StandardCurve
- Crypto.ECC.NIST.StandardCurves: p521 :: StandardCurve
- Crypto.F2: F2 :: {-# UNPACK #-} !Int -> !(Vector Word) -> F2
- Crypto.F2: add :: F2 -> F2 -> F2
- Crypto.F2: addr :: F2 -> F2 -> F2 -> F2
- Crypto.F2: data F2
- Crypto.F2: eq :: F2 -> F2 -> Bool
- Crypto.F2: fromInteger :: Int -> Integer -> F2
- Crypto.F2: instance GHC.Show.Show Crypto.F2.F2
- Crypto.F2: inv :: F2 -> F2 -> F2
- Crypto.F2: mul :: F2 -> F2 -> F2
- Crypto.F2: mulr :: F2 -> F2 -> F2 -> F2
- Crypto.F2: pow :: (Bits a, Integral a) => F2 -> F2 -> a -> F2
- Crypto.F2: redc :: F2 -> F2 -> F2
- Crypto.F2: shift :: F2 -> Int -> F2
- Crypto.F2: square :: F2 -> F2
- Crypto.F2: testBit :: F2 -> Int -> Bool
- Crypto.F2: toInteger :: F2 -> Integer
- Crypto.Fi: testBit :: FPrime -> Int -> Bool
+ Crypto.ECC.Ed25519.Internal: SigOK :: SigOK
+ Crypto.ECC.Ed25519.Internal: data Point
+ Crypto.ECC.Ed25519.Internal: data SecKey
+ Crypto.ECC.Ed25519.Internal: data SigOK
+ Crypto.ECC.Ed25519.Internal: getFPrime32 :: ByteString -> Either String FPrime
+ Crypto.ECC.Ed25519.Internal: type Message = ByteString
+ Crypto.ECC.Ed25519.Internal: type PubKey = ByteString
+ Crypto.ECC.Ed25519.Internal: type Signature = ByteString
+ Crypto.ECC.Ed25519.Internal: type SignedMessage = ByteString
+ Crypto.ECC.Ed25519.Internal: type VerifyResult = Either String SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: Point :: (FPrime, FPrime, FPrime, FPrime) -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: SecKeyBytes :: ByteString -> SecKey
+ Crypto.ECC.Ed25519.Internal.Ed25519: SecNum :: FPrime -> SecFPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: SigOK :: SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: alleeins :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: b :: Int
+ Crypto.ECC.Ed25519.Internal.Ed25519: bPoint :: Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: bstopoint :: ByteString -> Either String Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: by :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: clamp :: ByteString -> Either String FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: convert64BEtoLE8Byte :: FPrime -> ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: convertLE8ByteTo64BE :: ByteString -> Either String FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: d :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: data SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: eins :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: getFPrime32 :: ByteString -> Either String FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: getFPrime64 :: ByteString -> Either String FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: h :: ByteString -> ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: i :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: inf :: Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: instance GHC.Classes.Eq Crypto.ECC.Ed25519.Internal.Ed25519.Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: instance GHC.Classes.Eq Crypto.ECC.Ed25519.Internal.Ed25519.SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: instance GHC.Show.Show Crypto.ECC.Ed25519.Internal.Ed25519.Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: instance GHC.Show.Show Crypto.ECC.Ed25519.Internal.Ed25519.SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: ison :: Point -> Bool
+ Crypto.ECC.Ed25519.Internal.Ed25519: k :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: l :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: newtype Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: newtype SecFPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: newtype SecKey
+ Crypto.ECC.Ed25519.Internal.Ed25519: null :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: padd :: Point -> Point -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: pdouble :: Point -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: ph :: ByteString -> ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: pmul :: Point -> FPrime -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: pneg :: Point -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: pointtobs :: Point -> ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: putFPrime :: FPrime -> ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: q :: FPrime
+ Crypto.ECC.Ed25519.Internal.Ed25519: scale :: Point -> Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: type Message = ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: type PubKey = ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: type PubKeyPoint = Point
+ Crypto.ECC.Ed25519.Internal.Ed25519: type Signature = ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: type SignedMessage = ByteString
+ Crypto.ECC.Ed25519.Internal.Ed25519: type VerifyResult = Either String SigOK
+ Crypto.ECC.Ed25519.Internal.Ed25519: xrecover :: FPrime -> Integer -> FPrime
+ Crypto.ECC.Ed25519.Sign: SigOK :: SigOK
+ Crypto.ECC.Ed25519.Sign: data SecKey
+ Crypto.ECC.Ed25519.Sign: data SigOK
+ Crypto.ECC.Ed25519.Sign: dsign :: SecKey -> Message -> Either String Signature
+ Crypto.ECC.Ed25519.Sign: dverify :: PubKey -> Signature -> Message -> VerifyResult
+ Crypto.ECC.Ed25519.Sign: genkeys :: CryptoRandomGen g => g -> Either String (SecKey, PubKey)
+ Crypto.ECC.Ed25519.Sign: genkeysSimple :: IO (Either String (SecKey, PubKey))
+ Crypto.ECC.Ed25519.Sign: publickey :: SecKey -> Either String PubKey
+ Crypto.ECC.Ed25519.Sign: sign :: SecKey -> Message -> Either String SignedMessage
+ Crypto.ECC.Ed25519.Sign: type Message = ByteString
+ Crypto.ECC.Ed25519.Sign: type PubKey = ByteString
+ Crypto.ECC.Ed25519.Sign: type Signature = ByteString
+ Crypto.ECC.Ed25519.Sign: type SignedMessage = ByteString
+ Crypto.ECC.Ed25519.Sign: type VerifyResult = Either String SigOK
+ Crypto.ECC.Ed25519.Sign: verify :: PubKey -> SignedMessage -> VerifyResult
+ Crypto.ECC.Weierstrass.ECDH: basicecdh :: EC Integer -> ECPF Integer -> Integer -> Integer
+ Crypto.ECC.Weierstrass.ECDH: data EC a
+ Crypto.ECC.Weierstrass.ECDH: data ECPF a
+ Crypto.ECC.Weierstrass.ECDSA: basicecdsa :: ByteString -> Integer -> Integer -> Either String (Integer, Integer)
+ Crypto.ECC.Weierstrass.ECDSA: basicecdsaVerify :: ECPF Integer -> (Integer, Integer) -> ByteString -> Bool
+ Crypto.ECC.Weierstrass.ECDSA: data ECPF a
+ Crypto.ECC.Weierstrass.Internal: affine :: EC a -> ECPF a -> (Integer, Integer)
+ Crypto.ECC.Weierstrass.Internal: data EC a
+ Crypto.ECC.Weierstrass.Internal: data ECPF a
+ Crypto.ECC.Weierstrass.Internal: export :: EC a -> ECPF a -> (Integer, Integer)
+ Crypto.ECC.Weierstrass.Internal: isinf :: EC a -> ECPF a -> Bool
+ Crypto.ECC.Weierstrass.Internal: ison :: EC a -> ECPF a -> Bool
+ Crypto.ECC.Weierstrass.Internal: padd :: EC a -> ECPF a -> ECPF a -> ECPF a
+ Crypto.ECC.Weierstrass.Internal: pdouble :: EC a -> ECPF a -> ECPF a
+ Crypto.ECC.Weierstrass.Internal: pmul :: EC a -> ECPF a -> FPrime -> ECPF a
+ Crypto.ECC.Weierstrass.Internal: type FPrime = Integer
+ Crypto.ECC.Weierstrass.Internal.Curvemath: [ECPp] :: FPrime -> FPrime -> FPrime -> ECPF FPrime
+ Crypto.ECC.Weierstrass.Internal.Curvemath: [ECi] :: Int -> FPrime -> FPrime -> FPrime -> EC FPrime
+ Crypto.ECC.Weierstrass.Internal.Curvemath: affine :: EC a -> ECPF a -> (Integer, Integer)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: data EC a
+ Crypto.ECC.Weierstrass.Internal.Curvemath: data ECPF a
+ Crypto.ECC.Weierstrass.Internal.Curvemath: export :: EC a -> ECPF a -> (Integer, Integer)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: instance GHC.Classes.Eq (Crypto.ECC.Weierstrass.Internal.Curvemath.EC a)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: instance GHC.Classes.Eq (Crypto.ECC.Weierstrass.Internal.Curvemath.ECPF a)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: instance GHC.Show.Show (Crypto.ECC.Weierstrass.Internal.Curvemath.EC a)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: instance GHC.Show.Show (Crypto.ECC.Weierstrass.Internal.Curvemath.ECPF a)
+ Crypto.ECC.Weierstrass.Internal.Curvemath: isinf :: EC a -> ECPF a -> Bool
+ Crypto.ECC.Weierstrass.Internal.Curvemath: ison :: EC a -> ECPF a -> Bool
+ Crypto.ECC.Weierstrass.Internal.Curvemath: padd :: EC a -> ECPF a -> ECPF a -> ECPF a
+ Crypto.ECC.Weierstrass.Internal.Curvemath: pdouble :: EC a -> ECPF a -> ECPF a
+ Crypto.ECC.Weierstrass.Internal.Curvemath: pmul :: EC a -> ECPF a -> FPrime -> ECPF a
+ Crypto.ECC.Weierstrass.StandardCurves: StandardCurve :: Int -> FPrime -> FPrime -> FPrime -> FPrime -> FPrime -> StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_b] :: StandardCurve -> FPrime
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_l] :: StandardCurve -> Int
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_p] :: StandardCurve -> FPrime
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_r] :: StandardCurve -> FPrime
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_xp] :: StandardCurve -> FPrime
+ Crypto.ECC.Weierstrass.StandardCurves: [stdc_yp] :: StandardCurve -> FPrime
+ Crypto.ECC.Weierstrass.StandardCurves: data StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: p192 :: StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: p224 :: StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: p256 :: StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: p384 :: StandardCurve
+ Crypto.ECC.Weierstrass.StandardCurves: p521 :: StandardCurve
- Crypto.Common: log2len :: (Integral a, Bits a) => a -> Int
+ Crypto.Common: log2len :: Integer -> Int
- Crypto.Common: wordMax :: (Integral a) => a
+ Crypto.Common: wordMax :: Integral a => a
- Crypto.Fi: pow :: (Bits a, Integral a) => FPrime -> FPrime -> a -> FPrime
+ Crypto.Fi: pow :: FPrime -> FPrime -> Integer -> FPrime
Files
- README +1/−8
- Setup.hs +0/−0
- bench/bench.hs +55/−0
- dist/build/eccrypto-testsuiteStub/eccrypto-testsuiteStub-tmp/eccrypto-testsuiteStub.hs +5/−0
- eccrypto.cabal +64/−31
- src/Crypto/Common.hs +20/−11
- src/Crypto/ECC/Ed25519/EdDSA.hs +0/−269
- src/Crypto/ECC/Ed25519/Internal.hs +29/−0
- src/Crypto/ECC/Ed25519/Internal/Ed25519.hs +341/−0
- src/Crypto/ECC/Ed25519/Sign.hs +108/−0
- src/Crypto/ECC/NIST/Base.hs +0/−272
- src/Crypto/ECC/NIST/ECDH.hs +0/−30
- src/Crypto/ECC/NIST/StandardCurves.hs +0/−121
- src/Crypto/ECC/Weierstrass/ECDH.hs +33/−0
- src/Crypto/ECC/Weierstrass/ECDSA.hs +60/−0
- src/Crypto/ECC/Weierstrass/Internal.hs +31/−0
- src/Crypto/ECC/Weierstrass/Internal/Curvemath.hs +368/−0
- src/Crypto/ECC/Weierstrass/StandardCurves.hs +123/−0
- src/Crypto/F2.hs +10/−10
- src/Crypto/FPrime.hs +181/−0
- src/Crypto/Fi.hs +30/−20
- src/bench.hs +0/−55
- test/P192 +207/−0
- test/P224 +207/−0
- test/P256 +207/−0
- test/P384 +207/−0
- test/P521 +207/−0
- test/Tests.hs +128/−0
- test/sign.input too large to diff
README view
@@ -4,13 +4,6 @@ Enter elliptic curves: smaller numbers are necessary and everything is faster. Maybe this library is not for embedded system usage, but now people can experiment with ECC for those use-cases where some form of RSA would be chosen otherwise. -Timing Attack Resistance--------------------------The point multiplication uses the montgomery ladder algorithm which should be timing attack resistant, but when mul by a number in binary form 1000..0 the operation gets strangely fast (us instead of ms) and 1000..0001 it is strangely slow (1.5 times), which hints to something fishy going on. More research will follow, but sidechannel-resistance is not totally out-of-focus. -Testing has given me the idea that the following-zeroes-case massively benefits from branch-prediction and the trailing-one-case throws it totally off (will have to check that on other CPUs). "More natural" numbers are safer (tested), but I wouldn't dare to say that the matter is resolved.-P.S.: 2^N-1 does not show the cache-problem, only long rows of zeroes.-- Motivation -----------This is a side-project from which other people may benefit. Due to time-constraints, I can't work as much on it as I would like. If you use/like it or want to make some criticism heard, please write me an email.+This is a side-project from which other people may benefit. Due to time-constraints, I can't work as much on it as I would like. If you use/like it or want to make some criticism heard, please write an email.
Setup.hs view
+ bench/bench.hs view
@@ -0,0 +1,55 @@+-----------------------------------------------------------------------------+-- |+-- Module : +-- Copyright : (c) Marcel Fourné 20[09..14]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+--+-- benchmarks+-- recommended:+-- $ ghc --make -threaded bench.hs+-- best performance measured with just 1 thread+--+-----------------------------------------------------------------------------+{-# OPTIONS_GHC -O2 -feager-blackholing #-}++{-# LANGUAGE ScopedTypeVariables #-}++import Crypto.ECC.Weierstrass.Internal.Curvemath+import Crypto.ECC.Weierstrass.StandardCurves+import Crypto.ECC.Weierstrass.ECDSA+import Crypto.ECC.Weierstrass.ECDH+import Control.Monad.Random+import Criterion+import Criterion.Main+import qualified Crypto.ECC.Ed25519.Sign as ED+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as C8++main::IO ()+main = do+ let c1 = ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)+ p1 = ECPp (stdc_xp p256) (stdc_yp p256) 1+ rand = 93151144317885463729940025875124971369191600717633105593660251066268358953543+ pub = ECPp 49820351311576200663416054279040683857746363070013834679270516876052449262634 112699216918648906269327207660688102462037435574122213014814143327521473380783 18523244708209522220381629035092551864971849988089188687523906648093563992014+ sig = Right (108572692541258481963147160841164483731413918681474718309791481920132693582956,115780011294752138434352400342471965517508651449475483422239281368412284031413)+ Right (r,s) = sig+ pkfix = C8.pack "\185`\134^:gJw\146E\137@dw1\243w\212\178\213ry\140\159\137\&7yT+Y\156\EM"+ skfix = C8.pack "\131\190G\200\SYN\191&<\ETBd\223W\145}3\247#8\133\195\NUL\139\&8\138\197\132\191\255\SOC/\SOH"+ sigfix = C8.pack "S\EM\199\149\135\DC4Zr\242=\227(\139D\US,\232\159\210m\131\176\145\155\189\166Gl\186X\157\149U(zhd\224\133\DC1\237\FS\DLE\DC3\223S\153\218\214)\219o\177\n\248F\223^A\236\196\175N\STX"+ k13' <- evalRandIO $ getRandomR (1,stdc_p p256)+ Right (sk,pk) <- ED.genkeysSimple+ defaultMain [ bgroup "NIST P-256" [ bench "ECDHp256" $ whnf (basicecdh c1 p1) k13'+ , bench "ECDSAp256 sign" $ whnf (basicecdsa (BS.pack [0..255]) rand) rand+ , bench "ECDSAp256 verify" $ whnf (\x -> basicecdsaVerify pub (r,x) (BS.pack [0..255])) s+ ]+ , bgroup "Ed25519" [ bench "sign" $ whnf (benchED sk) 1+ , bench "verify" $ whnf (verifyED pkfix sigfix) 1+ ]+ ]++benchED sk n = let m = BS.pack [0..(255+n-n)]+ in ED.dsign sk m++verifyED pk sig n = let m = BS.pack [0..(255+n-n)]+ in ED.verify pk (BS.append sig m)
+ dist/build/eccrypto-testsuiteStub/eccrypto-testsuiteStub-tmp/eccrypto-testsuiteStub.hs view
@@ -0,0 +1,5 @@+module Main ( main ) where+import Distribution.Simple.Test.LibV09 ( stubMain )+import Tests ( tests )+main :: IO ()+main = stubMain tests
eccrypto.cabal view
@@ -1,47 +1,80 @@ Name: eccrypto-Version: 0.0.1-Synopsis: Elliptic Curve Cryptography for Haskell+Version: 0.1.0+Synopsis: Elliptic Curve Cryptography for Haskell Description: Elliptic Curve Cryptography in Haskell, evolved for correctness and practical usability from higher-level libraries.- .- The implementation is pure Haskell and as generic and fast as reasonably possible. Timing-attack resistance is important, failure must be documented.- .- This library was formerly known and its code originated as hecc, but since this would imply Hyperelliptic ECC, the name was changed. - .- Also the scope was changed by selecting best internal formats and no longer trying to be overly general, allowing more optimizations.- .- N.B.: F2 is faulty and slow.- .- More secure curves will be added.+ .+ The implementation is pure Haskell and as generic and fast as reasonably possible. Timing-attack resistance is important, failure must be documented.+ .+ This library was formerly known and its code originated as hecc, but since this would imply Hyperelliptic ECC, the name was changed.+ .+ Also the scope was changed by selecting best internal formats and no longer trying to be overly general, allowing more optimizations. License: BSD3 License-file: COPYING-Copyright: (c) Marcel Fourné, 2009-2016+Copyright: (c) Marcel Fourné, 2009-2019 Author: Marcel Fourné Maintainer: Marcel Fourné (haskell@marcelfourne.de)-Category: Cryptography-Stability: beta+Category: Cryptography+Stability: beta Build-Type: Simple Cabal-Version: >=1.9-Data-Files: README-Extra-Source-Files: src/bench.hs+Data-Files: README+Extra-Source-Files: test/P192+ , test/P224+ , test/P256+ , test/P384+ , test/P521+ , test/sign.input+ , src/Crypto/F2.hs+ , src/Crypto/FPrime.hs Library hs-source-dirs: src Build-Depends:- base >= 4 && < 5- , bytestring >= 0.10 && < 0.11- , cereal >=0.4 && < 0.6- , SHA >= 1.6.4 && < 1.7- , crypto-api >= 0.13 && < 0.14- , vector >= 0.10 && < 0.12+ base >= 4 && < 5+ , bytestring >= 0.10 && < 0.11+ , crypto-api >= 0.13 && < 0.14+ , integer-gmp >= 1.0 && < 1.1+ , SHA >= 1.6.4 && < 1.7 Exposed-modules:- Crypto.Common- Crypto.F2- Crypto.Fi- Crypto.ECC.NIST.Base- Crypto.ECC.NIST.ECDH- Crypto.ECC.NIST.StandardCurves- Crypto.ECC.Ed25519.EdDSA- ghc-options: -Wall+ Crypto.Common+ Crypto.Fi+ Crypto.ECC.Weierstrass.Internal+ Crypto.ECC.Weierstrass.Internal.Curvemath+ Crypto.ECC.Weierstrass.ECDH+ Crypto.ECC.Weierstrass.ECDSA+ Crypto.ECC.Weierstrass.StandardCurves+ Crypto.ECC.Ed25519.Sign+ Crypto.ECC.Ed25519.Internal+ Crypto.ECC.Ed25519.Internal.Ed25519+ ghc-options:+ -Wall+ -O2+ -feager-blackholing++Test-Suite eccrypto-testsuite+ Type: detailed-0.9+ hs-source-dirs: test+ test-Module: Tests+ Build-depends:+ base >= 4 && < 5+ , base16-bytestring+ , bytestring >= 0.10 && < 0.11+ , Cabal >= 1.9.2+ , eccrypto+ ghc-options: -O2+ -feager-blackholing++benchmark eccrypto-benchmark+ type: exitcode-stdio-1.0+ hs-source-dirs: bench+ main-is: bench.hs+ build-depends: base >= 4 && < 5+ , bytestring >= 0.10 && < 0.11+ , criterion >= 1.4 && < 1.6+ , eccrypto+ , MonadRandom >= 0.5 && < 0.6+ ghc-options: -O2+ -feager-blackholing source-repository head type: git
src/Crypto/Common.hs view
@@ -13,23 +13,26 @@ ----------------------------------------------------------------------------- {-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Trustworthy, NoImplicitPrelude, MagicHash #-} module Crypto.Common ( wordMax , wordSize , sizeinWords- , zero+{- , zero , one , two- , three+ , three -} , log2len , testcond ) where -import Prelude (Num(..),Int,($),(+),(-),(*),fromInteger,Integral,takeWhile,length,iterate,(>),(<=),toInteger,maxBound,rem,quot,quotRem,div)-import qualified Data.Bits as B (Bits(..))-import qualified Data.Word as W (Word)-import qualified Data.Vector.Unboxed as V+import safe Prelude (Num(..),Int,($),(+),(-),fromInteger,Integral,Integer,(>),toInteger,maxBound,quotRem)+import safe qualified Data.Bits as B (Bits(..),FiniteBits(..))+import safe qualified Data.Word as W (Word)+-- import qualified Data.Vector.Unboxed as V+import GHC.Exts+import GHC.Integer.Logarithms -- | return the maximum value storable in a Word wordMax :: (Integral a) => a@@ -37,15 +40,16 @@ -- | return the bitSize of a Word wordSize :: Int-wordSize = B.bitSize (0::W.Word)+wordSize = B.finiteBitSize (0::W.Word) {-# INLINE wordSize #-} -- | determine the needed storage for a bitlength in Words sizeinWords :: Int -> Int sizeinWords 0 = 1 -- or error? 0 bit len?!-sizeinWords t = let (w,r) = (abs t) `quotRem` wordSize+sizeinWords t = let (w,r) = abs t `quotRem` wordSize in if r > 0 then w + 1 else w- ++{- -- constant vectors for comparisons etc. -- | a vector of zeros of requested length zero :: Int -> V.Vector W.Word@@ -59,11 +63,16 @@ -- | a vector of zeros of requested length, but least significant word 3 three :: Int -> V.Vector W.Word three l = V.singleton 3 V.++ V.replicate (sizeinWords l - 1) 0+-} --- | returning the binary length of an Integer-log2len :: (Integral a, B.Bits a) => a -> Int+-- returning the binary length of an Integer, not sidechannel secure!+-- | returning the binary length of an Integer, uses integer-gmp directly+log2len :: Integer -> Int+{- log2len 0 = 1 log2len n = length (takeWhile (<=n) (iterate (*2) 1))+-- -}+log2len x = (I# (integerLog2# x)) + 1 {-# INLINABLE log2len #-} -- | we want word w at position i to result in a word to multiply by, eliminating branching
− src/Crypto/ECC/Ed25519/EdDSA.hs
@@ -1,269 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Crypto.ECC.Bernstein.Ed25519--- Copyright : (c) Marcel Fourné 20[14..]--- License : BSD3--- Maintainer : Marcel Fourné (haskell@marcelfourne.de)--- Stability : alpha--- Portability : Good------ Long-time plan: get rid of Integer and do all field arithmetic const-time by hand--------------------------------------------------------------------------------{-# OPTIONS_GHC -O2 -feager-blackholing #-}-{-# LANGUAGE ScopedTypeVariables,PackageImports #-}--module Crypto.ECC.Ed25519.EdDSA {-( genkeys- , genkeys_simple- , sign_detached- , sign- , verify- )-- -}- where--import Prelude (Eq,Show,(==),(/=),(&&),Int,show,Bool(False,True),(++),($),fail,undefined,(+),(-),(*),otherwise,(<),(>),(<=),(>=),maxBound,rem,quot,quotRem,error,(/),(^),mod,IO,return,not,head,tail,mapM_,Maybe,Either(Left,Right),String,map,Integer,foldr,abs)-import qualified Data.Bits as B (shift,(.&.),(.|.))-import qualified Prelude as P (fromInteger,toInteger,fromIntegral)-import Crypto.Common-import qualified Crypto.Fi as FP--- import qualified Crypto.FPrime as FP-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL-import qualified Data.Digest.Pure.SHA as H-import qualified Data.Word as W (Word64)-import qualified "crypto-api" Crypto.Random as CR-import qualified Data.Serialize as S-import qualified Data.Serialize.Get as SG (getWord64le)-import qualified Data.Serialize.Put as SP (putWord64le)---- | working on exactly 256 bits-b :: Int-b = 256---- | the large prime-q :: FP.FPrime-q = FP.fromInteger b $ 2^(255::Integer) - 19---- | curve parameter l-l :: FP.FPrime-l = FP.addr q (FP.pow q (FP.fromInteger b 2) (FP.fromInteger b 252)) (FP.fromInteger b 27742317777372353535851937790883648493)---- | curve parameter d-d :: FP.FPrime-d = FP.mulr q (FP.neg q $ FP.fromInteger b 121665) $ FP.inv q (FP.fromInteger b 121666)---- | sqrt (-1) on our curve-i :: FP.FPrime-i = FP.pow q 2 (FP.shift (FP.subr q q (FP.fromInteger b 1)) (-2))---- | wrapper for our hash function-h :: BS.ByteString -> BS.ByteString-h bs = BSL.toStrict $ H.bytestringDigest $ H.sha512 $ BSL.fromStrict bs---- | the y coordinate of the base point of the curve-by :: FP.FPrime-by = FP.mulr q (FP.fromInteger b 4) (FP.inv q $ FP.fromInteger b 5)---- additive neutral element-inf :: Point-inf = Point (FP.fromInteger b 0, FP.fromInteger b 1)---- | special form of FPrime, no bits set-null :: FP.FPrime-null = FP.fromInteger b 0---- | special form of FPrime, lowest bit set-eins :: FP.FPrime-eins = FP.fromInteger b 1---- | special form of FPrime, all bits set-alleeins:: FP.FPrime-alleeins = FP.fromInteger b (2^b-1)---- | recover the x coordinate from the y coordinate and a signum-xrecover :: FP.FPrime -> Integer -> FP.FPrime-xrecover y sign' = let ysqu = FP.pow q y (2::Int)- u = FP.subr q ysqu eins- v = FP.addr q eins $ FP.mulr q d ysqu- beta = FP.mulr q (FP.mulr q u (FP.pow q v (3::Int))) (FP.pow q (FP.mulr q u (FP.pow q v (7::Int))) (FP.shift (FP.sub q (FP.fromInteger b 5)) (-3)))- -- v*beta^2 + u == 0? -> z [all-0 or some pattern]; foldr (.|.) 0 [bits from z] -> [0|1] -> [i|eins]- fixroot num = let c = FP.addr q (FP.mulr q v (FP.pow q num (2::Int))) u- s = foldr (B..|.) 0 $ listofbits c- pattern = FP.mul alleeins (FP.sub eins s) -- pattern for == -u- invpattern = FP.mul alleeins s -- pattern for /= -u- in FP.add (i B..&. pattern) (eins B..&. invpattern)- zwischen = FP.mulr q beta (fixroot beta)- signum num sign'' = let signbit = abs (sign'' - (num `mod` 2)) -- y:(0 pos, 1 neg), beta`mod`2:(0 pos, 1 neg)- pat = FP.mul alleeins (FP.sub eins signbit) -- pattern for pos- invpat = FP.mul alleeins signbit -- pattern for neg- in FP.add (eins B..&. pat) (FP.neg q eins B..&. invpat)- in FP.mulr q (signum zwischen sign') zwischen---- | convert a FPrime to a list of FPrimes, each 0 or 1 depending on the inputs bits-listofbits :: FP.FPrime -> [FP.FPrime]-listofbits c = let ex erg pos- | pos == 256 = erg- | otherwise = ex (FP.condBit c pos:erg) (pos + 1)- in ex [] (0::Int)---- | base point on the curve-bPoint :: Point-bPoint = Point (xrecover by 0, FP.redc q by)--- bPoint = Point (FP.fromInteger b 15112221349535400772501151409588531511454012693041857206046113283949847762202,FP.fromInteger b 46316835694926478169428394003475163141307993866256225615783033603165251855960)---- | scalar addition-padd :: Point -> Point -> Point-padd (Point (x1,y1)) (Point (x2,y2)) =- let x1y2 = FP.mulr q x1 y2- x2y1 = FP.mulr q x2 y1- y1y2 = FP.mulr q y1 y2- x1x2 = FP.mulr q x1 x2- dx1x2y1y2 = FP.mulr q (FP.mulr q d x1x2) y1y2- x3 = FP.mulr q (FP.addr q x1y2 x2y1) $ FP.inv q (FP.addr q eins dx1x2y1y2)- y3 = FP.mulr q (FP.addr q y1y2 x1x2) $ FP.inv q (FP.subr q eins dx1x2y1y2)- in Point (x3,y3)---- | scalar multiplication, branchfree in k, pattern-matched branch on j (length of k)-pmul :: Point -> FP.FPrime -> Point-pmul (Point (x,y)) k =- let ex erg j- | j < 0 = erg- | otherwise = let s = FP.condBit k j- pattern = FP.mul alleeins s- invpattern = FP.mul alleeins (FP.sub eins s)- in ex (padd (padd erg erg) (Point (x B..&. pattern, FP.add (y B..&. pattern) (eins B..&. invpattern)))) (j - 1)- in ex inf (log2len k - 1)-{---- branching montgomery- let ex p1 p2 j- | j < 0 = p1- | not (FP.testBit k j) = ex (padd p1 p1) (padd p1 p2) (j - 1)- | otherwise = ex (padd p1 p2) (padd p2 p2) (j - 1)- in ex inf (Point (x,y)) (log2len k - 1)--- -}---- | check if Point is on the curve, prevents some attacks-ison :: Point -> Bool-ison (Point (x,y)) = FP.addr q (FP.neg q (FP.pow q x(2::Int))) (FP.pow q y (2::Int)) == FP.addr q eins (FP.mulr q (FP.mulr q d (FP.pow q x (2::Int))) (FP.pow q y (2::Int)))----- | converts 32 little endian bytes into one FPrime-getFPrime :: S.Get FP.FPrime-getFPrime = do- lowest <- SG.getWord64le- lower <- SG.getWord64le- higher <- SG.getWord64le- highest <- SG.getWord64le- return (((P.toInteger lowest) + ((B.shift (P.toInteger lower) 64)::Integer) + (B.shift (P.toInteger higher) 128) + (B.shift (P.toInteger highest) 192))::Integer)----- | converts one FPrime into exactly 32 little endian bytes-putFPrime :: FP.FPrime -> S.Put-putFPrime num = do- let arg = FP.toInteger num- lowest = (P.fromInteger $ arg `mod` (2^(64::Integer)))::W.Word64- lower = (P.fromInteger $ B.shift (arg `mod` (2^(128::Integer))) (-64))::W.Word64- higher = (P.fromInteger $ B.shift (arg `mod` (2^(192::Integer))) (-128))::W.Word64- highest = (P.fromInteger $ B.shift arg (-192))::W.Word64- SP.putWord64le lowest- SP.putWord64le lower- SP.putWord64le higher- SP.putWord64le highest---- | convert a point on the curve to a ByteString-pointtobs :: Point -> BS.ByteString-pointtobs (Point (x,y)) = let yf = FP.add y (FP.shift (x B..&. eins) (b - 1))- in S.runPut $ putFPrime yf---- | convert a ByteString to a point on the curve-bstopoint :: BS.ByteString -> Either String Point-bstopoint bs = do let y = S.runGet getFPrime bs- case y of- Left _ -> Left "Could not decode Point"- Right (y'::FP.FPrime) -> let yf = y' B..&. (alleeins - (2^(b-1)))- xf = xrecover yf (FP.condBit y' (b-1)) - pt = Point (xf,yf)- in if ison pt then Right pt else Left "Point not on curve"---- | multiply the curve base point by a FPrime, giving a point on the curve-keyPoint :: SecFPrime -> PubKeyPoint-keyPoint = pmul bPoint---- [b Bits ] --- BigEndian 01x..x000 ==> ((getFPrime $ h k) .&. (2^254-1-(2^0+2^1+2^2)) .|. (2^254))--- .&. 28948022309329048855892746252171976963317496166410141009864396001978282409976 .|. 28948022309329048855892746252171976963317496166410141009864396001978282409984-a :: SecKey -> Either String SecFPrime-a k = let hashed = S.runGet getFPrime (h k)- in case hashed of- Right h' -> Right (((FP.toInteger h') B..&. 28948022309329048855892746252171976963317496166410141009864396001978282409976 B..|. 28948022309329048855892746252171976963317496166410141009864396001978282409984)::SecFPrime)- Left e -> Left e---- Public API + types--- TODO: make everything more explicit, esp. internals--data Point = Point (FP.FPrime,FP.FPrime) deriving (Eq,Show)--data VerifyResult = SigOK | SigBad deriving (Eq,Show)--type PubKey = BS.ByteString-type PubKeyPoint = Point-type SecKey = BS.ByteString-type SecFPrime = FP.FPrime-type Signature = BS.ByteString-type Message = BS.ByteString---- | generate a new key pair (secret and derived public key) using some external entropy-genkeys_simple :: IO (Either String (SecKey,PubKey))-genkeys_simple = do- (g :: CR.SystemRandom) <- CR.newGenIO- return $ genkeys g----- | generate a new key pair (secret and derived public key) using the supplied randomness-generator-genkeys :: (CR.CryptoRandomGen g) => g -> (Either String (SecKey,PubKey))-genkeys g = case CR.genBytes 32 g of- Left e -> Left (show e)- Right (bs,g') -> let secret = a bs- in case secret of- Left e -> Left e- Right sec -> let bigA = keyPoint sec- bigAbs = pointtobs bigA- in if ison bigA- then Right (bs,bigAbs)- else Left "private key is not on curve"---- | sign with secret key the message, resulting in message appended to the signature-sign :: SecKey -> Message -> Either String Signature-sign sk m = case sign_detached sk m of- Left e -> Left e- Right sig -> Right (BS.append sig m)---- | sign with secret key the message, resulting in a detached signature-sign_detached :: SecKey -> Message -> Either String Signature-sign_detached sk m = let r = S.runGet getFPrime $ h $ BS.append (BS.drop 32 $ h sk) m- in case r of- Left e -> Left e- Right r' -> let rB_ = pointtobs $ keyPoint r'- a' = a sk- in case a' of- Left e -> Left e- Right a'' -> let a_ = pointtobs $ keyPoint a''- t = S.runGet getFPrime (h $ rB_ `BS.append` a_ `BS.append` m)- in case t of- Left e -> Left e- Right t' -> let s = (r' + (t' * a'')) `mod` l- s_ = S.runPut $ putFPrime s- in Right (BS.append rB_ s_)---{---- | in: public key, message and signature, out: is signature valid for public key and message?-verify :: PubKey -> Signature -> Message -> VerifyResult-verify pk sig m = let r = undefined -- TODO- pka = undefined -- TODO- sb = undefined -- TODO- a' = undefined -- TODO- in if pmul sb 8 == padd (pmul r 8) (pmul (pmul a' (getFPrime $ h $ BS.append r $ BS.append pk m)) 8)- then SigOK- else SigBad--- -}
+ src/Crypto/ECC/Ed25519/Internal.hs view
@@ -0,0 +1,29 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Ed25519.Internal+-- Copyright : (c) Marcel Fourné 20[14..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : alpha+-- Portability : Bad+--+-- safe re-exports+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, NoImplicitPrelude #-}+++module Crypto.ECC.Ed25519.Internal ( Point+ , Message+ , PubKey+ , SecKey -- only type export, not constructors+ , Signature+ , SignedMessage+ , SigOK(..)+ , VerifyResult+ , getFPrime32+ )+where++import safe Crypto.ECC.Ed25519.Internal.Ed25519
+ src/Crypto/ECC/Ed25519/Internal/Ed25519.hs view
@@ -0,0 +1,341 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Ed25519.Internal.Ed25519+-- Copyright : (c) Marcel Fourné 20[14..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : alpha+-- Portability : Bad+--+-- This module contain the internal functions. It's use should be limited to the Sign module, which exports certain types without constructors, so the timing attack surface is only over the verified functions.+-- In other words: If an external module imports this module or uses unsafecoerce, it may circumvent the verifications against timing attacks!+--+-- Short-time plan: custom field arithmetic+-- TODO: optimal const time inversion in 25519, see eccss-20130911b.pdf+-- TODO: convert code to portable, get rid of Integer+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, ScopedTypeVariables, NoImplicitPrelude #-}++module Crypto.ECC.Ed25519.Internal.Ed25519 where++import safe Prelude (Eq,Show,(==),Int,Bool,($),(-),otherwise,(<),(^),mod,Either(Left,Right),String,Integer,abs,id)+import safe qualified Data.Bits as B (shift,(.&.),(.|.),xor)+import safe qualified Prelude as P (fromInteger,toInteger)+import safe qualified Crypto.Fi as FP+import safe qualified Data.ByteString as BS+import safe qualified Data.ByteString.Lazy as BSL+import safe qualified Data.Digest.Pure.SHA as H+import safe qualified Data.Word as W (Word8)++-- a point on the twisted Edwards curve, affine coordinates, neutral element (0,1)+-- | twisted Edwards curve point, extended point format (x,y,z,t), neutral element (0,1,1,0), c=1, a=-1 https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html, after "Twisted Edwards curves revisited" eprint 2008/522+newtype Point = Point (FP.FPrime,FP.FPrime,FP.FPrime,FP.FPrime) deriving (Eq,Show)++-- | clear signal that everything is ok+data SigOK = SigOK deriving (Show,Eq)++-- | Result of verifying a signature should only yield if it's good or bad, not more, but contains an error string if underlying primitives failed+type VerifyResult = Either String SigOK++-- | just a newtype for the public key (string of 32 bytes, b=256 bit)+type PubKey = BS.ByteString++-- | just a newtype for the public key as a point on the Edwards curve+type PubKeyPoint = Point++-- | just a wrapper for the secret key (string of 32 bytes, b=256 bit)+newtype SecKey = SecKeyBytes BS.ByteString++-- | just a wrapper for the secret key as a number+newtype SecFPrime = SecNum FP.FPrime++-- | just a newtype for the signature (string of 2*32 bytes, b=256 bit)+type Signature = BS.ByteString++-- | just a newtype for the message+type Message = BS.ByteString++-- | just a newtype for the signature with appended message+type SignedMessage = BS.ByteString++-- | working on exactly 256 bits+b :: Int+b = 256+{-# INLINABLE b #-}++-- | the large prime+q :: FP.FPrime+-- q = FP.fromInteger b $ 2^(255::Integer) - 19+q = FP.fromInteger b 57896044618658097711785492504343953926634992332820282019728792003956564819949+{-# INLINABLE q #-}++-- | curve parameter l, the group order, f.e. needed to use Farmat's little theorem+l :: FP.FPrime+-- l = FP.addr q (FP.pow q (FP.fromInteger b 2) (FP.fromInteger b 252)) (FP.fromInteger b 27742317777372353535851937790883648493)+l = FP.fromInteger b 7237005577332262213973186563042994240857116359379907606001950938285454250989+{-# INLINABLE l #-}++-- | curve parameter d, non-square element, -(121665/121666)+d :: FP.FPrime+-- d = FP.mulr q (P.neg q $ FP.fromInteger b 121665) $ FP.inv q (FP.fromInteger b 121666)+d = FP.fromInteger b 37095705934669439343138083508754565189542113879843219016388785533085940283555+{-# INLINABLE d #-}++-- | sqrt (-1) on our curve+i :: FP.FPrime+-- i = FP.pow q 2 (FP.shift (FP.subr q q (FP.fromInteger b 1)) (-2))+i = FP.fromInteger b 19681161376707505956807079304988542015446066515923890162744021073123829784752+{-# INLINABLE i #-}++-- | wrapper for our hash function+h :: BS.ByteString -> BS.ByteString+h bs = BSL.toStrict $ H.bytestringDigest $ H.sha512 $ BSL.fromStrict bs+-- h = H.hash+{-# INLINABLE h #-}++-- | the prehash function, id in PureEdDSA+ph :: BS.ByteString -> BS.ByteString+ph = id+{-# INLINABLE ph #-}++-- | the y coordinate of the base point of the curve+by :: FP.FPrime+-- by = FP.mulr q (FP.fromInteger b 4) (FP.inv q $ FP.fromInteger b 5)+by = FP.fromInteger b 46316835694926478169428394003475163141307993866256225615783033603165251855960+{-# INLINABLE by #-}++-- | additive neutral element, really (0,Z,Z,0)+inf :: Point+inf = Point (FP.fromInteger b 0, FP.fromInteger b 1, FP.fromInteger b 1, FP.fromInteger b 0)+{-# INLINABLE inf #-}++-- | special form of FPrime, no bits set+null :: FP.FPrime+null = FP.fromInteger b 0+{-# INLINABLE null #-}++-- | special form of FPrime, lowest bit set+eins :: FP.FPrime+eins = FP.fromInteger b 1+{-# INLINABLE eins #-}++-- | special form of FPrime, all bits set+alleeins:: FP.FPrime+-- alleeins = FP.fromInteger b (2^b-1)+alleeins = FP.fromInteger b 115792089237316195423570985008687907853269984665640564039457584007913129639935+{-# INLINABLE alleeins #-}++-- | recover the x coordinate from the y coordinate and a signum+xrecover :: FP.FPrime -> Integer -> FP.FPrime+xrecover y sign' = let yy = FP.mulr q y y+ u = FP.subr q yy eins -- u = y^2-1+ v = FP.addr q eins $ FP.mulr q d yy -- v = dy^2+1+ beta = FP.mulr q (FP.mulr q u $ FP.mulr q v $ FP.square q v) (FP.pow q (FP.mulr q u (FP.pow q v (7::Integer))) (FP.shift (FP.sub q (FP.fromInteger b 5)) (-3)))+ -- v*beta^2 + u == 0? -> z [all-0 or some pattern]; foldr (.|.) 0 [bits from z] -> [0|1] -> [i|eins]+ fixroot num = let c = FP.addr q (FP.mulr q v (FP.mulr q num num)) u+ -- s = foldr (B..|.) 0 $ listofbits c+ s = -(FP.shift (-(B.xor c null)) (-255)) -- better than listbuilding, eccss-20130911b.pdf p.77/133 -- TODO: portable lowlevel!+ realpattern = FP.mul alleeins (FP.sub eins s) -- pattern for == -u+ invpattern = FP.mul alleeins s -- pattern for /= -u+ in FP.add (i B..&. realpattern) (eins B..&. invpattern)+ zwischen = FP.mulr q beta (fixroot beta)+ signum num sign'' = let signbit = abs (sign'' - (num `mod` 2)) -- y:(0 pos, 1 neg), beta`mod`2:(0 pos, 1 neg)+ pat = FP.mul alleeins (FP.sub eins signbit) -- pattern for pos+ invpat = FP.mul alleeins signbit -- pattern for neg+ in FP.add (eins B..&. pat) (FP.neg q eins B..&. invpat)+ in FP.mulr q (signum zwischen sign') zwischen -- multiply by masked one or zero+++-- | base point on the curve+bPoint :: Point+bPoint = Point (FP.fromInteger b 15112221349535400772501151409588531511454012693041857206046113283949847762202,FP.fromInteger b 46316835694926478169428394003475163141307993866256225615783033603165251855960, FP.fromInteger b 1, FP.fromInteger b 46827403850823179245072216630277197565144205554125654976674165829533817101731)+{-# INLINABLE bPoint #-}++-- | point negation+pneg :: Point -> Point+pneg (Point (x,y,z,t)) = Point (FP.neg q x, y, z, FP.neg q t)+{-# INLINABLE pneg #-}++-- | k=2*d, constant used for point addition+k :: FP.FPrime+k = FP.mulr q d 2+{-# INLINABLE k #-}++-- | point addition+-- add-2008-hwcd-3+padd :: Point -> Point -> Point+padd (Point (x1,y1,z1,t1)) (Point (x2,y2,z2,t2)) =+ let a' = FP.mulr q (FP.subr q y1 x1) (FP.subr q y2 x2)+ b' = FP.mulr q (FP.addr q y1 x1) (FP.addr q y2 x2)+ c' = FP.mulr q k $ FP.mulr q t1 t2+ d' = FP.mulr q 2 $ FP.mulr q z1 z2+ e' = FP.subr q b' a'+ f' = FP.subr q d' c'+ g' = FP.addr q d' c'+ h' = FP.addr q b' a'+ x3 = FP.mulr q e' f'+ y3 = FP.mulr q g' h'+ z3 = FP.mulr q f' g'+ t3 = FP.mulr q e' h'+ in Point (x3,y3,z3,t3)++-- | point doubling+pdouble :: Point -> Point+-- {-+-- RFC 8032+pdouble (Point (x1,y1,z1,_)) =+ let a' = FP.square q x1+ b' = FP.square q y1+ c' = FP.mulr q 2 $ FP.square q z1+ h' = FP.addr q a' b'+ e' = FP.subr q h' (FP.square q (FP.addr q x1 y1))+ g' = FP.subr q a' b'+ f' = FP.addr q c' g'+ x3 = FP.mulr q e' f'+ y3 = FP.mulr q g' h'+ z3 = FP.mulr q f' g'+ t3 = FP.mulr q e' h'+ in Point (x3,y3,z3,t3)+-- -}+{-+-- dbl-2008-hwcd+pdouble (Point (x1,y1,z1,_)) =+ let a' = FP.square q x1+ b' = FP.square q y1+ c' = FP.mulr q 2 $ FP.square q z1+ d' = FP.neg q a'+ e' = FP.subr q (FP.subr q (FP.square q (FP.addr q x1 y1)) a') b'+ g' = FP.addr q d' b'+ f' = FP.subr q g' c'+ h' = FP.subr q d' b'+ x3 = FP.mulr q e' f'+ y3 = FP.mulr q g' h'+ z3 = FP.mulr q f' g'+ t3 = FP.mulr q e' h'+ in Point (x3,y3,z3,t3)+-- -}++-- | scalar multiplication, branchfree in k, pattern-matched branch on j (static known length of k)+pmul :: Point -> FP.FPrime -> Point+pmul (Point (x,y,z,_)) k' =+ let ex erg j+ | j < 0 = erg+ | otherwise = let s = FP.condBit k' j+ realpattern = FP.mul alleeins s+ invpattern = FP.mul alleeins (FP.sub eins s)+ x' = x B..&. realpattern+ y' = FP.add (y B..&. realpattern) (eins B..&. invpattern)+ z' = FP.add (z B..&. realpattern) (eins B..&. invpattern)+ t' = FP.mulr q x' y'+ in ex (padd (pdouble erg) (Point (x', y', z',t'))) (j - 1)+ -- length k should be at most 256 bits, since mod q we have 0xyz.. so at max 255 steps from 254 to 0 included+ in ex inf 254++-- | check if Point is on the curve, prevent some attacks+ison :: Point -> Bool+ison (Point (x,y,z,_)) = FP.mulr q (FP.mulr q z z) (FP.addr q (FP.neg q (FP.mulr q x x)) (FP.mulr q y y)) == FP.addr q (FP.pow q z 4) (FP.mulr q d $ FP.mulr q (FP.mulr q x x) (FP.mulr q y y))++-- | make scalar format Point from projective coordinates+scale :: Point -> Point+scale (Point (xz,yz,z,_)) = let zInv = FP.inv q z+ x = FP.mulr q xz zInv+ y = FP.mulr q yz zInv+ in Point (x,y,1,FP.mulr q x y)++-- | convert a point on the curve to a ByteString+pointtobs :: Point -> BS.ByteString+pointtobs p = let Point (x,y,_,_) = scale p+ -- LSB of x is sign bit, put to MSB of y (which was zero)+ yf = FP.add y (FP.shift (x B..&. eins) (b - 1))+ in putFPrime yf++-- | convert a ByteString to a point on the curve+bstopoint :: BS.ByteString -> Either String Point+bstopoint bs = do+ let y = getFPrime32 bs+ case y of+ Left _ -> Left "Could not decode Point"+ Right (y'::FP.FPrime) -> let yf = y' B..&. (alleeins - (2^(b-1)))+ xf = xrecover yf (FP.condBit y' (b-1))+ pt = Point (xf,yf, FP.fromInteger b 1, FP.mulr q xf yf)+ in if ison pt then Right pt else Left "Point not on curve"++-- | clamping of a string of bytes to make it suitable for usage on the (clamped) Edwards curve in Ed25519, reduces cofactor+-- [ b Bits ] 001..1000 010..0+-- BigEndian 01x..x000 ==> ((getFPrime N) .&. (2^254-1-(2^0+2^1+2^2)) .|. (2^254))+-- .&. 28948022309329048855892746252171976963317496166410141009864396001978282409976 .|. 28948022309329048855892746252171976963317496166410141009864396001978282409984+clamp :: BS.ByteString -> Either String FP.FPrime+clamp bs = let num' = getFPrime32 bs+ in case num' of+ Right num -> Right ((FP.toInteger num B..&. 28948022309329048855892746252171976963317496166410141009864396001978282409976) B..|. 28948022309329048855892746252171976963317496166410141009864396001978282409984)+ Left e -> Left e++-- | convert an 8 Byte little endian ByteString to either an error String (if too short) or a big endian FPrime+convertLE8ByteTo64BE :: BS.ByteString -> Either String FP.FPrime+convertLE8ByteTo64BE bs | BS.length bs < 8 = Left "ByteString does not contain at least 32 Bytes"+ | otherwise = + let lowest = bs `BS.index` 0+ lower = bs `BS.index` 1+ low = bs `BS.index` 2+ midlow = bs `BS.index` 3+ midhigh = bs `BS.index` 4+ high = bs `BS.index` 5+ higher = bs `BS.index` 6+ highest = bs `BS.index` 7+ in Right (P.fromInteger $ P.toInteger lowest + B..|. B.shift (P.toInteger lower) 8+ B..|. B.shift (P.toInteger low) 16+ B..|. B.shift (P.toInteger midlow) 24+ B..|. B.shift (P.toInteger midhigh) 32+ B..|. B.shift (P.toInteger high) 40+ B..|. B.shift (P.toInteger higher) 48+ B..|. B.shift (P.toInteger highest) 56+ )++-- | convert a big endian FPrime to an 8 Byte little endian ByteString+convert64BEtoLE8Byte :: FP.FPrime -> BS.ByteString+convert64BEtoLE8Byte z = let lowest = (P.fromInteger $ z `mod` (2^( 8::Integer))) ::W.Word8+ lower = (P.fromInteger $ B.shift (z `mod` (2^(16::Integer))) ( -8))::W.Word8+ low = (P.fromInteger $ B.shift (z `mod` (2^(24::Integer))) (-16))::W.Word8+ midlow = (P.fromInteger $ B.shift (z `mod` (2^(32::Integer))) (-24))::W.Word8+ midhigh = (P.fromInteger $ B.shift (z `mod` (2^(40::Integer))) (-32))::W.Word8+ high = (P.fromInteger $ B.shift (z `mod` (2^(48::Integer))) (-40))::W.Word8+ higher = (P.fromInteger $ B.shift (z `mod` (2^(56::Integer))) (-48))::W.Word8+ highest = (P.fromInteger $ B.shift z (-56))::W.Word8+ in BS.pack [lowest,lower,low,midlow,midhigh,high,higher,highest]++-- | converts 32 little endian bytes into one FPrime+getFPrime32 :: BS.ByteString -> Either String FP.FPrime+getFPrime32 bs | BS.length bs < 32 = Left "ByteString does not contain at least 32 Bytes"+ | otherwise = do+ lowest <- convertLE8ByteTo64BE bs+ lower <- convertLE8ByteTo64BE $ BS.drop 8 bs+ higher <- convertLE8ByteTo64BE $ BS.drop 16 bs+ highest <- convertLE8ByteTo64BE $ BS.drop 24 bs+ Right ( P.toInteger lowest+ B..|. B.shift (P.toInteger lower) 64+ B..|. B.shift (P.toInteger higher) 128+ B..|. B.shift (P.toInteger highest) 192+ )++-- | converts 64 little endian bytes into one FPrime+getFPrime64 :: BS.ByteString -> Either String FP.FPrime+getFPrime64 bs | BS.length bs < 64 = Left "ByteString does not contain at least 64 Bytes"+ | otherwise = do+ low <- getFPrime32 bs+ high <- getFPrime32 $ BS.drop 32 bs+ Right (P.toInteger low B..|. B.shift (P.toInteger high) 256)++-- | converts one FPrime into exactly 32 little endian bytes+putFPrime :: FP.FPrime -> BS.ByteString+putFPrime num = let arg = FP.toInteger num+ lowest = P.fromInteger $ arg `mod` (2^(64::Integer))+ lower = P.fromInteger $ B.shift (arg `mod` (2^(128::Integer))) (-64)+ higher = P.fromInteger $ B.shift (arg `mod` (2^(192::Integer))) (-128)+ highest = P.fromInteger $ B.shift arg (-192)+ in convert64BEtoLE8Byte (P.fromInteger lowest)+ `BS.append` convert64BEtoLE8Byte (P.fromInteger lower)+ `BS.append` convert64BEtoLE8Byte (P.fromInteger higher)+ `BS.append` convert64BEtoLE8Byte (P.fromInteger highest)
+ src/Crypto/ECC/Ed25519/Sign.hs view
@@ -0,0 +1,108 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Ed25519.Sign+-- Copyright : (c) Marcel Fourné 20[14..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : alpha+-- Portability : Bad+--+-- Short-time plan: custom field arithmetic+-- TODO: optimal const time inversion in 25519, see eccss-20130911b.pdf+-- TODO: convert code to portable implementation and get rid of Integer+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Trustworthy, ScopedTypeVariables, PackageImports, NoImplicitPrelude #-}++module Crypto.ECC.Ed25519.Sign ( genkeys+ , genkeysSimple+ , publickey+ , dsign+ , sign+ , dverify+ , verify+ , Message+ , PubKey+ , SecKey -- only type export, not constructors+ , Signature+ , SignedMessage+ , SigOK(..)+ , VerifyResult+ )+where++import safe Crypto.ECC.Ed25519.Internal.Ed25519++import safe Prelude ((==),show,($),(<),IO,return,pure,Either(Left,Right),String,(&&))+import safe qualified Crypto.Fi as FP+import safe qualified Data.ByteString as BS+import qualified "crypto-api" Crypto.Random as CR++-- | generate a new key pair (secret and derived public key) using some external entropy+-- | This may be insecure, depending on your environment, so it's better to use the genkeys function and supply a random number generator which is secure for your usage case!+genkeysSimple :: IO (Either String (SecKey,PubKey))+genkeysSimple = do+ (g :: CR.SystemRandom) <- CR.newGenIO+ return $ genkeys g++-- | generate a new key pair (secret and derived public key) using the supplied randomness-generator+genkeys :: (CR.CryptoRandomGen g) => g -> Either String (SecKey,PubKey)+genkeys g = case CR.genBytes 32 g of+ Left e -> Left (show e)+ Right (sk',_) -> let sk = SecKeyBytes sk'+ derived = publickey sk+ in case derived of+ Left e -> Left e+ Right pk -> Right (sk,pk)++-- | derive public key from secret key+publickey :: SecKey -> Either String PubKey+publickey (SecKeyBytes sk) = let mysk = BS.take 32 sk -- ensure sk is b bit+ secret = clamp $ BS.take 32 $ h mysk+ in case secret of+ Left e -> Left e+ Right sec -> let aB = pmul bPoint sec+ in if ison aB+ then Right (pointtobs aB)+ else Left "public key is not on curve"++-- | sign with secret key the message, resulting in message appended to the signature+sign :: SecKey -> Message -> Either String SignedMessage+sign sk m = case dsign sk m of+ Left e -> Left e+ Right sig -> Right (BS.append sig m)++-- | wrapper around dverify, in case we work with a signed message, i.e. the signature with appended message+verify :: PubKey -> SignedMessage -> VerifyResult+verify a_ sigm = let sig = BS.take 64 sigm+ m = BS.drop 64 sigm+ in dverify a_ sig m++-- | sign the message m with secret key sk, resulting in a detached signature+dsign :: SecKey -> Message -> Either String Signature+dsign (SecKeyBytes sk) m = do+ let mysk = BS.take 32 sk+ hsk = h mysk+ ahsk = BS.take 32 hsk+ rhsk = BS.drop 32 hsk+ r <- getFPrime64 $ h $ rhsk `BS.append ` m+ let rB_ = pointtobs $ pmul bPoint (FP.redc l r)+ a' <- clamp ahsk+ let aB_ = pointtobs $ pmul bPoint a'+ t' <- getFPrime64 (h $ rB_ `BS.append` aB_ `BS.append` ph m)+ let s = FP.addr l r (FP.mulr l t' a')+ let s_ = putFPrime s+ pure $ BS.append rB_ s_++-- | in: public key, message and signature, out: is the signature valid for public key and message?+dverify :: PubKey -> Signature -> Message -> VerifyResult+dverify a_ sig m = do+ let r_ = BS.take 32 sig+ r <- bstopoint r_+ a' <- bstopoint a_+ s' <- getFPrime32 $ BS.drop 32 sig+ t <- getFPrime64 $ h $ r_ `BS.append` a_ `BS.append` m+ if (FP.toInteger s' < FP.toInteger l) && (scale $ pmul bPoint (FP.redc l s')) == (scale $ padd r $ pmul a' (FP.redc l t))+ then Right SigOK+ else Left "bad Signature"
− src/Crypto/ECC/NIST/Base.hs
@@ -1,272 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Crypto.ECC.NIST.Base--- Copyright : (c) Marcel Fourné 20[09..14]--- License : BSD3--- Maintainer : Marcel Fourné (haskell@marcelfourne.de)--- Stability : beta--- Portability : Good------ ECC Base algorithms & point formats for NIST Curves as specified in NISTReCur.pdf[http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf]--- Re Timing-Attacks: The field backends differ in timing-attack resistance. Due to the nature of NIST-curves, there are pitfalls in this module.--- --------------------------------------------------------------------------------{-# OPTIONS_GHC -O2 -feager-blackholing #-}-{-# LANGUAGE GADTs, FlexibleInstances, DeriveDataTypeable , BangPatterns #-}--module Crypto.ECC.NIST.Base ( FP.FPrime- , F2.F2- , EC(..)- , ECPF(..)- , affine- , export- , padd- , pdouble- , pmul- , ison- )- where--import Prelude (Eq,Show,(==),(&&),Integer,Int,show,Bool(False,True),(++),($),fail,undefined,(+),(-),otherwise,(<),div,not,(>),(<=),(>=),maxBound,rem,quot,quotRem,error,mod,(^))-import qualified Prelude as P (fromInteger,toInteger)--- import qualified Data.Bits as B (shift)-import Data.Typeable(Typeable)-import Crypto.Common-import qualified Crypto.Fi as FP--- import Crypto.FPrime-import qualified Crypto.F2 as F2---- | all Elliptic Curves, the parameters being the BitLength L, A, B and P-data EC a where- -- the Integer Curves, having the form y^2*z=x^3-3*x*z^2+B*z^3 mod P (projective with a = -3); relevant for "ison"- ECi :: Int -- the effective bitlength- -> FP.FPrime -- b- -> FP.FPrime -- p- -> FP.FPrime -- r- -> EC FP.FPrime -- the resulting curve- -- the Curves on F2, having the form y^2*z+x*y*z=x^3+a*x^2*z+b*z^3 mod P (projective); relevant for "ison"- ECb :: Int -- the effective bitlength- -> Int -- a, may be 0 or 1- -> F2.F2 -- b, may be 1 or something larger- -> F2.F2 -- p- -> FP.FPrime -- r- -> EC F2.F2 -- the resulting curve- deriving(Typeable)-instance Eq (EC a) where- (ECi l b p r) == (ECi l' b' p' r') = l==l' && FP.eq b b' && FP.eq p p' && FP.eq r r'- (ECb l a b p r) == (ECb l' a' b' p' r') = l==l' && a==a' && F2.eq b b' && F2.eq p p' && FP.eq r r'- _ == _ = False-instance Show (EC a) where- show (ECi l b p r) = "Curve with length" ++ show l ++", y^2=x^3-3*x+" ++ show b ++ " mod " ++ show p ++ " and group order " ++ show r ++ "."- show (ECb l a b p r) = "Curve with length" ++ show l ++", y^2=x^3+" ++ show a ++ "*x+" ++ show (F2.toInteger b) ++ " mod " ++ show (F2.toInteger p) ++ " and group order " ++ show r ++ "."---- every point has a curve on which it is valid (has to be tested manually), plus possibly some coordinates--- parametrised by the kind of numbers one which it may be computed--- point formats may be translated through functions--- | data of Elliptic Curve Points-data ECPF a where - -- Elliptic Curve Point Projective coordinates, three parameters x, y and z, like affine (x/z,y/z)- ECPp :: FP.FPrime -- x- -> FP.FPrime -- y- -> FP.FPrime -- z- -> ECPF FP.FPrime -- the point- -- Elliptic Curve Point Projective coordinates in F2, three parameters x, y and z, like affine (x/z,y/z)- ECPpF2 :: F2.F2 -- x- -> F2.F2 -- y- -> F2.F2 -- z- -> ECPF F2.F2 -- the point- deriving(Typeable)-instance Eq (ECPF a) where- (ECPp x y z) == (ECPp x' y' z') = FP.eq x x' && FP.eq y y' && FP.eq z z'- (ECPpF2 x y z) == (ECPpF2 x' y' z') = F2.eq x x' && F2.eq y y' && F2.eq z z'- _ == _ = False-instance Show (ECPF a) where- show (ECPp x y z) = "x: " ++ show x ++ " y: " ++ show y ++ " z: " ++ show z- show (ECPpF2 x y z) = "x: " ++ show (F2.toInteger x) ++ " y: " ++ show (F2.toInteger y) ++ " z: " ++ show (F2.toInteger z)---- internal function, codifies point at infinity-isinf :: Int -> ECPF a -> Bool-isinf l (ECPp x y z) = FP.eq x (FP.fromInteger l 0) && FP.eq y (FP.fromInteger l 1) && FP.eq z (FP.fromInteger l 0)-isinf l (ECPpF2 x y z) = F2.eq x (F2.F2 l (zero l)) && F2.eq y (F2.F2 l (one l)) && F2.eq z (F2.F2 l (zero l))---- | translate point in internal format to a pair of Integers in affine x and y coordinate--- | this is intended as interface to other libraries-export :: EC a -> ECPF a -> (Integer,Integer)-export c@ECi{} pt@ECPp{} = let (x,y) = affine c pt- in (FP.toInteger x, FP.toInteger y)-export c@ECb{} pt@ECPpF2{} = let (x,y) = affine c pt- in (F2.toInteger x, F2.toInteger y) -export _ _ = error "export parameters of different type"---- | generic getter, returning the affine x and y-value-affine :: EC a -> ECPF a -> (a,a)-affine (ECi l _ p _) a@(ECPp x y z)- | isinf l a = error "converting Point at Infinity"- | FP.eq z $ FP.fromInteger l 0 = (FP.fromInteger l 0,FP.fromInteger l 0)- | FP.eq z $ FP.fromInteger l 1 = (x,y)- | otherwise = let z' = FP.inv p z- in (FP.mulr p x z', FP.mulr p y z')-affine (ECb l _ _ p _) a@(ECPpF2 x y z)- | isinf l a = error "converting Point at Infinity"- | F2.eq z $ F2.F2 l (zero l) = (F2.fromInteger l 0, F2.fromInteger l 0)- | F2.eq z $ F2.F2 l (one l) = (x,y)- | otherwise = let z' = F2.inv p z- in (F2.mulr p x z', F2.mulr p y z')-affine _ _ = error "affine parameters of different type"-{-# INLINABLE affine #-}---- | add an elliptic point onto itself, base for padd a a-pdouble :: EC a -> ECPF a -> ECPF a-pdouble (ECi l _ p _) p1@(ECPp x1 y1 z1) =- if isinf l p1- then p1- else -- old: let a = ((-3)*z1^(2::Int)+3*x1^(2::Int)) `mod` p- let a = FP.mulr p (FP.fromInteger l 3) (FP.mulr p (FP.subr p x1 z1) (FP.addr p x1 z1)) -- since alpha == -3 on NIST-curves- b = FP.mulr p y1 z1- c = FP.mulr p x1 $ FP.mulr p y1 b- d = FP.subr p (FP.pow p a (2::Int)) (FP.mulr p (FP.fromInteger l 8) c)- x3 = FP.mulr p (FP.fromInteger l 2) $ FP.mulr p b d- y3 = FP.subr p (FP.mulr p a (FP.subr p (FP.mulr p (FP.fromInteger l 4) c) d)) (FP.mulr p (FP.mulr p (FP.fromInteger l 8) (FP.pow p y1 (2::Int))) (FP.pow p b (2::Int)))- z3 = FP.mulr p (FP.fromInteger l 8) (FP.pow p b (3::Int))- in ECPp x3 y3 z3-pdouble (ECb l alpha _ p _) p1@(ECPpF2 x1 y1 z1) =- if isinf l p1- then p1- else let a = F2.pow p x1 (2::Int)- b = F2.addr p a (F2.mulr p y1 z1)- c = F2.mulr p x1 z1- d = F2.pow p c (2::Int)- e = F2.addr p (F2.addr p (F2.pow p b (2::Int)) (F2.mulr p b c)) (if alpha==1 then d else F2.F2 l (zero l))- x3 = F2.mulr p c e- y3 = F2.addr p (F2.mulr p (F2.addr p b c) e) (F2.mulr p (F2.pow p a (2::Int)) c)- z3 = F2.mulr p c d- in ECPpF2 x3 y3 z3-pdouble _ _ = error "pdouble parameters of different type"-{-# INLINABLE pdouble #-}---- | add 2 elliptic points-padd :: EC a -> ECPF a -> ECPF a -> ECPF a-padd curve@(ECi l _ p _) p1@(ECPp x1 y1 z1) p2@(ECPp x2 y2 z2)- | FP.eq x1 x2 && FP.eq y1 (FP.neg p y2) && FP.eq z1 z2 = ECPp (FP.fromInteger l 0) (FP.fromInteger l 1) (FP.fromInteger l 0) -- Point at Infinity- | isinf l p1 = p2- | isinf l p2 = p1- | p1==p2 = pdouble curve p1- | otherwise = - let a = FP.subr p (FP.mulr p y2 z1) (FP.mulr p y1 z2)- b = FP.subr p (FP.mulr p x2 z1) (FP.mulr p x1 z2)- c = FP.subr p (FP.subr p (FP.mulr p (FP.pow p a (2::Int)) $ FP.mulr p z1 z2) (FP.pow p b (3::Int))) (FP.mulr p (FP.fromInteger l 2) $ FP.mulr p (FP.pow p b (2::Int)) $ FP.mulr p x1 z2)- x3 = FP.mulr p b c- y3 = FP.subr p (FP.mulr p a (FP.subr p (FP.mulr p (FP.pow p b (2::Int)) $ FP.mulr p x1 z2) c)) (FP.mulr p (FP.pow p b (3::Int)) $ FP.mulr p y1 z2)- z3 = FP.mulr p (FP.pow p b (3::Int)) $ FP.mulr p z1 z2- in ECPp x3 y3 z3-padd curve@(ECb l alpha _ p _) p1@(ECPpF2 x1 y1 z1) p2@(ECPpF2 x2 y2 z2)- | F2.eq x1 x2 && F2.eq y1 (F2.addr p x2 y2) && F2.eq z1 z2 = ECPpF2 (F2.F2 l (zero l)) (F2.F2 l (one l)) (F2.F2 l (zero l)) -- Point at Infinity- | isinf l p1 = p2- | isinf l p2 = p1- | p1==p2 = pdouble curve p1- | otherwise = - let a = F2.addr p (F2.mulr p y1 z2) (F2.mulr p z1 y2)- b = F2.addr p (F2.mulr p x1 z2) (F2.mulr p z1 x2)- c = F2.pow p b (2::Int)- d = F2.mulr p z1 z2- e = F2.addr p- (F2.mulr p- (F2.addr p- (F2.addr p- (F2.pow p a (2::Int))- (F2.mulr p a b)- )- (F2.mulr p (if alpha==1 then c else F2.F2 l (zero l)) c)- )- d- )- (F2.mulr p b c)- x3 = F2.mulr p b e- y3 = F2.addr p- (F2.mulr p- (F2.mulr p- c- (F2.addr p- (F2.mulr p a x1)- (F2.mulr p y1 b))- )- z2- )- (F2.mulr p (F2.addr p a b) e)- z3 = F2.mulr p (F2.pow p b (3::Int)) d- in ECPpF2 x3 y3 z3-padd _ _ _ = error "padd parameters of different type"-{-# INLINABLE padd #-}---- | "generic" verify, if generic ECP is on EC via getxA and getyA-ison :: EC a -> ECPF a -> Bool-ison (ECi l beta p _) a@(ECPp x y z)- | isinf l a = True- | otherwise =- FP.eq- (FP.mulr p (FP.pow p y (2::Int)) z)- (FP.addr p (FP.pow p x (3::Int)) (FP.addr p (FP.mulr p (FP.mulr p (FP.neg p (FP.fromInteger l 3)) x) (FP.pow p z (2::Int))) (FP.mulr p beta (FP.pow p z (3::Int)))))-ison (ECb l alpha beta p _) a@(ECPpF2 x y z)- | isinf l a = True- | otherwise =- F2.eq- (F2.addr p- (F2.mulr p (F2.pow p y (2::Int)) z)- (F2.mulr p (F2.mulr p x y) z)- )- (F2.addr p- (F2.addr p- (F2.pow p x (3::Int))- (if alpha==1 then F2.mulr p (F2.pow p x (2::Int)) z else F2.F2 l (zero l))- )- (F2.mulr p beta (F2.pow p z (3::Int)))- )-ison _ _ = error "ison parameters of different type"-{-# INLINABLE ison #-}---- | Point Multiplication. The implementation is a montgomery ladder, which should be timing-attack-resistant (except for caches...)-pmul :: EC a -> ECPF a -> FP.FPrime -> ECPF a--- {--pmul curve@(ECi l _ p _) b@ECPp{} k' =- let k = FP.redc (FP.subr p p (FP.fromInteger l 1)) k'- ex !p1 !p2 !i- | i < 0 = p1- | not (FP.testBit k i) = ex (pdouble curve p1) (padd curve p1 p2) (i - 1)- | otherwise = ex (padd curve p1 p2) (pdouble curve p2) (i - 1)- in ex b (pdouble curve b) (log2len k - 2)-pmul curve@(ECb l _ _ p _) b@ECPpF2{} k' =- let p' = (FP.fromInteger l $ F2.toInteger p)- k = FP.redc (FP.subr p' p' (FP.fromInteger l 1)) k'- ex !p1 !p2 !i- | i < 0 = p1- | not (FP.testBit k i) = ex (pdouble curve p1) (padd curve p1 p2) (i - 1)- | otherwise = ex (padd curve p1 p2) (pdouble curve p2) (i - 1)- in ex b (pdouble curve b) (log2len k - 2)--- -}- {---- these rely on point addition/doubling to be branching free! i.e. DO NOT USE FOR STANDARD NIST-CURVES! (bc. simpler timing attack w/o FLUSH+RELOAD)-pmul curve@(ECi l _ p _) b@ECPp{} k'- | k' == 0 = ECPp (FP.fromInteger l 0) (FP.fromInteger l 1) (FP.fromInteger l 0)- | k' == 1 = b- | otherwise =- let k = FP.redc (FP.subr p p (FP.fromInteger l 1)) k'- ex pt i- | i < 0 = pt- | otherwise = let cond = B.shift k (-i) `mod` 2- in ex (padd curve (pmul curve b cond) (pdouble curve pt)) (i - 1) -- cond == 1 -> b, cond == 0 -> inf (add neutral)- in ex b (log2len k - 2) -- begin one after highest bit (always set for i > 0), loglen returns highest bit position +1-pmul curve@(ECb l _ _ p _) b@ECPpF2{} k'- | k' == 0 = ECPpF2 (F2.fromInteger l 0) (F2.fromInteger l 1) (F2.fromInteger l 0)- | k' == 1 = b- | otherwise =- let p' = (FP.fromInteger l $ F2.toInteger p)- k = FP.redc (FP.subr p' p' (FP.fromInteger l 1)) k'- ex pt i- | i < 0 = pt- | otherwise = let cond = B.shift k (-i) `mod` 2- in ex (padd curve (pmul curve pt cond) (pdouble curve pt)) (i - 1)- in ex b (log2len k - 2)--- -}-pmul _ _ _ = error "pmul parameters of different type"-{-# INLINABLE pmul #-}
− src/Crypto/ECC/NIST/ECDH.hs
@@ -1,30 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Crypto.ECC.NIST.ECDH--- Copyright : (c) Marcel Fourné 20[09..14]--- License : BSD3--- Maintainer : Marcel Fourné (haskell@marcelfourne.de)--- Stability : experimental--- Portability : Good------ basic ECDH functions using hecc-----------------------------------------------------------------------------------{-# OPTIONS_GHC -O2 -feager-blackholing #-}--module Crypto.ECC.NIST.ECDH- where--import Crypto.ECC.NIST.Base--- import Crypto.ECC.NIST.StandardCurves---- private key dA of this side and public key qB of the communication partner, returning the simple x coordinate as result--- to be executed on both sides with fitting parameters...--- d = pickOne [1..N-1]--- q = pmul G d--- | basic ecdh for testing-basicecdh :: EC Integer -> Integer -> ECPF Integer -> Integer-basicecdh c dA qB = if ison c qB then let (x,_) = affine c $ pmul c qB dA- in x- else error "point not on curve"
− src/Crypto/ECC/NIST/StandardCurves.hs
@@ -1,121 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Crypto.ECC.NIST.StandardCurves--- Copyright : (c) Marcel Fourné 20[09..14]--- License : BSD3--- Maintainer : Marcel Fourné (haskell@marcelfourne.de)--- Stability : experimental--- Portability : Good--- --- ECC NIST Standard Curves, taken from NISTReCur.pdf[http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf]--- NB: The rigidity of the curve parameters may be manipulatable, for more--- information see http://safecurves.cr.yp.to/rigid.html--- Therein mentioned are only the NIST Prime Curves, because...--- NB F2: Read up on solving the Discrete Logarithm Problem in fields of small characteristic (i.e. here: Binary Curves)--- and then decide if the results are relevant to you.--- Recommendation: If your need NIST Curves and you do not know which one, use the Prime Curves.-----------------------------------------------------------------------------------{-# OPTIONS_GHC -O2 -feager-blackholing #-}-{-# LANGUAGE DeriveDataTypeable #-}--module Crypto.ECC.NIST.StandardCurves- where--import Prelude(Int,Integer,fromInteger)-import Crypto.ECC.NIST.Base (FPrime,F2)-import qualified Crypto.Fi as FP (fromInteger)-import qualified Crypto.F2 as F2 (fromInteger)-import Data.Typeable(Typeable)---- | Datatype for defined Standard Curves-data StandardCurve = - -- Curves on Prime Fields- StandardCurve {stdc_l::Int,stdc_p::FPrime,stdc_r::FPrime,stdc_b::FPrime,stdc_xp::FPrime,stdc_yp::FPrime}- -- Curves on Binary Fields (F2)- | StandardCurveF2 {stdcF_l::Int,stdcF_p::F2,stdcF_r::FPrime,stdcF_a::Int,stdcF_b::F2,stdcF_xp::F2,stdcF_yp::F2}- deriving (Typeable)---- Nist variety Curves over Prime Fields (large characteristic: p)---- | NIST Prime Curve P-192-p192:: StandardCurve-p192 = StandardCurve {- stdc_l = 192,- stdc_p = FP.fromInteger 192 6277101735386680763835789423207666416083908700390324961279,- stdc_r = FP.fromInteger 192 6277101735386680763835789423176059013767194773182842284081,- stdc_b = FP.fromInteger 192 2455155546008943817740293915197451784769108058161191238065,- stdc_xp = FP.fromInteger 192 602046282375688656758213480587526111916698976636884684818,- stdc_yp = FP.fromInteger 192 174050332293622031404857552280219410364023488927386650641- }---- | NIST Prime Curve P-224-p224:: StandardCurve-p224 = StandardCurve {- stdc_l = 224,- stdc_p = FP.fromInteger 224 26959946667150639794667015087019630673557916260026308143510066298881,- stdc_r = FP.fromInteger 224 26959946667150639794667015087019625940457807714424391721682722368061,- stdc_b = FP.fromInteger 224 18958286285566608000408668544493926415504680968679321075787234672564,- stdc_xp = FP.fromInteger 224 19277929113566293071110308034699488026831934219452440156649784352033,- stdc_yp = FP.fromInteger 224 19926808758034470970197974370888749184205991990603949537637343198772- }---- | NIST Prime Curve P-256-p256:: StandardCurve-p256 = StandardCurve {- stdc_l = 256,- stdc_p = FP.fromInteger 256 115792089210356248762697446949407573530086143415290314195533631308867097853951,- stdc_r = FP.fromInteger 256 115792089210356248762697446949407573529996955224135760342422259061068512044369,- stdc_b = FP.fromInteger 256 41058363725152142129326129780047268409114441015993725554835256314039467401291,- stdc_xp = FP.fromInteger 256 48439561293906451759052585252797914202762949526041747995844080717082404635286,- stdc_yp = FP.fromInteger 256 36134250956749795798585127919587881956611106672985015071877198253568414405109- }---- | NIST Prime Curve P-384-p384:: StandardCurve-p384 = StandardCurve {- stdc_l = 384,- stdc_p = FP.fromInteger 384 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319,- stdc_r = FP.fromInteger 384 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643,- stdc_b = FP.fromInteger 384 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575,- stdc_xp = FP.fromInteger 384 26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053975719786650872476732087,- stdc_yp = FP.fromInteger 384 8325710961489029985546751289520108179287853048861315594709205902480503199884419224438643760392947333078086511627871- }---- | NIST Prime Curve P-521-p521:: StandardCurve-p521 = StandardCurve {- stdc_l = 521,- stdc_p = FP.fromInteger 521 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151,- stdc_r = FP.fromInteger 521 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449,- stdc_b = FP.fromInteger 521 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984,- stdc_xp = FP.fromInteger 521 2661740802050217063228768716723360960729859168756973147706671368418802944996427808491545080627771902352094241225065558662157113545570916814161637315895999846,- stdc_yp = FP.fromInteger 521 3757180025770020463545507224491183603594455134769762486694567779615544477440556316691234405012945539562144444537289428522585666729196580810124344277578376784- }---- Nist variety Curves over Binary Fields (small characteristic: 2; please refer to the new results of solving the Discrete Logarithm Problem in fields of small characterstic, "Cryptopocalypse", Joux et al.)---- | NIST Binary Field Curve K-283-k283:: StandardCurve-k283 = StandardCurveF2 {- stdcF_l = 283,- stdcF_p = F2.fromInteger 283 15541351137805832567355695254588151253139254712417116170014499277911234281641667989665,- stdcF_r = FP.fromInteger 283 3885337784451458141838923813647037813284811733793061324295874997529815829704422603873,- stdcF_a = 0,- stdcF_b = F2.fromInteger 283 1,- stdcF_xp = F2.fromInteger 283 9737095673315832344313391497449387731784428326114441977662399932694280557468376967222,- stdcF_yp = F2.fromInteger 283 3497201781826516614681192670485202061196189998012192335594744939847890291586353668697- }---- | NIST Binary Field Curve B-283-b283:: StandardCurve-b283 = StandardCurveF2 {- stdcF_l = 283,- stdcF_p = F2.fromInteger 283 15541351137805832567355695254588151253139254712417116170014499277911234281641667989665,- stdcF_r = FP.fromInteger 283 7770675568902916283677847627294075626569625924376904889109196526770044277787378692871,- stdcF_a = 1,- stdcF_b = F2.fromInteger 283 4821813576056072374006997780399081180312270030300601270120450341205914644378616963829,- stdcF_xp = F2.fromInteger 283 11604587487407003699882500449177537465719784002620028212980871291231978603047872962643,- stdcF_yp = F2.fromInteger 283 6612720053854191978412609357563545875491153188501906352980899759345275170452624446196- }
+ src/Crypto/ECC/Weierstrass/ECDH.hs view
@@ -0,0 +1,33 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Weierstrass.ECDH+-- Copyright : (c) Marcel Fourné 20[09..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : experimental+-- Portability : Good+--+-- basic ECDH, for testing only+--+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe #-}++module Crypto.ECC.Weierstrass.ECDH ( basicecdh+ , EC+ , ECPF+ )+ where++import safe Crypto.ECC.Weierstrass.Internal++-- private key dA of this side and public key qB of the communication partner, returning the simple x coordinate as result+-- to be executed on both sides with fitting parameters...+-- d = pickOne [1..N-1]+-- q = pmul G d+-- | basic ecdh for testing+basicecdh :: EC Integer -> ECPF Integer -> Integer -> Integer+basicecdh c qB dA = if ison c qB then fst $ affine c $ pmul c qB dA+ else error "point not on curve"+
+ src/Crypto/ECC/Weierstrass/ECDSA.hs view
@@ -0,0 +1,60 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Weierstrass.ECDH+-- Copyright : (c) Marcel Fourné 20[09..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : experimental+-- Portability : Good+--+-- basic ECDSA, probably insecure if used improperly (really needs random k), for testing only+--+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe #-}++module Crypto.ECC.Weierstrass.ECDSA ( basicecdsa+ , basicecdsaVerify+ , ECPF+ )+ where++import safe Crypto.ECC.Weierstrass.Internal.Curvemath+import safe Crypto.ECC.Weierstrass.StandardCurves+import safe qualified Crypto.Fi as FP+import safe qualified Crypto.ECC.Ed25519.Internal as Ed+import safe qualified Data.Digest.Pure.SHA as H+import safe qualified Data.ByteString as BS+import safe qualified Data.ByteString.Lazy as BSL++-- | basic ecdsa for testing+basicecdsa :: BS.ByteString -> Integer -> Integer -> Either String (Integer,Integer)+basicecdsa bs dA k = + let curve = ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)+ bPoint = ECPp (stdc_xp p256) (stdc_yp p256) 1+ order = stdc_r p256+ Right z = Ed.getFPrime32 $ h bs+ (x1,_) = affine curve $ pmul curve bPoint k+ r = x1 `mod` order+ s = FP.mulr order (FP.inv order k) (FP.add z (FP.mulr order r dA))+ in if r /= 0 && s /= 0+ then Right (r,s)+ else Left "fail"++-- | basic ECDSA verification+basicecdsaVerify :: ECPF Integer -> (Integer,Integer) -> BS.ByteString -> Bool+basicecdsaVerify dB (r,s) m = let curve = ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)+ order = stdc_r p256+ bPoint = ECPp (stdc_xp p256) (stdc_yp p256) 1+ Right z = Ed.getFPrime32 $ h m+ w = FP.inv order s+ u1 = FP.mulr order z w+ u2 = FP.mulr order r w+ point = padd curve (pmul curve bPoint u1) (pmul curve dB u2)+ (x1,_) = affine curve point+ in not (isinf curve dB) && ison curve dB && isinf curve (pmul curve dB order) && r >= 0 && r < order && s >= 0 && s < order && not (isinf curve point) && x1 == r++-- | using SHA-256+h :: BS.ByteString -> BS.ByteString+h bs = BSL.toStrict $ H.bytestringDigest $ H.sha256 $ BSL.fromStrict bs
+ src/Crypto/ECC/Weierstrass/Internal.hs view
@@ -0,0 +1,31 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Weierstrass.Internal+-- Copyright : (c) Marcel Fourné 20[09..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : beta+-- Portability : Good+--+-- quasi-safe re-exports+-- +-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, NoImplicitPrelude #-}++module Crypto.ECC.Weierstrass.Internal ( FPrime+ , EC()+ , ECPF()+ , affine+ , export+ , padd+ , pdouble+ , pmul+ , ison+ , isinf+ )+where++import safe Crypto.ECC.Weierstrass.Internal.Curvemath+import safe Crypto.Fi
+ src/Crypto/ECC/Weierstrass/Internal/Curvemath.hs view
@@ -0,0 +1,368 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Weierstrass.Internal.Curvemath+-- Copyright : (c) Marcel Fourné 20[09..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : beta+-- Portability : Good+--+-- This module contain the internal functions. It's use should be limited to the ECDH and ECDSA modules, which export certain types without constructors, so the timing attack surface is only over the verified functions.+-- ECC Base algorithms & point formats for NIST Curves as specified in NISTReCur.pdf[http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf]+-- +-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, GADTs, DeriveDataTypeable, NoImplicitPrelude, StrictData #-}++module Crypto.ECC.Weierstrass.Internal.Curvemath where++import safe Prelude (Eq,Show,(==),(&&),Integer,Int,show,Bool,(++),(-),otherwise,(<),mod,(^),(+))+import safe qualified Data.Bits as B ((.&.))+import safe Data.Typeable(Typeable)+-- import safe Crypto.Common+import safe qualified Crypto.Fi as FP+-- import safe qualified Crypto.FPrime as FP+-- import safe qualified Crypto.F2 as F2++-- | all Elliptic Curves, the parameters being the BitLength L, A, B and P+data EC a where+ -- the Integer Curves, having the form y^2*z=x^3-3*x*z^2+B*z^3 mod P (projective with a = -3); relevant for "ison"+ ECi :: Int -- the effective bitlength+ -> FP.FPrime -- b+ -> FP.FPrime -- p+ -> FP.FPrime -- r+ -> EC FP.FPrime -- the resulting curve+ -- the Curves on F2, having the form y^2*z+x*y*z=x^3+a*x^2*z+b*z^3 mod P (projective); relevant for "ison"+{- ECb :: Int -- the effective bitlength+ -> Int -- a, may be 0 or 1+ -> F2.F2 -- b, may be 1 or something larger+ -> F2.F2 -- p+ -> FP.FPrime -- r+ -> EC F2.F2 -- the resulting curve-}+ deriving(Typeable)++instance Eq (EC a) where+ (ECi l b p r) == (ECi l' b' p' r') = l==l' && FP.eq b b' && FP.eq p p' && FP.eq r r'+-- (ECb l a b p r) == (ECb l' a' b' p' r') = l==l' && a==a' && F2.eq b b' && F2.eq p p' && FP.eq r r'++instance Show (EC a) where+ show (ECi l b p r) = "Curve with length" ++ show l ++", y^2=x^3-3*x+" ++ show b ++ " mod " ++ show p ++ " and group order " ++ show r ++ "."+-- show (ECb l a b p r) = "Curve with length" ++ show l ++", y^2=x^3+" ++ show a ++ "*x+" ++ show (F2.toInteger b) ++ " mod " ++ show (F2.toInteger p) ++ " and group order " ++ show r ++ "."++-- every point has a curve on which it is valid (has to be tested manually), plus possibly some coordinates+-- parametrised by the kind of numbers one which it may be computed+-- point formats may be translated through functions+-- | data of Elliptic Curve Points+data ECPF a where + -- Elliptic Curve Point Projective coordinates, three parameters x, y and z, like affine (x/z,y/z)+ ECPp :: FP.FPrime -- x+ -> FP.FPrime -- y+ -> FP.FPrime -- z+ -> ECPF FP.FPrime -- the point+ -- Elliptic Curve Point Projective coordinates in F2, three parameters x, y and z, like affine (x/z,y/z)+{- ECPpF2 :: F2.F2 -- x+ -> F2.F2 -- y+ -> F2.F2 -- z+ -> ECPF F2.F2 -- the point -}+ deriving(Typeable)+instance Eq (ECPF a) where+ (ECPp x y z) == (ECPp x' y' z') = FP.eq x x' && FP.eq y y' && FP.eq z z'+-- (ECPpF2 x y z) == (ECPpF2 x' y' z') = F2.eq x x' && F2.eq y y' && F2.eq z z'++instance Show (ECPF a) where+ show (ECPp x y z) = "x: " ++ show x ++ " y: " ++ show y ++ " z: " ++ show z+-- show (ECPpF2 x y z) = "x: " ++ show (F2.toInteger x) ++ " y: " ++ show (F2.toInteger y) ++ " z: " ++ show (F2.toInteger z)++-- | internal function, codifies point at infinity, is used in comparisons+isinf :: EC a -> ECPF a -> Bool+isinf (ECi l _ _ _) (ECPp x _ z) = FP.eq x (FP.fromInteger l 0) {-&& FP.eq y (FP.fromInteger l 1)-} && FP.eq z (FP.fromInteger l 0)+-- isinf l (ECPpF2 x y z) = F2.eq x (F2.F2 l (zero l)) {-&& F2.eq y (F2.F2 l (one l))-} && F2.eq z (F2.F2 l (zero l))++-- | translate point in internal format to a pair of Integers in affine x and y coordinate+-- | this is intended as interface to other libraries+export :: EC a -> ECPF a -> (Integer,Integer)+export c@ECi{} pt@ECPp{} = let (x,y) = affine c pt+ in (FP.toInteger x, FP.toInteger y)+{-export c@ECb{} pt@ECPpF2{} = let (x,y) = affine c pt+ in (F2.toInteger x, F2.toInteger y) -}++-- | generic getter, returning the affine x and y-value+affine :: EC a -> ECPF a -> (Integer,Integer)+affine (ECi _ _ p _) (ECPp x y z) = let z' = FP.inv p z+ in (FP.mulr p x z', FP.mulr p y z')+{-affine (ECb l _ _ p _) a@(ECPpF2 x y z)+ | isinf l a = error "converting Point at Infinity"+ | F2.eq z $ F2.F2 l (zero l) = (F2.fromInteger l 0, F2.fromInteger l 0)+ | F2.eq z $ F2.F2 l (one l) = (x,y)+ | otherwise = let z' = F2.inv p z+ in (F2.mulr p x z', F2.mulr p y z')-}+{-# INLINABLE affine #-}++-- | add an elliptic point onto itself, base for padd a a+pdouble :: EC a -> ECPF a -> ECPF a+pdouble (ECi _ b p _) (ECPp x y z) =+{-+ if isinf l p1+ then p1+ else -- old: let a = ((-3)*z^(2::Int)+3*x^(2::Int)) `mod` p+ let a = FP.mulr p (FP.fromInteger l 3) (FP.mulr p (FP.subr p x z) (FP.addr p x z)) -- since alpha == -3 on NIST-curves+ b = FP.mulr p y z+ c = FP.mulr p x $ FP.mulr p y b+ d = FP.subr p (FP.pow p a (2::Integer)) (FP.mulr p (FP.fromInteger l 8) c)+ x3 = FP.mulr p (FP.fromInteger l 2) $ FP.mulr p b d+ y3 = FP.subr p (FP.mulr p a (FP.subr p (FP.mulr p (FP.fromInteger l 4) c) d)) (FP.mulr p (FP.mulr p (FP.fromInteger l 8) (FP.pow p y (2::Integer))) (FP.pow p b (2::Integer)))+ z3 = FP.mulr p (FP.fromInteger l 8) (FP.pow p b (3::Integer))+ in ECPp x3 y3 z3+-- -}+-- {-+ -- 1060.pdf Alg 6.+ -- TODO: nisttv+ let t0_0 = FP.mulr p x x+ t1_0 = FP.mulr p y y+ t2_0 = FP.mulr p z z+ t3_0 = FP.mulr p x y+ t3_1 = FP.addr p t3_0 t3_0 -- 5.+ z3_0 = FP.mulr p x z+ z3_1 = FP.addr p z3_0 z3_0+ y3_0 = FP.mulr p b t2_0+ y3_1 = FP.subr p y3_0 z3_1+ x3_0 = FP.addr p y3_1 y3_1 -- 10.+ y3_2 = FP.addr p x3_0 y3_1+ x3_1 = FP.subr p t1_0 y3_2+ y3_3 = FP.addr p t1_0 y3_2+ y3_4 = FP.mulr p x3_1 y3_3+ x3_2 = FP.mulr p x3_1 t3_1 -- 15.+ t3_2 = FP.addr p t2_0 t2_0+ t2_1 = FP.addr p t2_0 t3_2+ z3_2 = FP.mulr p b z3_1+ z3_3 = FP.subr p z3_2 t2_1+ z3_4 = FP.subr p z3_3 t0_0 -- 20.+ t3_3 = FP.addr p z3_4 z3_4+ z3_5 = FP.addr p z3_4 t3_3+ t3_4 = FP.addr p t0_0 t0_0+ t0_1 = FP.addr p t3_4 t0_0+ t0_2 = FP.subr p t0_1 t2_1 -- 25.+ t0_3 = FP.mulr p t0_2 z3_5+ y3_5 = FP.addr p y3_4 t0_3+ t0_4 = FP.mulr p y z+ t0_5 = FP.addr p t0_4 t0_4+ z3_6 = FP.mulr p t0_5 z3_5 -- 30.+ x3_3 = FP.subr p x3_2 z3_6+ z3_7 = FP.mulr p t0_5 t1_0+ z3_8 = FP.addr p z3_7 z3_7+ z3_9 = FP.addr p z3_8 z3_8+ in ECPp x3_3 y3_5 z3_9+-- -}++{-pdouble (ECb l alpha _ p _) p1@(ECPpF2 x1 y1 z1) =+ if isinf l p1+ then p1+ else let a = F2.pow p x1 (2::Integer)+ b = F2.addr p a (F2.mulr p y1 z1)+ c = F2.mulr p x1 z1+ d = F2.pow p c (2::Integer)+ e = F2.addr p (F2.addr p (F2.pow p b (2::Integer)) (F2.mulr p b c)) (if alpha==1 then d else F2.F2 l (zero l))+ x3 = F2.mulr p c e+ y3 = F2.addr p (F2.mulr p (F2.addr p b c) e) (F2.mulr p (F2.pow p a (2::Integer)) c)+ z3 = F2.mulr p c d+ in ECPpF2 x3 y3 z3 -}+{-# INLINABLE pdouble #-}++-- | add 2 elliptic points+padd :: EC a -> ECPF a -> ECPF a -> ECPF a+padd (ECi _ b p _) (ECPp x1 y1 z1) (ECPp x2 y2 z2)+{-+ | FP.eq x1 x2 && FP.eq y1 (FP.neg p y2) && FP.eq z1 z2 = ECPp (FP.fromInteger l 0) (FP.fromInteger l 1) (FP.fromInteger l 0) -- Point at Infinity+ | isinf l p1 = p2+ | isinf l p2 = p1+ | p1==p2 = pdouble curve p1+ | otherwise = + let a = FP.subr p (FP.mulr p y2 z1) (FP.mulr p y1 z2)+ b = FP.subr p (FP.mulr p x2 z1) (FP.mulr p x1 z2)+ c = FP.subr p (FP.subr p (FP.mulr p (FP.pow p a (2::Integer)) $ FP.mulr p z1 z2) (FP.pow p b (3::Integer))) (FP.mulr p (FP.fromInteger l 2) $ FP.mulr p (FP.pow p b (2::Integer)) $ FP.mulr p x1 z2)+ x3 = FP.mulr p b c+ y3 = FP.subr p (FP.mulr p a (FP.subr p (FP.mulr p (FP.pow p b (2::Integer)) $ FP.mulr p x1 z2) c)) (FP.mulr p (FP.pow p b (3::Integer)) $ FP.mulr p y1 z2)+ z3 = FP.mulr p (FP.pow p b (3::Integer)) $ FP.mulr p z1 z2+ in ECPp x3 y3 y3+-- -}+-- {-+ -- 1060.pdf Alg 4.+ -- TODO: nisttv+ = let t0_0 = FP.mulr p x1 x2+ t1_0 = FP.mulr p y1 y2+ t2_0 = FP.mulr p z1 z2+ t3_0 = FP.addr p x1 y1+ t4_0 = FP.addr p x2 y2 -- 5.+ t3_1 = FP.mulr p t3_0 t4_0+ t4_1 = FP.addr p t0_0 t1_0+ t3_2 = FP.subr p t3_1 t4_1+ t4_2 = FP.addr p y1 z1+ x3_0 = FP.addr p y2 z2 -- 10.+ t4_3 = FP.mulr p t4_2 x3_0+ x3_1 = FP.addr p t1_0 t2_0+ t4_4 = FP.subr p t4_3 x3_1+ x3_2 = FP.addr p x1 z1+ y3_0 = FP.addr p x2 z2 -- 15.+ x3_3 = FP.mulr p x3_2 y3_0+ y3_1 = FP.addr p t0_0 t2_0+ y3_2 = FP.subr p x3_3 y3_1+ z3_0 = FP.mulr p b t2_0+ x3_4 = FP.subr p y3_2 z3_0 -- 20.+ z3_1 = FP.addr p x3_4 x3_4+ x3_5 = FP.addr p x3_4 z3_1+ z3_2 = FP.subr p t1_0 x3_5+ x3_6 = FP.addr p t1_0 x3_5+ y3_3 = FP.mulr p b y3_2 -- 25.+ t1_1 = FP.addr p t2_0 t2_0+ t2_1 = FP.addr p t1_1 t2_0+ y3_4 = FP.subr p y3_3 t2_1+ y3_5 = FP.subr p y3_4 t0_0+ t1_2 = FP.addr p y3_5 y3_5 -- 30.+ y3_6 = FP.addr p t1_2 y3_5+ t1_3 = FP.addr p t0_0 t0_0+ t0_1 = FP.addr p t1_3 t0_0+ t0_2 = FP.subr p t0_1 t2_1+ t1_4 = FP.mulr p t4_4 y3_6 -- 35.+ t2_2 = FP.mulr p t0_2 y3_6+ y3_7 = FP.mulr p x3_6 z3_2+ y3_8 = FP.addr p y3_7 t2_2+ x3_7 = FP.mulr p t3_2 x3_6+ x3_8 = FP.subr p x3_7 t1_4 -- 40.+ z3_3 = FP.mulr p t4_4 z3_2+ t1_5 = FP.mulr p t3_2 t0_2+ z3_4 = FP.addr p z3_3 t1_5+ in ECPp x3_8 y3_8 z3_4+-- -}+{-padd curve@(ECb l alpha _ p _) p1@(ECPpF2 x1 y1 z1) p2@(ECPpF2 x2 y2 z2)+ | F2.eq x1 x2 && F2.eq y1 (F2.addr p x2 y2) && F2.eq z1 z2 = ECPpF2 (F2.F2 l (zero l)) (F2.F2 l (one l)) (F2.F2 l (zero l)) -- Point at Infinity+ | isinf l p1 = p2+ | isinf l p2 = p1+ | p1==p2 = pdouble curve p1+ | otherwise = + let a = F2.addr p (F2.mulr p y1 z2) (F2.mulr p z1 y2)+ b = F2.addr p (F2.mulr p x1 z2) (F2.mulr p z1 x2)+ c = F2.pow p b (2::Integer)+ d = F2.mulr p z1 z2+ e = F2.addr p+ (F2.mulr p+ (F2.addr p+ (F2.addr p+ (F2.pow p a (2::Integer))+ (F2.mulr p a b)+ )+ (F2.mulr p (if alpha==1 then c else F2.F2 l (zero l)) c)+ )+ d+ )+ (F2.mulr p b c)+ x3 = F2.mulr p b e+ y3 = F2.addr p+ (F2.mulr p+ (F2.mulr p+ c+ (F2.addr p+ (F2.mulr p a x1)+ (F2.mulr p y1 b))+ )+ z2+ )+ (F2.mulr p (F2.addr p a b) e)+ z3 = F2.mulr p (F2.pow p b (3::Integer)) d+ in ECPpF2 x3 y3 z3+-}+{-# INLINABLE padd #-}++-- | "generic" verify, if generic ECP is on EC via getxA and getyA+ison :: EC a -> ECPF a -> Bool+ison (ECi l beta p _) (ECPp x y z) = FP.eq+ (FP.mulr p (FP.pow p y (2::Integer)) z)+ (FP.addr p (FP.pow p x (3::Integer)) (FP.addr p (FP.mulr p (FP.mulr p (FP.neg p (FP.fromInteger l 3)) x) (FP.pow p z (2::Integer))) (FP.mulr p beta (FP.pow p z (3::Integer)))))+{-ison (ECb l alpha beta p _) a@(ECPpF2 x y z)+ | isinf l a = True+ | otherwise =+ F2.eq+ (F2.addr p+ (F2.mulr p (F2.pow p y (2::Integer)) z)+ (F2.mulr p (F2.mulr p x y) z)+ )+ (F2.addr p+ (F2.addr p+ (F2.pow p x (3::Integer))+ (if alpha==1 then F2.mulr p (F2.pow p x (2::Integer)) z else F2.F2 l (zero l))+ )+ (F2.mulr p beta (F2.pow p z (3::Integer)))+ ) -}+{-# INLINABLE ison #-}++-- | Point Multiplication.+pmul :: EC a -> ECPF a -> FP.FPrime -> ECPF a+-- {-+pmul curve@(ECi l _ p _) (ECPp x y z) k =+ let alleeins = FP.fromInteger l (2^l-1)+ eins = FP.fromInteger l 1+ k' = k `mod` (p+1)+ ex erg j+ | j < 0 = erg+ | otherwise = let s = FP.condBit k' j+ realpattern = FP.mul alleeins s+ invpattern = FP.mul alleeins (FP.sub eins s)+ x' = x B..&. realpattern+ y' = FP.add (y B..&. realpattern) (eins B..&. invpattern)+ z' = (z B..&. realpattern)+ in ex (padd curve (pdouble curve erg) (ECPp x' y' z')) (j - 1)+ in ex (ECPp 0 1 0) (l - 1)+-- -}+{-+pmul curve@(ECi l _ p _) b@ECPp{} k' =+-- {- + let k = FP.redc (FP.subr p p (FP.fromInteger l 1)) k'+ ex p1 p2 i+ | i < 0 = p1+ | not (FP.testBit k i) = ex (pdouble curve p1) (padd curve p1 p2) (i - 1)+ | otherwise = ex (padd curve p1 p2) (pdouble curve p2) (i - 1)+ in ex b (pdouble curve b) (log2len k - 2)+-- -}+-- -}+{-+ -- basic double and add, for comparison, demo of attacks+ let k = FP.redc (FP.subr p p (FP.fromInteger l 1)) k'+ ex p2 i+ | i < 0 = b+ | not (FP.testBit k i) = ex (pdouble curve p2) (i - 1)+ | otherwise = ex (pdouble curve (padd curve b p2)) (i - 1)+ in ex (pdouble curve b) (log2len k - 2)+-- -}+{-pmul curve@(ECb l _ _ p _) b@ECPpF2{} k' =+ let p' = (FP.fromInteger l $ F2.toInteger p)+ k = FP.redc (FP.subr p' p' (FP.fromInteger l 1)) k'+ ex p1 p2 i+ | i < 0 = p1+ | not (FP.testBit k i) = ex (pdouble curve p1) (padd curve p1 p2) (i - 1)+ | otherwise = ex (padd curve p1 p2) (pdouble curve p2) (i - 1)+ in ex b (pdouble curve b) (log2len k - 2) -}+{-+-- these rely on point addition/doubling to be branching free!+pmul curve@(ECi l _ p _) b@ECPp{} k'+ | k' == 0 = ECPp (FP.fromInteger l 0) (FP.fromInteger l 1) (FP.fromInteger l 0)+ | k' == 1 = b+ | otherwise =+ let k = FP.redc (FP.subr p p (FP.fromInteger l 1)) k'+ ex pt i+ | i < 0 = pt+ | otherwise = let cond = B.shift k (-i) `mod` 2+ in ex (padd curve (pmul curve b cond) (pdouble curve pt)) (i - 1) -- cond == 1 -> b, cond == 0 -> inf (add neutral)+ in ex b (log2len k - 2) -- begin one after highest bit (always set for i > 0), loglen returns highest bit position +1+pmul curve@(ECb l _ _ p _) b@ECPpF2{} k'+ | k' == 0 = ECPpF2 (F2.fromInteger l 0) (F2.fromInteger l 1) (F2.fromInteger l 0)+ | k' == 1 = b+ | otherwise =+ let p' = (FP.fromInteger l $ F2.toInteger p)+ k = FP.redc (FP.subr p' p' (FP.fromInteger l 1)) k'+ ex pt i+ | i < 0 = pt+ | otherwise = let cond = B.shift k (-i) `mod` 2+ in ex (padd curve (pmul curve pt cond) (pdouble curve pt)) (i - 1)+ in ex b (log2len k - 2)+-- -}+{-# INLINABLE pmul #-}
+ src/Crypto/ECC/Weierstrass/StandardCurves.hs view
@@ -0,0 +1,123 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.ECC.Weierstrass.StandardCurves+-- Copyright : (c) Marcel Fourné 20[09..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : experimental+-- Portability : Good+-- +-- ECC NIST Standard Curves, taken from NISTReCur.pdf[http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf]+-- NB: The rigidity of the curve parameters may be manipulatable, for more+-- information see http://safecurves.cr.yp.to/rigid.html+-- Therein mentioned are only the NIST Prime Curves, because...+-- NB F2: Read up on solving the Discrete Logarithm Problem in fields of small characteristic (i.e. here: Binary Curves)+-- and then decide if the results are relevant to you.+-- Recommendation: If you need NIST Curves and you do not know which one, use the Prime Curves.+--+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, DeriveDataTypeable, NoImplicitPrelude #-}++module Crypto.ECC.Weierstrass.StandardCurves+ where++import safe Prelude(Int)+import safe Crypto.ECC.Weierstrass.Internal (FPrime)+-- import safe Crypto.ECC.Weierstrass.Internal (FPrime,F2)+import safe qualified Crypto.Fi as FP (fromInteger)+-- import safe qualified Crypto.F2 as F2 (fromInteger)+import safe Data.Typeable(Typeable)++-- | Datatype for defined Standard Curves+data StandardCurve = + -- Curves on Prime Fields+ StandardCurve {stdc_l::Int,stdc_p::FPrime,stdc_r::FPrime,stdc_b::FPrime,stdc_xp::FPrime,stdc_yp::FPrime}+ -- Curves on Binary Fields (F2)+-- | StandardCurveF2 {stdcF_l::Int,stdcF_p::F2,stdcF_r::FPrime,stdcF_a::Int,stdcF_b::F2,stdcF_xp::F2,stdcF_yp::F2}+ deriving (Typeable)++-- Nist variety Curves over Prime Fields (large characteristic: p)++-- | NIST Prime Curve P-192+p192:: StandardCurve+p192 = StandardCurve {+ stdc_l = 192,+ stdc_p = FP.fromInteger 192 6277101735386680763835789423207666416083908700390324961279,+ stdc_r = FP.fromInteger 192 6277101735386680763835789423176059013767194773182842284081,+ stdc_b = FP.fromInteger 192 2455155546008943817740293915197451784769108058161191238065,+ stdc_xp = FP.fromInteger 192 602046282375688656758213480587526111916698976636884684818,+ stdc_yp = FP.fromInteger 192 174050332293622031404857552280219410364023488927386650641+ }++-- | NIST Prime Curve P-224+p224:: StandardCurve+p224 = StandardCurve {+ stdc_l = 224,+ stdc_p = FP.fromInteger 224 26959946667150639794667015087019630673557916260026308143510066298881,+ stdc_r = FP.fromInteger 224 26959946667150639794667015087019625940457807714424391721682722368061,+ stdc_b = FP.fromInteger 224 18958286285566608000408668544493926415504680968679321075787234672564,+ stdc_xp = FP.fromInteger 224 19277929113566293071110308034699488026831934219452440156649784352033,+ stdc_yp = FP.fromInteger 224 19926808758034470970197974370888749184205991990603949537637343198772+ }++-- | NIST Prime Curve P-256+p256:: StandardCurve+p256 = StandardCurve {+ stdc_l = 256,+ stdc_p = FP.fromInteger 256 115792089210356248762697446949407573530086143415290314195533631308867097853951,+ stdc_r = FP.fromInteger 256 115792089210356248762697446949407573529996955224135760342422259061068512044369,+ stdc_b = FP.fromInteger 256 41058363725152142129326129780047268409114441015993725554835256314039467401291,+ stdc_xp = FP.fromInteger 256 48439561293906451759052585252797914202762949526041747995844080717082404635286,+ stdc_yp = FP.fromInteger 256 36134250956749795798585127919587881956611106672985015071877198253568414405109+ }++-- | NIST Prime Curve P-384+p384:: StandardCurve+p384 = StandardCurve {+ stdc_l = 384,+ stdc_p = FP.fromInteger 384 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319,+ stdc_r = FP.fromInteger 384 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643,+ stdc_b = FP.fromInteger 384 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575,+ stdc_xp = FP.fromInteger 384 26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053975719786650872476732087,+ stdc_yp = FP.fromInteger 384 8325710961489029985546751289520108179287853048861315594709205902480503199884419224438643760392947333078086511627871+ }++-- | NIST Prime Curve P-521+p521:: StandardCurve+p521 = StandardCurve {+ stdc_l = 521,+ stdc_p = FP.fromInteger 521 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151,+ stdc_r = FP.fromInteger 521 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449,+ stdc_b = FP.fromInteger 521 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984,+ stdc_xp = FP.fromInteger 521 2661740802050217063228768716723360960729859168756973147706671368418802944996427808491545080627771902352094241225065558662157113545570916814161637315895999846,+ stdc_yp = FP.fromInteger 521 3757180025770020463545507224491183603594455134769762486694567779615544477440556316691234405012945539562144444537289428522585666729196580810124344277578376784+ }++-- Nist variety Curves over Binary Fields (small characteristic: 2; please refer to the new results of solving the Discrete Logarithm Problem in fields of small characterstic, "Cryptopocalypse", Joux et al.)+{-+-- | NIST Binary Field Curve K-283+k283:: StandardCurve+k283 = StandardCurveF2 {+ stdcF_l = 283,+ stdcF_p = F2.fromInteger 283 15541351137805832567355695254588151253139254712417116170014499277911234281641667989665,+ stdcF_r = FP.fromInteger 283 3885337784451458141838923813647037813284811733793061324295874997529815829704422603873,+ stdcF_a = 0,+ stdcF_b = F2.fromInteger 283 1,+ stdcF_xp = F2.fromInteger 283 9737095673315832344313391497449387731784428326114441977662399932694280557468376967222,+ stdcF_yp = F2.fromInteger 283 3497201781826516614681192670485202061196189998012192335594744939847890291586353668697+ }++-- | NIST Binary Field Curve B-283+b283:: StandardCurve+b283 = StandardCurveF2 {+ stdcF_l = 283,+ stdcF_p = F2.fromInteger 283 15541351137805832567355695254588151253139254712417116170014499277911234281641667989665,+ stdcF_r = FP.fromInteger 283 7770675568902916283677847627294075626569625924376904889109196526770044277787378692871,+ stdcF_a = 1,+ stdcF_b = F2.fromInteger 283 4821813576056072374006997780399081180312270030300601270120450341205914644378616963829,+ stdcF_xp = F2.fromInteger 283 11604587487407003699882500449177537465719784002620028212980871291231978603047872962643,+ stdcF_yp = F2.fromInteger 283 6612720053854191978412609357563545875491153188501906352980899759345275170452624446196+ }+-}
src/Crypto/F2.hs view
@@ -14,7 +14,7 @@ ----------------------------------------------------------------------------- {-# OPTIONS_GHC -O2 -feager-blackholing #-}-{-# LANGUAGE DeriveDataTypeable, BangPatterns #-}+{-# LANGUAGE Safe, DeriveDataTypeable, BangPatterns, NoImplicitPrelude #-} module Crypto.F2 ( F2(..) , eq@@ -33,13 +33,13 @@ ) 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,(.),max,map,foldl,compare,Ordering(..))-import qualified Prelude as P (toInteger,fromInteger)-import qualified Data.Bits as B (Bits(..),testBit)-import Data.Typeable(Typeable)-import qualified Data.Vector.Unboxed as V-import qualified Data.Word as W (Word)-import Crypto.Common+import safe Prelude (Show,(==),(&&),Integer,Int,Bool(True),($),(+),(-),(*),(^),otherwise,(<),not,(>),(<=),(>=),rem,quot,quotRem,error,compare,Ordering(..))+import safe qualified Prelude as P (toInteger,fromInteger)+import safe qualified Data.Bits as B (Bits(..),testBit)+import safe Data.Typeable(Typeable)+-- import safe qualified Data.Vector.Unboxed as V+import safe qualified Data.Word as W (Word)+import safe Crypto.Common -- | F2 consist of an exact length of meaningful bits and a representation of those bits in a possibly larger Vector of Words -- | Note: The vectors use small to large indices, but the Data.Word endianness is of no concern as it is hidden by Data.Bits@@ -104,7 +104,7 @@ -- | fill highest bits over official length with 0s bleachupper :: Int -> F2 -> F2 bleachupper l (F2 _ v) = let (_,ix2) = findindex (l - 1)- in F2 l $ V.take (sizeinWords l - 1) v V.++ (V.singleton $ B.shift (B.shift (V.last v) (wordSize - (ix2 + 1))) (-(wordSize - (ix2 + 1))))+ in F2 l $ V.take (sizeinWords l - 1) v V.++ V.singleton (B.shift (B.shift (V.last v) (wordSize - (ix2 + 1))) (-(wordSize - (ix2 + 1)))) -- | polynomial reduction, simple scan -- TODO: idempotent? not right now -> ERROR!@@ -144,7 +144,7 @@ square a = mul a a -- | the power function on F2 for positive exponents, reducing early-pow :: (B.Bits a, Integral a) => F2 -> F2 -> a -> F2+pow :: F2 -> F2 -> Integer -> F2 pow !p !a !k | k <= 0 = error "non-positive exponent for the power function on F2" | otherwise = let binlog = log2len k
+ src/Crypto/FPrime.hs view
@@ -0,0 +1,181 @@+-----------------------------------------------------------------------------+-- |+-- Module : Crypto.FPrime+-- Copyright : (c) Marcel Fourné 20[14..]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+-- Stability : experimental+-- Portability : Good+--+-- Reimplementation of Bigint math for crypto use+-- Re Timing-Attacks: We depend on (==) being resistant for Integer.+-- +-----------------------------------------------------------------------------++{-# OPTIONS_GHC -O2 -feager-blackholing #-}+{-# LANGUAGE Safe, DeriveDataTypeable #-}++module Crypto.FPrime ( FPrime()+ , eq+ , add+ , addr+ , sub+ , subr+ , neg+ , negr+ , shift+ , mul+ , mulr+ , redc+ , square+ , pow+ , inv+ , testBit+ , fromInteger+ , toInteger+ )+ where++import safe Prelude (Eq,Show,(==),(&&),Integer,Int,show,Bool(False,True),(++),($),fail,undefined,(+),(-),(*),(^),abs,mod,Integral,otherwise,(<),div,not,String,flip,takeWhile,length,iterate,(>),(<=),(>=),maxBound,rem,quot,quotRem,error,even)+import safe qualified Prelude as P (fromInteger,toInteger)+import safe qualified Data.Bits as B (Bits(..),testBit)+import safe Data.Typeable(Typeable)+import safe qualified Data.Array as A+import safe qualified Data.Array.Unboxed as U+import safe qualified Data.Word as W (Word)+import safe Crypto.Common++-- | FPrime consist of an exact length of meaningful bits, an indicator if the number is negative and a representation of bits in a possibly larger Vector of Words+-- | Note: The vectors use small to large indices, but the Data.Word endianness is of no concern as it is hidden by Data.Bits+-- | Be careful with those indices! The usage of quotRem with them has caused some headache.+data FPrime = FPrime {-# UNPACK #-} !Int !Bool !(U.UArray W.Word)+ deriving (Show,Typeable)++-- TODO: think of efficient radix-choices, f.e. 25519:-> 51*5+radix :: Int+radix = wordSize - 2++halfradix :: Int+halfradix = radix `div` 2++radmax :: Int+radmax = 2^radix-1++sizeinradwords :: Int -> Int+sizeinradwords 0 = 1+sizeinradwords l = let (w,r) = abs l `quotRem` radix+ in if r > 0 then w + 1 else w++-- | a == b+eq :: FPrime -> FPrime -> Bool+eq (FPrime la sa va) (FPrime lb sb vb) = ((la == lb) && (sa == sb)) && undefined -- V.all (== True) (V.zipWith (==) va vb)++-- | a + b+-- TODO: implement add with spare overflow bit, carry-loop+add :: FPrime -> FPrime -> FPrime+add a@(FPrime la sa va) b@(FPrime lb sb vb) =+ let fun res = undefined+ in fun (FPrime ((if la >= lb then la else lb) + 1) sa $ undefined) -- V.singleton (0::W.Word))++-- | a + b `mod` p+-- TODO: implement addr with spare overflow bit, +addr :: FPrime -> FPrime -> FPrime -> FPrime+addr p@(FPrime lp sp vp) a b =+ let summe = add a b+ in undefined++-- | a - b, different cost than fpplus but other operation, so no key bit leakage+-- TODO: implement+sub :: FPrime -> FPrime -> FPrime+sub a b = undefined++-- | a - b mod p, different cost than fpplus but other operation, so no key bit leakage+subr :: FPrime -> FPrime -> FPrime -> FPrime+subr p a b = addr p a $ sub p b++-- | (-a)+neg :: FPrime -> FPrime+neg (FPrime la sa va) = FPrime la (not sa) va++-- | (-a) `mod` p+negr :: FPrime -> FPrime -> FPrime+negr p a = redc p $ add p a++-- | internal function+-- TODO: implement shift+shift :: FPrime -> Int -> FPrime+shift a l = undefined++-- | testBit on Words, but highest Bit is overflow, so leave it out+testBit :: FPrime -> Int -> Bool+testBit (FPrime l _ v) i =+ (i >= 0 ) && (if i < radix+ then flip B.testBit i $ undefined -- V.head v+ else (i < l) && (let (index1,index2) = i `quotRem` radix+ in flip B.testBit index2 $ (A.!) v index1)+ )++-- | modular reduction, a `mod` p+-- TODO: implement redc+redc :: FPrime -> FPrime -> FPrime+redc p a = undefined++-- | internal multiply, x * y+-- TODO: implement mul+mul :: FPrime -> FPrime -> FPrime+mul x@(FPrime l1 s1 _) y@(FPrime l2 s2 _) =+ -- computations on half-size words, results word-size+ let xh = shift x (-halfradix)+ xl = shift (shift x halfradix) (-halfradix)+ yh = shift y (-halfradix)+ yl = shift (shift y halfradix) (-halfradix)+ in undefined++-- | multiply followed by reduction, a * b `mod` p+mulr :: FPrime -> FPrime -> FPrime -> FPrime+mulr p a b = redc p $ mul a b++square :: FPrime -> FPrime -> FPrime+square p a = redc p $ mul a a++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) (redc p $ mul p1 p2) (i - 1)+ | otherwise = redc p $ ex (redc p $ mul p1 p2) (square p p2) (i - 1)+ in redc p $ ex a (square p a) (binlog - 2)++inv :: FPrime -> FPrime -> FPrime+inv p a = pow p a (toInteger p - 2)++-- | this is a chunked converter from Integer into eccrypto native format+-- | TODO: implement low-level Integer conversion+fromInteger :: Int -> Integer -> FPrime+fromInteger l i =+ let i' = i `rem` (2^l) -- we take only non-negative Integers that fit into l bits+ s = i < 0+ binlog = log2len i'+ helper a = + if a <= P.toInteger radmax+ then undefined -- V.singleton $ P.fromInteger a+ else let (d,rest) = quotRem a (P.toInteger radmax + 1)+ in undefined -- V.singleton (P.fromInteger rest) V.++ helper d+ filler b = if binlog == l+ then helper b+ else let lendiff = sizeinradwords l - sizeinradwords binlog+ in helper b undefined -- V.++ V.replicate lendiff 0+ in FPrime l s (filler i')++-- | this is a chunked converter from eccrypto native format into Integer+-- | TODO: implement low-level Integer conversion+toInteger :: FPrime -> Integer+toInteger (FPrime la s va) =+ if la <= radix+ then P.toInteger undefined -- (V.head va) * if s then (-1) else 1+ else let len = undefined -- V.length va+ helper r z i = + if i > 1+ then helper undefined -- (V.tail r) (z + B.shift (P.toInteger $ V.head r) ((len - i) * radix)) (i - 1)+ else z + B.shift (P.toInteger $ undefined) -- V.head r) ((len - i) * radix)+ in helper va 0 len * if s then (-1) else 1
src/Crypto/Fi.hs view
@@ -13,7 +13,7 @@ ----------------------------------------------------------------------------- {-# OPTIONS_GHC -O2 -feager-blackholing #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE Safe, BangPatterns, NoImplicitPrelude #-} module Crypto.Fi ( FPrime , eq@@ -31,15 +31,14 @@ , 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)+import safe Prelude ((==),Integer,Int,Bool(),($),(+),(-),(*),(^),mod,otherwise,(<))+import safe qualified Prelude as P (fromInteger,toInteger)+import safe qualified Data.Bits as B (Bits(..),shift,(.&.))+import safe Crypto.Common (log2len) -- | a simple wrapper to ease transition type FPrime = Integer@@ -61,12 +60,12 @@ -- | (-) in the field sub :: FPrime -> FPrime -> FPrime-sub a b = a - b+sub !a !b = a - b {-# INLINABLE sub #-} -- | (-) in the field subr :: FPrime -> FPrime -> FPrime -> FPrime-subr p a b = redc p (a - b)+subr !p !a !b = redc p (a - b) {-# INLINABLE subr #-} -- | negation in the field@@ -76,7 +75,7 @@ -- | bitshift wrapper shift :: FPrime -> Int -> FPrime-shift = B.shift+shift !a !b = B.shift a b -- | modular reduction, a simple wrapper around mod redc :: FPrime -> FPrime -> FPrime@@ -95,17 +94,33 @@ -- | simple squaring in the field square :: FPrime -> FPrime -> FPrime-square p a = redc p (a ^ (2::Int))+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+-- | the power function in the field, for 1>= k < p+pow :: FPrime -> FPrime -> Integer -> 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)+-- -}+-- {-+pow !p !a' !k = let a = redc p a'+ binlog = log2len a+ alleeins = fromInteger binlog (2^binlog - 1)+ eins = fromInteger binlog 1+ ex erg i+ | i < 0 = erg+ | otherwise =+ let s = condBit k i+ pat = mul alleeins s+ invpat = mul alleeins (sub eins s)+ in redc p $ ex (mulr p (square p erg) (addr p (a B..&. pat) (eins B..&. invpat))) (i - 1)+ in redc p $ ex 1 (log2len k - 1)+-- -} -- | field inversion inv :: FPrime -> FPrime -> FPrime@@ -113,20 +128,15 @@ -- | conversion wrapper with a limit fromInteger :: Int -> FPrime -> Integer-fromInteger l !a = P.fromInteger (a `mod` (2^l))+fromInteger !l !a = P.fromInteger (a `mod` (2^l)) {-# INLINABLE fromInteger #-} -- | a most simple conversion wrapper toInteger :: FPrime -> Integer-toInteger = P.toInteger +toInteger !a = P.toInteger a {-# 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)+condBit !a !i = shift (a B..&. fromInteger (i+1) ((2^(i+1)-1)::Integer)) (-i) {-# INLINABLE condBit #-}
− src/bench.hs
@@ -1,55 +0,0 @@--------------------------------------------------------------------------------- |--- Module : --- Copyright : (c) Marcel Fourné 20[09..14]--- License : BSD3--- Maintainer : Marcel Fourné (haskell@marcelfourne.de)------ benchmarks--- recommended:--- $ ghc --make -threaded bench.hs--- best performance measured with just 1 thread----------------------------------------------------------------------------------{-# OPTIONS_GHC -O2 -feager-blackholing #-}--import Crypto.ECC.NIST.Base-import Crypto.ECC.NIST.StandardCurves-import qualified Crypto.F2 as F2 (fromInteger,toInteger)-import Control.Monad.Random-import Criterion-import Criterion.Main--main::IO ()-main = do- let c1 = ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)- p1 = ECPp (stdc_xp p256) (stdc_yp p256) 1- k10' = 78260987815077071890976764339238653408132491773166348437934213365482899760747- k11' = 2^254+2^253+2^252+2^251+2^250+2^249- k12' = 2^254+2^200+2^150+2^100+2^50+1- c2 = ECi (stdc_l p521) (stdc_b p521) (stdc_p p521) (stdc_r p521)- p2 = ECPp (stdc_xp p521) (stdc_yp p521) 1- k20' = 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984- c3 = ECb (stdcF_l b283) (stdcF_a b283) (stdcF_b b283) (stdcF_p b283) (stdcF_r b283)- p3 = ECPpF2 (stdcF_xp b283) (stdcF_yp b283) (F2.fromInteger 283 1)- k30' = 115792089210356248762697446949407573529996955224135760342422259061068512044368- k31' = 2- k32' = 3- k33' = 2^282- k13' <- evalRandIO $ getRandomR (1,stdc_p p256)- k21' <- evalRandIO $ getRandomR (1,stdc_p p521)- k34' <- evalRandIO $ getRandomR (1, F2.toInteger $ stdcF_p b283)- defaultMain [bgroup "NIST P-256" [ bench "pmul by random value" $ whnf (pmul c1 p1) k13'- , bench "pmul by 2^254" $ whnf (pmul c1 p1 ) (2^254)- , bench "pmul by top 5 bits" $ whnf (pmul c1 p1) k11'- , bench "pmul by 50bit pattern" $ whnf (pmul c1 p1) k12'- ]-{- - , bgroup "NIST P-521" [ bench "pmul by random value" $ whnf (pmul c2 p2) k21'- ]--- -}-{-- , bgroup "NIST B-283" [ bench "pmul by random value" $ whnf (pmul c3 p3) k34'- ]--- -}- ]
+ test/P192 view
@@ -0,0 +1,207 @@+k = 1+x = 188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012+y = 07192B95FFC8DA78631011ED6B24CDD573F977A11E794811++k = 2+x = DAFEBF5828783F2AD35534631588A3F629A70FB16982A888+y = DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB++k = 3+x = 76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA+y = 782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD++k = 4+x = 35433907297CC378B0015703374729D7A4FE46647084E4BA+y = A2649984F2135C301EA3ACB0776CD4F125389B311DB3BE32++k = 5+x = 10BB8E9840049B183E078D9C300E1605590118EBDD7FF590+y = 31361008476F917BADC9F836E62762BE312B72543CCEAEA1++k = 6+x = A37ABC6C431F9AC398BF5BD1AA6678320ACE8ECB93D23F2A+y = 851B3CAEC99908DBFED7040A1BBDA90E081F7C5710BC68F0++k = 7+x = 8DA75A1F75DDCD7660F923243060EDCE5DE37F007011FCFD+y = 57CB5FCF6860B35418240DB8FDB3C01DD4B702F96409FFB5++k = 8+x = 2FA1F92D1ECCE92014771993CC14899D4B5977883397EDDE+y = A338AFDEF78B7214273B8B5978EF733FF2DD8A8E9738F6C0++k = 9+x = 818A4D308B1CABB74E9E8F2BA8D27C9E1D9D375AB980388F+y = 01D1AA5E208D87CD7C292F7CBB457CDF30EA542176C8E739++k = 10+x = AA7C4F9EF99E3E96D1AEDE2BD9238842859BB150D1FE9D85+y = 3212A36547EDC62901EE3658B2F4859460EB5EB2491397B0++k = 11+x = 1C995995EB76324F1844F7164D22B652280940370628A2AA+y = EF1765CE37E9EB73029F556400FA77BDB34CB8611AAA9C04++k = 12+x = 1061343F3D456D0ECA013877F8C9E7B28FCCDCDA67EEB8AB+y = 5A064CAA2EA6B03798FEF8E3E7A48648681EAC020B27293F++k = 13+x = 112AF141D33EFB9F2F68821E051E4EA004144A363C4A090A+y = 6E0CBE3BFC5293F72A2C1726E081E09E7F10A094432B1C1E++k = 14+x = 13B9310646EBC93B591746B3F7C64E05DEE08843DE1081C1+y = 1EDCEA63B44142DD15F3B427EC41A1EC4FBACA95E186E6B4++k = 15+x = 8C9595E63B56B633BA3546B2B5414DE736DE4A9E7578B1E7+y = 266B762A934F00C17CF387993AA566B6AD7537CDD98FC7B1++k = 16+x = B7310B4548FBFDBD29005092A5355BFCD99473733048AFDF+y = FF9EAE9EDCD27C1E42D8585C4546D9491845C56629CF2290++k = 17+x = 44275CD2E1F46DC3F9F57636C2B4213B8BB445930510FF8A+y = EFAD8348FDE30C87DE438612A818E98D9B76A67AD25DDFD0++k = 18+x = C1B4DB0227210613A6CA15C428024E40B6513365D72591A3+y = 1E26B286BCA1D08F4FE8F801267DF9FD7782EC3EC3F47F53++k = 19+x = C0626BCF247DE5D307FD839238D72688774FC97A1CF8AD1B+y = 9CDC99D753973DC197E12778E829C804EC1A6B4E71FAA20A++k = 20+x = BB6F082321D34DBD786A1566915C6DD5EDF879AB0F5ADD67+y = 91E4DD8A77C4531C8B76DEF2E5339B5EB95D5D9479DF4C8D++k = 112233445566778899+x = 81E6E0F14C9302C8A8DCA8A038B73165E9687D0490CD9F85+y = F58067119EED8579388C4281DC645A27DB7764750E812477++k = 112233445566778899112233445566778899+x = B357B10AC985C891B29FB37DA56661CCCF50CEC21128D4F6+y = BA20DC2FA1CC228D3C2D8B538C2177C2921884C6B7F0D96F++k = 1618292094200346491064154703205151664562462359653015613567+x = 74FEC215F253C6BD845831E059B318C87F727B136A700B91+y = 4B702B15B126A703E7A7CEC3E0EC81F8DFCA73A59F5D88B9++k = 1484605055214526729816930749766694384906446681761906688+x = 0C40230F9C4B8C0FD91F2C604FCBA9B87C2DFA153F010B4F+y = 5FC4F5771F467971B2C82752413833A68CE00F4A9A692B02++k = 1569275434166462877105627261392580354519833538813866540831+x = 28783BBF6208E1FF0F965FD8DC0C26FF1D8E02B433EDF2F7+y = A5852BBC44FD8164C1ABA9A3EC7A88E461D5D77ABD743E87++k = 3138550867681922400546388175470823984762234518836963313664+x = 45DAF0A306121BDB3B82E734CB44FDF65C9930F0E4FD2068+y = F039FACE58EB7DE34E3374ADB28DF81F019C4548BAA75B64++k = 3138550119404545973088374812479323842475901485681169401600+x = 1D5EC85004EA2ABA905CEF98A818A8C3516D7CB69A6FD575+y = 4008F35F5820F66C902195644162E5AA231DD69C9E1ECC97++k = 24519928471166604179655321383971467003990211439919824896+x = F063727C2EA4D358AB02F6B0BEEB14DBEAF2E8A1DB3208EE+y = 427418C015553361769B6A0C42923C4CA103740B6DCD9703++k = 46756768218837031708063422466358611246556475572231+x = DC81D33CA6604B1EFE49386CD492979EF807B8BAEB8566E3+y = D454247FF478514556333B3901C9F1CCC18DBC9AB938CFA0++k = 3138502977207688322901699644928655553044791844086883549215+x = D932741DF6AA0E1EED24279150436C752AA5ADCFD0698D72+y = 9759B6D2EF21D885E94CDFF219F17004D8763401DAB021B5++k = 47890485652059026491391979477371914515865621847605503+x = 571477E9D9F2A628780742257F7250C4224C483B30F3A97E+y = 1AD35EE3177D22DD5F01B5A46FFDEC547B6A41786EBB8C8F++k = 3138549376958826959341570842566593375326996431013993775615+x = 4C69939642792776C826DB8B4EBF4BD8C03FC9DFA2AEC822+y = 29BF35BE52A6036E07EBA5741CFEB4C143310216EF1B9A2E++k = 6277101735386680763835789423176059013767194773182842284061+x = BB6F082321D34DBD786A1566915C6DD5EDF879AB0F5ADD67+y = 6E1B2275883BACE37489210D1ACC64A046A2A26B8620B372++k = 6277101735386680763835789423176059013767194773182842284062+x = C0626BCF247DE5D307FD839238D72688774FC97A1CF8AD1B+y = 63236628AC68C23E681ED88717D637FA13E594B18E055DF5++k = 6277101735386680763835789423176059013767194773182842284063+x = C1B4DB0227210613A6CA15C428024E40B6513365D72591A3+y = E1D94D79435E2F70B01707FED9820601887D13C13C0B80AC++k = 6277101735386680763835789423176059013767194773182842284064+x = 44275CD2E1F46DC3F9F57636C2B4213B8BB445930510FF8A+y = 10527CB7021CF37821BC79ED57E71671648959852DA2202F++k = 6277101735386680763835789423176059013767194773182842284065+x = B7310B4548FBFDBD29005092A5355BFCD99473733048AFDF+y = 00615161232D83E1BD27A7A3BAB926B5E7BA3A99D630DD6F++k = 6277101735386680763835789423176059013767194773182842284066+x = 8C9595E63B56B633BA3546B2B5414DE736DE4A9E7578B1E7+y = D99489D56CB0FF3E830C7866C55A9948528AC8322670384E++k = 6277101735386680763835789423176059013767194773182842284067+x = 13B9310646EBC93B591746B3F7C64E05DEE08843DE1081C1+y = E123159C4BBEBD22EA0C4BD813BE5E12B045356A1E79194B++k = 6277101735386680763835789423176059013767194773182842284068+x = 112AF141D33EFB9F2F68821E051E4EA004144A363C4A090A+y = 91F341C403AD6C08D5D3E8D91F7E1F6080EF5F6BBCD4E3E1++k = 6277101735386680763835789423176059013767194773182842284069+x = 1061343F3D456D0ECA013877F8C9E7B28FCCDCDA67EEB8AB+y = A5F9B355D1594FC86701071C185B79B697E153FDF4D8D6C0++k = 6277101735386680763835789423176059013767194773182842284070+x = 1C995995EB76324F1844F7164D22B652280940370628A2AA+y = 10E89A31C816148CFD60AA9BFF0588414CB3479EE55563FB++k = 6277101735386680763835789423176059013767194773182842284071+x = AA7C4F9EF99E3E96D1AEDE2BD9238842859BB150D1FE9D85+y = CDED5C9AB81239D6FE11C9A74D0B7A6A9F14A14DB6EC684F++k = 6277101735386680763835789423176059013767194773182842284072+x = 818A4D308B1CABB74E9E8F2BA8D27C9E1D9D375AB980388F+y = FE2E55A1DF72783283D6D08344BA831FCF15ABDE893718C6++k = 6277101735386680763835789423176059013767194773182842284073+x = 2FA1F92D1ECCE92014771993CC14899D4B5977883397EDDE+y = 5CC7502108748DEBD8C474A687108CBF0D22757168C7093F++k = 6277101735386680763835789423176059013767194773182842284074+x = 8DA75A1F75DDCD7660F923243060EDCE5DE37F007011FCFD+y = A834A030979F4CABE7DBF247024C3FE12B48FD069BF6004A++k = 6277101735386680763835789423176059013767194773182842284075+x = A37ABC6C431F9AC398BF5BD1AA6678320ACE8ECB93D23F2A+y = 7AE4C3513666F7240128FBF5E44256F0F7E083A8EF43970F++k = 6277101735386680763835789423176059013767194773182842284076+x = 10BB8E9840049B183E078D9C300E1605590118EBDD7FF590+y = CEC9EFF7B8906E84523607C919D89D40CED48DABC331515E++k = 6277101735386680763835789423176059013767194773182842284077+x = 35433907297CC378B0015703374729D7A4FE46647084E4BA+y = 5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD++k = 6277101735386680763835789423176059013767194773182842284078+x = 76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA+y = 87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02++k = 6277101735386680763835789423176059013767194773182842284079+x = DAFEBF5828783F2AD35534631588A3F629A70FB16982A888+y = 229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54++k = 6277101735386680763835789423176059013767194773182842284080+x = 188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012+y = F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE
+ test/P224 view
@@ -0,0 +1,207 @@+k = 1+x = B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21+y = BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34++k = 2+x = 706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6+y = 1C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB++k = 3+x = DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04+y = A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925++k = 4+x = AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301+y = 0482580A0EC5BC47E88BC8C378632CD196CB3FA058A7114EB03054C9++k = 5+x = 31C49AE75BCE7807CDFF22055D94EE9021FEDBB5AB51C57526F011AA+y = 27E8BFF1745635EC5BA0C9F1C2EDE15414C6507D29FFE37E790A079B++k = 6+x = 1F2483F82572251FCA975FEA40DB821DF8AD82A3C002EE6C57112408+y = 89FAF0CCB750D99B553C574FAD7ECFB0438586EB3952AF5B4B153C7E++k = 7+x = DB2F6BE630E246A5CF7D99B85194B123D487E2D466B94B24A03C3E28+y = 0F3A30085497F2F611EE2517B163EF8C53B715D18BB4E4808D02B963++k = 8+x = 858E6F9CC6C12C31F5DF124AA77767B05C8BC021BD683D2B55571550+y = 046DCD3EA5C43898C5C5FC4FDAC7DB39C2F02EBEE4E3541D1E78047A++k = 9+x = 2FDCCCFEE720A77EF6CB3BFBB447F9383117E3DAA4A07E36ED15F78D+y = 371732E4F41BF4F7883035E6A79FCEDC0E196EB07B48171697517463++k = 10+x = AEA9E17A306517EB89152AA7096D2C381EC813C51AA880E7BEE2C0FD+y = 39BB30EAB337E0A521B6CBA1ABE4B2B3A3E524C14A3FE3EB116B655F++k = 11+x = EF53B6294ACA431F0F3C22DC82EB9050324F1D88D377E716448E507C+y = 20B510004092E96636CFB7E32EFDED8265C266DFB754FA6D6491A6DA++k = 12+x = 6E31EE1DC137F81B056752E4DEAB1443A481033E9B4C93A3044F4F7A+y = 207DDDF0385BFDEAB6E9ACDA8DA06B3BBEF224A93AB1E9E036109D13++k = 13+x = 34E8E17A430E43289793C383FAC9774247B40E9EBD3366981FCFAECA+y = 252819F71C7FB7FBCB159BE337D37D3336D7FEB963724FDFB0ECB767++k = 14+x = A53640C83DC208603DED83E4ECF758F24C357D7CF48088B2CE01E9FA+y = D5814CD724199C4A5B974A43685FBF5B8BAC69459C9469BC8F23CCAF++k = 15+x = BAA4D8635511A7D288AEBEEDD12CE529FF102C91F97F867E21916BF9+y = 979A5F4759F80F4FB4EC2E34F5566D595680A11735E7B61046127989++k = 16+x = 0B6EC4FE1777382404EF679997BA8D1CC5CD8E85349259F590C4C66D+y = 3399D464345906B11B00E363EF429221F2EC720D2F665D7DEAD5B482++k = 17+x = B8357C3A6CEEF288310E17B8BFEFF9200846CA8C1942497C484403BC+y = FF149EFA6606A6BD20EF7D1B06BD92F6904639DCE5174DB6CC554A26++k = 18+x = C9FF61B040874C0568479216824A15EAB1A838A797D189746226E4CC+y = EA98D60E5FFC9B8FCF999FAB1DF7E7EF7084F20DDB61BB045A6CE002++k = 19+x = A1E81C04F30CE201C7C9ACE785ED44CC33B455A022F2ACDBC6CAE83C+y = DCF1F6C3DB09C70ACC25391D492FE25B4A180BABD6CEA356C04719CD++k = 20+x = FCC7F2B45DF1CD5A3C0C0731CA47A8AF75CFB0347E8354EEFE782455+y = 0D5D7110274CBA7CDEE90E1A8B0D394C376A5573DB6BE0BF2747F530++k = 112233445566778899+x = 61F077C6F62ED802DAD7C2F38F5C67F2CC453601E61BD076BB46179E+y = 2272F9E9F5933E70388EE652513443B5E289DD135DCC0D0299B225E4++k = 112233445566778899112233445566778899+x = 029895F0AF496BFC62B6EF8D8A65C88C613949B03668AAB4F0429E35+y = 3EA6E53F9A841F2019EC24BDE1A75677AA9B5902E61081C01064DE93++k = 6950511619965839450988900688150712778015737983940691968051900319680+x = AB689930BCAE4A4AA5F5CB085E823E8AE30FD365EB1DA4ABA9CF0379+y = 3345A121BBD233548AF0D210654EB40BAB788A03666419BE6FBD34E7++k = 13479972933410060327035789020509431695094902435494295338570602119423+x = BDB6A8817C1F89DA1C2F3DD8E97FEB4494F2ED302A4CE2BC7F5F4025+y = 4C7020D57C00411889462D77A5438BB4E97D177700BF7243A07F1680++k = 13479971751745682581351455311314208093898607229429740618390390702079+x = D58B61AA41C32DD5EBA462647DBA75C5D67C83606C0AF2BD928446A9+y = D24BA6A837BE0460DD107AE77725696D211446C5609B4595976B16BD++k = 13479972931865328106486971546324465392952975980343228160962702868479+x = DC9FA77978A005510980E929A1485F63716DF695D7A0C18BB518DF03+y = EDE2B016F2DDFFC2A8C015B134928275CE09E5661B7AB14CE0D1D403++k = 11795773708834916026404142434151065506931607341523388140225443265536+x = 499D8B2829CFB879C901F7D85D357045EDAB55028824D0F05BA279BA+y = BF929537B06E4015919639D94F57838FA33FC3D952598DCDBB44D638++k = 784254593043826236572847595991346435467177662189391577090+x = 8246C999137186632C5F9EDDF3B1B0E1764C5E8BD0E0D8A554B9CB77+y = E80ED8660BC1CB17AC7D845BE40A7A022D3306F116AE9F81FEA65947++k = 13479767645505654746623887797783387853576174193480695826442858012671+x = 6670C20AFCCEAEA672C97F75E2E9DD5C8460E54BB38538EBB4BD30EB+y = F280D8008D07A4CAF54271F993527D46FF3FF46FD1190A3F1FAA4F74++k = 205688069665150753842126177372015544874550518966168735589597183+x = 000ECA934247425CFD949B795CB5CE1EFF401550386E28D1A4C5A8EB+y = D4C01040DBA19628931BC8855370317C722CBD9CA6156985F1C2E9CE++k = 13479966930919337728895168462090683249159702977113823384618282123295+x = EF353BF5C73CD551B96D596FBC9A67F16D61DD9FE56AF19DE1FBA9CD+y = 21771B9CDCE3E8430C09B3838BE70B48C21E15BC09EE1F2D7945B91F++k = 50210731791415612487756441341851895584393717453129007497216+x = 4036052A3091EB481046AD3289C95D3AC905CA0023DE2C03ECD451CF+y = D768165A38A2B96F812586A9D59D4136035D9C853A5BF2E1C86A4993++k = 26959946667150639794667015087019625940457807714424391721682722368041+x = FCC7F2B45DF1CD5A3C0C0731CA47A8AF75CFB0347E8354EEFE782455+y = F2A28EEFD8B345832116F1E574F2C6B2C895AA8C24941F40D8B80AD1++k = 26959946667150639794667015087019625940457807714424391721682722368042+x = A1E81C04F30CE201C7C9ACE785ED44CC33B455A022F2ACDBC6CAE83C+y = 230E093C24F638F533DAC6E2B6D01DA3B5E7F45429315CA93FB8E634++k = 26959946667150639794667015087019625940457807714424391721682722368043+x = C9FF61B040874C0568479216824A15EAB1A838A797D189746226E4CC+y = 156729F1A003647030666054E208180F8F7B0DF2249E44FBA5931FFF++k = 26959946667150639794667015087019625940457807714424391721682722368044+x = B8357C3A6CEEF288310E17B8BFEFF9200846CA8C1942497C484403BC+y = 00EB610599F95942DF1082E4F9426D086FB9C6231AE8B24933AAB5DB++k = 26959946667150639794667015087019625940457807714424391721682722368045+x = 0B6EC4FE1777382404EF679997BA8D1CC5CD8E85349259F590C4C66D+y = CC662B9BCBA6F94EE4FF1C9C10BD6DDD0D138DF2D099A282152A4B7F++k = 26959946667150639794667015087019625940457807714424391721682722368046+x = BAA4D8635511A7D288AEBEEDD12CE529FF102C91F97F867E21916BF9+y = 6865A0B8A607F0B04B13D1CB0AA992A5A97F5EE8CA1849EFB9ED8678++k = 26959946667150639794667015087019625940457807714424391721682722368047+x = A53640C83DC208603DED83E4ECF758F24C357D7CF48088B2CE01E9FA+y = 2A7EB328DBE663B5A468B5BC97A040A3745396BA636B964370DC3352++k = 26959946667150639794667015087019625940457807714424391721682722368048+x = 34E8E17A430E43289793C383FAC9774247B40E9EBD3366981FCFAECA+y = DAD7E608E380480434EA641CC82C82CBC92801469C8DB0204F13489A++k = 26959946667150639794667015087019625940457807714424391721682722368049+x = 6E31EE1DC137F81B056752E4DEAB1443A481033E9B4C93A3044F4F7A+y = DF82220FC7A4021549165325725F94C3410DDB56C54E161FC9EF62EE++k = 26959946667150639794667015087019625940457807714424391721682722368050+x = EF53B6294ACA431F0F3C22DC82EB9050324F1D88D377E716448E507C+y = DF4AEFFFBF6D1699C930481CD102127C9A3D992048AB05929B6E5927++k = 26959946667150639794667015087019625940457807714424391721682722368051+x = AEA9E17A306517EB89152AA7096D2C381EC813C51AA880E7BEE2C0FD+y = C644CF154CC81F5ADE49345E541B4D4B5C1ADB3EB5C01C14EE949AA2++k = 26959946667150639794667015087019625940457807714424391721682722368052+x = 2FDCCCFEE720A77EF6CB3BFBB447F9383117E3DAA4A07E36ED15F78D+y = C8E8CD1B0BE40B0877CFCA1958603122F1E6914F84B7E8E968AE8B9E++k = 26959946667150639794667015087019625940457807714424391721682722368053+x = 858E6F9CC6C12C31F5DF124AA77767B05C8BC021BD683D2B55571550+y = FB9232C15A3BC7673A3A03B0253824C53D0FD1411B1CABE2E187FB87++k = 26959946667150639794667015087019625940457807714424391721682722368054+x = DB2F6BE630E246A5CF7D99B85194B123D487E2D466B94B24A03C3E28+y = F0C5CFF7AB680D09EE11DAE84E9C1072AC48EA2E744B1B7F72FD469E++k = 26959946667150639794667015087019625940457807714424391721682722368055+x = 1F2483F82572251FCA975FEA40DB821DF8AD82A3C002EE6C57112408+y = 76050F3348AF2664AAC3A8B05281304EBC7A7914C6AD50A4B4EAC383++k = 26959946667150639794667015087019625940457807714424391721682722368056+x = 31C49AE75BCE7807CDFF22055D94EE9021FEDBB5AB51C57526F011AA+y = D817400E8BA9CA13A45F360E3D121EAAEB39AF82D6001C8186F5F866++k = 26959946667150639794667015087019625940457807714424391721682722368057+x = AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301+y = FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38++k = 26959946667150639794667015087019625940457807714424391721682722368058+x = DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04+y = 5C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC++k = 26959946667150639794667015087019625940457807714424391721682722368059+x = 706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6+y = E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746++k = 26959946667150639794667015087019625940457807714424391721682722368060+x = B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21+y = 42C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD
+ test/P256 view
@@ -0,0 +1,207 @@+k = 1+x = 6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296+y = 4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5++k = 2+x = 7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978+y = 07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1++k = 3+x = 5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C+y = 8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032++k = 4+x = E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852+y = E0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6++k = 5+x = 51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED+y = E0C17DA8904A727D8AE1BF36BF8A79260D012F00D4D80888D1D0BB44FDA16DA4++k = 6+x = B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9+y = E85C10743237DAD56FEC0E2DFBA703791C00F7701C7E16BDFD7C48538FC77FE2++k = 7+x = 8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3+y = 73EB1DBDE03318366D069F83A6F5900053C73633CB041B21C55E1A86C1F400B4++k = 8+x = 62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393+y = AD5ACCBD91E9D8244FF15D771167CEE0A2ED51F6BBE76A78DA540A6A0F09957E++k = 9+x = EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0+y = 2A2744C972C9FCE787014A964A8EA0C84D714FEAA4DE823FE85A224A4DD048FA++k = 10+x = CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F+y = 878662A229AAAE906E123CDD9D3B4C10590DED29FE751EEECA34BBAA44AF0773++k = 11+x = 3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1+y = 9099209ACCC4C8A224C843AFA4F4C68A090D04DA5E9889DAE2F8EEFCE82A3740++k = 12+x = 741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4+y = 0770B46A9C385FDC567383554887B1548EEB912C35BA5CA71995FF22CD4481D3++k = 13+x = 177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01+y = 63BB58CD4EBEA558A24091ADB40F4E7226EE14C3A1FB4DF39C43BBE2EFC7BFD8++k = 14+x = 54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B+y = F599F1BB29F4317542121F8C05A2E7C37171EA77735090081BA7C82F60D0B375++k = 15+x = F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F+y = B5B93EE3592E2D1F4E6594E51F9643E62A3B21CE75B5FA3F47E59CDE0D034F36++k = 16+x = 76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E+y = A985FE61341F260E6CB0A1B5E11E87208599A0040FC78BAA0E9DDD724B8C5110++k = 17+x = 47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E+y = AA005EE6B5B957286231856577648E8381B2804428D5733F32F787FF71F1FCDC++k = 18+x = 1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA+y = F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2++k = 19+x = CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83+y = 58D7614B24D9EF515C35E7100D6D6CE4A496716E30FA3E03E39150752BCECDAA++k = 20+x = 83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A+y = 76E49B6DE2F73234AE6A5EB9D612B75C9F2202BB6923F54FF8240AAA86F640B8++k = 112233445566778899+x = 339150844EC15234807FE862A86BE77977DBFB3AE3D96F4C22795513AEAAB82F+y = B1C14DDFDC8EC1B2583F51E85A5EB3A155840F2034730E9B5ADA38B674336A21++k = 112233445566778899112233445566778899+x = 1B7E046A076CC25E6D7FA5003F6729F665CC3241B5ADAB12B498CD32F2803264+y = BFEA79BE2B666B073DB69A2A241ADAB0738FE9D2DD28B5604EB8C8CF097C457B++k = 29852220098221261079183923314599206100666902414330245206392788703677545185283+x = 9EACE8F4B071E677C5350B02F2BB2B384AAE89D58AA72CA97A170572E0FB222F+y = 1BBDAEC2430B09B93F7CB08678636CE12EAAFD58390699B5FD2F6E1188FC2A78++k = 57896042899961394862005778464643882389978449576758748073725983489954366354431+x = 878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D+y = 714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E++k = 1766845392945710151501889105729049882997660004824848915955419660366636031+x = 659A379625AB122F2512B8DADA02C6348D53B54452DFF67AC7ACE4E8856295CA+y = 49D81AB97B648464D0B4A288BD7818FAB41A16426E943527C4FED8736C53D0F6++k = 28948025760307534517734791687894775804466072615242963443097661355606862201087+x = CBCEAAA8A4DD44BBCE58E8DB7740A5510EC2CB7EA8DA8D8F036B3FB04CDA4DE4+y = 4BD7AA301A80D7F59FD983FEDBE59BB7B2863FE46494935E3745B360E32332FA++k = 113078210460870548944811695960290644973229224625838436424477095834645696384+x = F0C4A0576154FF3A33A3460D42EAED806E854DFA37125221D37935124BA462A4+y = 5B392FA964434D29EEC6C9DBC261CF116796864AA2FAADB984A2DF38D1AEF7A3++k = 12078056106883488161242983286051341125085761470677906721917479268909056+x = 5E6C8524B6369530B12C62D31EC53E0288173BD662BDF680B53A41ECBCAD00CC+y = 447FE742C2BFEF4D0DB14B5B83A2682309B5618E0064A94804E9282179FE089F++k = 57782969857385448082319957860328652998540760998293976083718804450708503920639+x = 03792E541BC209076A3D7920A915021ECD396A6EB5C3960024BE5575F3223484+y = FC774AE092403101563B712F68170312304F20C80B40C06282063DB25F268DE4++k = 57896017119460046759583662757090100341435943767777707906455551163257755533312+x = 2379FF85AB693CDF901D6CE6F2473F39C04A2FE3DCD842CE7AAB0E002095BCF8+y = F8B476530A634589D5129E46F322B02FBC610A703D80875EE70D7CE1877436A1++k = 452312848374287284681282171017647412726433684238464212999305864837160993279+x = C1E4072C529BF2F44DA769EFC934472848003B3AF2C0F5AA8F8DDBD53E12ED7C+y = 39A6EE77812BB37E8079CD01ED649D3830FCA46F718C1D3993E4A591824ABCDB++k = 904571339174065134293634407946054000774746055866917729876676367558469746684+x = 34DFBC09404C21E250A9B40FA8772897AC63A094877DB65862B61BD1507B34F3+y = CF6F8A876C6F99CEAEC87148F18C7E1E0DA6E165FFC8ED82ABB65955215F77D3++k = 115792089210356248762697446949407573529996955224135760342422259061068512044349+x = 83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A+y = 891B64911D08CDCC5195A14629ED48A360DDFD4596DC0AB007DBF5557909BF47++k = 115792089210356248762697446949407573529996955224135760342422259061068512044350+x = CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83+y = A7289EB3DB2610AFA3CA18EFF292931B5B698E92CF05C1FC1C6EAF8AD4313255++k = 115792089210356248762697446949407573529996955224135760342422259061068512044351+x = 1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA+y = 090E9BA4EA341A246056482026911A58233EE4A4A10B0E08727C4CC6C395BA5D++k = 115792089210356248762697446949407573529996955224135760342422259061068512044352+x = 47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E+y = 55FFA1184A46A8D89DCE7A9A889B717C7E4D7FBCD72A8CC0CD0878008E0E0323++k = 115792089210356248762697446949407573529996955224135760342422259061068512044353+x = 76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E+y = 567A019DCBE0D9F2934F5E4A1EE178DF7A665FFCF0387455F162228DB473AEEF++k = 115792089210356248762697446949407573529996955224135760342422259061068512044354+x = F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F+y = 4A46C11BA6D1D2E1B19A6B1AE069BC19D5C4DE328A4A05C0B81A6321F2FCB0C9++k = 115792089210356248762697446949407573529996955224135760342422259061068512044355+x = 54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B+y = 0A660E43D60BCE8BBDEDE073FA5D183C8E8E15898CAF6FF7E45837D09F2F4C8A++k = 115792089210356248762697446949407573529996955224135760342422259061068512044356+x = 177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01+y = 9C44A731B1415AA85DBF6E524BF0B18DD911EB3D5E04B20C63BC441D10384027++k = 115792089210356248762697446949407573529996955224135760342422259061068512044357+x = 741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4+y = F88F4B9463C7A024A98C7CAAB7784EAB71146ED4CA45A358E66A00DD32BB7E2C++k = 115792089210356248762697446949407573529996955224135760342422259061068512044358+x = 3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1+y = 6F66DF64333B375EDB37BC505B0B3975F6F2FB26A16776251D07110317D5C8BF++k = 115792089210356248762697446949407573529996955224135760342422259061068512044359+x = CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F+y = 78799D5CD655517091EDC32262C4B3EFA6F212D7018AE11135CB4455BB50F88C++k = 115792089210356248762697446949407573529996955224135760342422259061068512044360+x = EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0+y = D5D8BB358D36031978FEB569B5715F37B28EB0165B217DC017A5DDB5B22FB705++k = 115792089210356248762697446949407573529996955224135760342422259061068512044361+x = 62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393+y = 52A533416E1627DCB00EA288EE98311F5D12AE0A4418958725ABF595F0F66A81++k = 115792089210356248762697446949407573529996955224135760342422259061068512044362+x = 8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3+y = 8C14E2411FCCE7CA92F9607C590A6FFFAC38C9CD34FBE4DE3AA1E5793E0BFF4B++k = 115792089210356248762697446949407573529996955224135760342422259061068512044363+x = B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9+y = 17A3EF8ACDC8252B9013F1D20458FC86E3FF0890E381E9420283B7AC7038801D++k = 115792089210356248762697446949407573529996955224135760342422259061068512044364+x = 51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED+y = 1F3E82566FB58D83751E40C9407586D9F2FED1002B27F7772E2F44BB025E925B++k = 115792089210356248762697446949407573529996955224135760342422259061068512044365+x = E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852+y = 1F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739++k = 115792089210356248762697446949407573529996955224135760342422259061068512044366+x = 5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C+y = 78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD++k = 115792089210356248762697446949407573529996955224135760342422259061068512044367+x = 7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978+y = F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E++k = 115792089210356248762697446949407573529996955224135760342422259061068512044368+x = 6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296+y = B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A
+ test/P384 view
@@ -0,0 +1,207 @@+k = 1+x = AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7+y = 3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F++k = 2+x = 08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61+y = 8E80F1FA5B1B3CEDB7BFE8DFFD6DBA74B275D875BC6CC43E904E505F256AB4255FFD43E94D39E22D61501E700A940E80++k = 3+x = 077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831+y = C995F7CA0B0C42837D0BBE9602A9FC998520B41C85115AA5F7684C0EDC111EACC24ABD6BE4B5D298B65F28600A2F1DF1++k = 4+x = 138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835+y = CACAE29869A62E1631E8A28181AB56616DC45D918ABC09F3AB0E63CF792AA4DCED7387BE37BBA569549F1C02B270ED67++k = 5+x = 11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B037882F4A1CA297E60ABCDBC3836D84BC+y = 8FA696C77440F92D0F5837E90A00E7C5284B447754D5DEE88C986533B6901AEB3177686D0AE8FB33184414ABE6C1713A++k = 6+x = 627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F26257383021317D7202FF30E50937F0854E35C5DF+y = 09766A4CB3F8B1C21BE6DDA6C14F1575B2C95352644F774C99864F613715441604C45B8D84E165311733A408D3F0F934++k = 7+x = 283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05526F55B9EBB2040F05B48FB6D0E1+y = 9475C99061E41B88BA52EFDB8C1690471A61D867ED799729D9C92CD01DBD225630D84EDE32A78F9E64664CDAC512EF8C++k = 8+x = 1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D+y = DCD2365700D4106A835388BA3DB8FD0E22554ADC6D521CD4BD1C30C2EC0EEC196BADE1E9CDD1708D6F6ABFA4022B0AD2++k = 9+x = 8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388528BFEE2B9535C55E4461079118B+y = 62C77E1438B601D6452C4A5322C3A9799A9B3D7CA3C400C6B7678854AED9B3029E743EFEDFD51B68262DA4F9AC664AF8++k = 10+x = A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E85AB507BF91AA9CB2D13186658FB+y = A988B72AE7C1279F22D9083DB5F0ECDDF70119550C183C31C502DF78C3B705A8296D8195248288D997784F6AB73A21DD++k = 11+x = 099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749B66E3AFB81D626356F3B55B4DDD8+y = 2E4C0C234E30AB96688505544AC5E0396FC4EED8DFC363FD43FF93F41B52A3255466D51263AAFF357D5DBA8138C5E0BB++k = 12+x = 952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A5E22DA817CB466DA2EA77D2A7022+y = A0320FAF84B5BC0563052DEAE6F66F2E09FB8036CE18A0EBB9028B096196B50D031AA64589743E229EF6BACCE21BD16E++k = 13+x = A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5F441ABD99F1BAAF1CA1E3B5CBCE7+y = DE1B38B3989F3318644E4147AF164ECC5185595046932EC086329BE057857D66776BCB8272218A7D6423A12736F429CC++k = 14+x = E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41ABA24DBC02DE6637209ACCF0F59EA0+y = 891AE44356FC8AE0932BCBF6DE52C8A933B86191E7728D79C8319413A09D0F48FC468BA05509DE22D7EE5C9E1B67B888++k = 15+x = B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849557A10B6383B4B88701A9606860B+y = 152919E7DF9162A61B049B2536164B1BEEBAC4A11D749AF484D1114373DFBFD9838D24F8B284AF50985D588D33F7BD62++k = 16+x = D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8EBC773D157811A462B892401DAFCF+y = D815229DE12906D241816D5E9A9448F1D41D4FC40E2A3BDB9CABA57E440A7ABAD1210CB8F49BF2236822B755EBAB3673++k = 17+x = 4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F817012A991AF1F486CAF3A9ADD9FFCC03+y = 5ECF94777833059839474594AF603598163AD3F8008AD0CD9B797D277F2388B304DA4D2FAA9680ECFA650EF5E23B09A0++k = 18+x = DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C2355169CC9C99DFB44692A9B93DD+y = 453ACA1243B5EC6B423A68A25587E1613A634C1C42D2EE7E6C57F449A1C91DC89168B7036EC0A7F37A366185233EC522++k = 19+x = 8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8651060801C0E9599E68713F5D41B+y = A1592FF0121460857BE99F2A60669050B2291B68A1039AA0594B32FD7ADC0E8C11FFBA5608004E646995B07E75E52245++k = 20+x = 605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A105D70D4F85C50599BE5800A623F+y = 5158EE87962AC6B81F00A103B8543A07381B7639A3A65F1353AEF11B733106DDE92E99B78DE367B48E238C38DAD8EEDD++k = 112233445566778899+x = A499EFE48839BC3ABCD1C5CEDBDD51904F9514DB44F4686DB918983B0C9DC3AEE05A88B72433E9515F91A329F5F4FA60+y = 3B7CA28EF31F809C2F1BA24AAED847D0F8B406A4B8968542DE139DB5828CA410E615D1182E25B91B1131E230B727D36A++k = 112233445566778899112233445566778899+x = 90A0B1CAC601676B083F21E07BC7090A3390FE1B9C7F61D842D27FA315FB38D83667A11A71438773E483F2A114836B24+y = 3197D3C6123F0D6CD65D5F0DE106FEF36656CB16DC7CD1A6817EB1D51510135A8F492F72665CFD1053F75ED03A7D04C9++k = 10158184112867540819754776755819761756724522948540419979637868435924061464745859402573149498125806098880003248619520+x = F2A066BD332DC59BBC3D01DA1B124C687D8BB44611186422DE94C1DA4ECF150E664D353CCDB5CB2652685F8EB4D2CD49+y = D6ED0BF75FDD8E53D87765FA746835B673881D6D1907163A2C43990D75B454294F942EC571AD5AAE1806CAF2BB8E9A4A++k = 9850501551105991028245052605056992139810094908912799254115847683881357749738726091734403950439157209401153690566655+x = 5C7F9845D1C4AA44747F9137B6F9C39B36B26B8A62E8AF97290434D5F3B214F5A0131550ADB19058DC4C8780C4165C4A+y = 712F7FCCC86F647E70DB8798228CB16344AF3D00B139B6F8502939C2A965AF0EB4E39E2E16AB8F597B8D5630A50C9D85++k = 9850502723405747097317271194763310482462751455185699630571661657946308788426092983270628740691202018691293898608608+x = DD5838F7EC3B8ACF1BECFD746F8B668C577107E93548ED93ED0D254C112E76B10F053109EF8428BFCD50D38C4C030C57+y = 33244F479CDAC34F160D9E4CE2D19D2FF0E3305B5BF0EEF29E91E9DE6E28F678C61B773AA7E3C03740E1A49D1AA2493C++k = 1146189371817832990947611400450889406070215735255370280811736587845016396640969656447803207438173695115264+x = CB8ED893530BFBA04B4CA655923AAAD109A62BC8411D5925316C32D33602459C33057A1FBCB5F70AEB295D90F9165FBC+y = 426AEE3E91B08420F9B357B66D5AFCBCF3956590BF5564DBF9086042EB880493D19DA39AAA6436C6B5FC66CE5596B43F++k = 9619341438217097641865390297189708858938017986426152622639500179774624579127744608993294698873437325090751520764+x = 67F714012B6B070182122DDD435CC1C2262A1AB88939BC6A2906CB2B4137C5E82B4582160F6403CAB887ACDF5786A268+y = 90E31CF398CE2F8C5897C7380BF541075D1B4D3CB70547262B7095731252F181AC0597C66AF8311C7780DB39DEC0BD32++k = 1231307996623833742387400352380172566077927415136813282735641918395585376659282194317590461518639141730493780722175+x = 55A79DF7B53A99D31462C7E1A5ED5623970715BB1021098CB973A7520CBD6365E613E4B2467486FB37E86E01CEE09B8F+y = B95AEB71693189911661B709A886A1867F056A0EFE401EE11C06030E46F7A87731DA4575863178012208707DD666727C++k = 587118838854683800942906722504810343086699021451906946003274128973058942197377013128840514404789143516741631+x = 9539A968CF819A0E52E10EEA3BACA1B6480D7E4DF69BC07002C568569047110EE4FE72FCA423FDD5179D6E0E19C44844+y = A7728F37A0AE0DF2716061900D83A4DA149144129F89A214A8260464BAB609BB322E4E67DE5E4C4C6CB8D25983EC19B0++k = 153914077530671739663795070876894766451466019374644150541452557147890542143280855693795882295846834387672681660416+x = 933FC13276672AB360D909161CD02D830B1628935DF0D800C6ED602C59D575A86A8A97E3A2D697E3ED06BE741C0097D6+y = F35296BD7A6B4C6C025ED6D84338CCCC7522A45C5D4FBDB1442556CAEFB598128FA188793ADA510EB5F44E90A4E4BEF1++k = 75148784606135150476268171850082176256856776750560539466196504390587921789283134009866871754361028131485122560+x = 0CE31E1C4A937071E6EBACA026A93D783848BCC0C1585DAF639518125FCD1F1629D63041ABFB11FFC8F03FA8B6FCF6BF+y = A69EA55BE4BEAB2D5224050FEBFFBDFCFD614624C3B4F228909EB80012F003756D1C377E52F04FA539237F24DD080E2E++k = 19691383761310193665095292424754807745686799029814707849273381514021788371252213000473497648851202400395528761229312+x = 6842CFE3589AC268818291F31D44177A9168DCBC19F321ED66D81ECF59E31B54CCA0DDFD4C4136780171748D69A91C54+y = E3A5ECD5AC725F13DBC631F358C6E817EDCF3A613B83832741A9DB591A0BAE767FC714F70C2E7EA891E4312047DECCC0++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942623+x = 605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A105D70D4F85C50599BE5800A623F+y = AEA7117869D53947E0FF5EFC47ABC5F8C7E489C65C59A0ECAC510EE48CCEF92116D16647721C984B71DC73C825271122++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942624+x = 8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8651060801C0E9599E68713F5D41B+y = 5EA6D00FEDEB9F7A841660D59F996FAF4DD6E4975EFC655FA6B4CD028523F172EE0045A8F7FFB19B966A4F828A1ADDBA++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942625+x = DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C2355169CC9C99DFB44692A9B93DD+y = BAC535EDBC4A1394BDC5975DAA781E9EC59CB3E3BD2D118193A80BB65E36E2366E9748FB913F580C85C99E7BDCC13ADD++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942626+x = 4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F817012A991AF1F486CAF3A9ADD9FFCC03+y = A1306B8887CCFA67C6B8BA6B509FCA67E9C52C07FF752F32648682D880DC774BFB25B2CF55697F13059AF10B1DC4F65F++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942627+x = D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8EBC773D157811A462B892401DAFCF+y = 27EADD621ED6F92DBE7E92A1656BB70E2BE2B03BF1D5C42463545A81BBF585442EDEF3460B640DDC97DD48AB1454C98C++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942628+x = B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849557A10B6383B4B88701A9606860B+y = EAD6E618206E9D59E4FB64DAC9E9B4E411453B5EE28B650B7B2EEEBC8C2040257C72DB064D7B50AF67A2A773CC08429D++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942629+x = E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41ABA24DBC02DE6637209ACCF0F59EA0+y = 76E51BBCA903751F6CD4340921AD3756CC479E6E188D728637CE6BEC5F62F0B603B9745EAAF621DD2811A362E4984777++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942630+x = A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5F441ABD99F1BAAF1CA1E3B5CBCE7+y = 21E4C74C6760CCE79BB1BEB850E9B133AE7AA6AFB96CD13F79CD641FA87A82988894347C8DDE75829BDC5ED9C90BD633++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942631+x = 952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A5E22DA817CB466DA2EA77D2A7022+y = 5FCDF0507B4A43FA9CFAD215190990D1F6047FC931E75F1446FD74F69E694AF1FCE559B9768BC1DD610945341DE42E91++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942632+x = 099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749B66E3AFB81D626356F3B55B4DDD8+y = D1B3F3DCB1CF5469977AFAABB53A1FC6903B1127203C9C02BC006C0BE4AD5CD9AB992AEC9C5500CA82A2457FC73A1F44++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942633+x = A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E85AB507BF91AA9CB2D13186658FB+y = 567748D5183ED860DD26F7C24A0F132208FEE6AAF3E7C3CE3AFD20873C48FA56D6927E69DB7D77266887B09648C5DE22++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942634+x = 8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388528BFEE2B9535C55E4461079118B+y = 9D3881EBC749FE29BAD3B5ACDD3C56866564C2835C3BFF39489877AB51264CFC618BC100202AE497D9D25B075399B507++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942635+x = 1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D+y = 232DC9A8FF2BEF957CAC7745C24702F1DDAAB52392ADE32B42E3CF3D13F113E594521E15322E8F729095405CFDD4F52D++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942636+x = 283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05526F55B9EBB2040F05B48FB6D0E1+y = 6B8A366F9E1BE47745AD102473E96FB8E59E2798128668D62636D32FE242DDA8CF27B120CD5870619B99B3263AED1073++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942637+x = 627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F26257383021317D7202FF30E50937F0854E35C5DF+y = F68995B34C074E3DE41922593EB0EA8A4D36ACAD9BB088B36679B09EC8EABBE8FB3BA4717B1E9ACEE8CC5BF82C0F06CB++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942638+x = 11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B037882F4A1CA297E60ABCDBC3836D84BC+y = 705969388BBF06D2F0A7C816F5FF183AD7B4BB88AB2A211773679ACC496FE513CE889791F51704CCE7BBEB55193E8EC5++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942639+x = 138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835+y = 35351D679659D1E9CE175D7E7E54A99E923BA26E7543F60C54F19C3086D55B22128C7840C8445A96AB60E3FE4D8F1298++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942640+x = 077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831+y = 366A0835F4F3BD7C82F44169FD5603667ADF4BE37AEEA55A0897B3F123EEE1523DB542931B4A2D6749A0D7A0F5D0E20E++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942641+x = 08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61+y = 717F0E05A4E4C312484017200292458B4D8A278A43933BC16FB1AFA0DA954BD9A002BC15B2C61DD29EAFE190F56BF17F++k = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642+x = AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7+y = C9E821B569D9D390A26167406D6D23D6070BE242D765EB831625CEEC4A0F473EF59F4E30E2817E6285BCE2846F15F1A0
+ test/P521 view
@@ -0,0 +1,207 @@+k = 1+x = 00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66+y = 011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650++k = 2+x = 00433C219024277E7E682FCB288148C282747403279B1CCC06352C6E5505D769BE97B3B204DA6EF55507AA104A3A35C5AF41CF2FA364D60FD967F43E3933BA6D783D+y = 00F4BB8CC7F86DB26700A7F3ECEEEED3F0B5C6B5107C4DA97740AB21A29906C42DBBB3E377DE9F251F6B93937FA99A3248F4EAFCBE95EDC0F4F71BE356D661F41B02++k = 3+x = 01A73D352443DE29195DD91D6A64B5959479B52A6E5B123D9AB9E5AD7A112D7A8DD1AD3F164A3A4832051DA6BD16B59FE21BAEB490862C32EA05A5919D2EDE37AD7D+y = 013E9B03B97DFA62DDD9979F86C6CAB814F2F1557FA82A9D0317D2F8AB1FA355CEEC2E2DD4CF8DC575B02D5ACED1DEC3C70CF105C9BC93A590425F588CA1EE86C0E5++k = 4+x = 0035B5DF64AE2AC204C354B483487C9070CDC61C891C5FF39AFC06C5D55541D3CEAC8659E24AFE3D0750E8B88E9F078AF066A1D5025B08E5A5E2FBC87412871902F3+y = 0082096F84261279D2B673E0178EB0B4ABB65521AEF6E6E32E1B5AE63FE2F19907F279F283E54BA385405224F750A95B85EEBB7FAEF04699D1D9E21F47FC346E4D0D++k = 5+x = 00652BF3C52927A432C73DBC3391C04EB0BF7A596EFDB53F0D24CF03DAB8F177ACE4383C0C6D5E3014237112FEAF137E79A329D7E1E6D8931738D5AB5096EC8F3078+y = 015BE6EF1BDD6601D6EC8A2B73114A8112911CD8FE8E872E0051EDD817C9A0347087BB6897C9072CF374311540211CF5FF79D1F007257354F7F8173CC3E8DEB090CB++k = 6+x = 01EE4569D6CDB59219532EFF34F94480D195623D30977FD71CF3981506ADE4AB01525FBCCA16153F7394E0727A239531BE8C2F66E95657F380AE23731BEDF79206B9+y = 01DE0255AD0CC64F586AE2DD270546E3B1112AABBB73DA5A808E7240A926201A8A96CAB72D0E56648C9DF96C984DE274F2203DC7B8B55CA0DADE1EACCD7858D44F17++k = 7+x = 0056D5D1D99D5B7F6346EEB65FDA0B073A0C5F22E0E8F5483228F018D2C2F7114C5D8C308D0ABFC698D8C9A6DF30DCE3BBC46F953F50FDC2619A01CEAD882816ECD4+y = 003D2D1B7D9BAAA2A110D1D8317A39D68478B5C582D02824F0DD71DBD98A26CBDE556BD0F293CDEC9E2B9523A34591CE1A5F9E76712A5DDEFC7B5C6B8BC90525251B++k = 8+x = 000822C40FB6301F7262A8348396B010E25BD4E29D8A9B003E0A8B8A3B05F826298F5BFEA5B8579F49F08B598C1BC8D79E1AB56289B5A6F4040586F9EA54AA78CE68+y = 016331911D5542FC482048FDAB6E78853B9A44F8EDE9E2C0715B5083DE610677A8F189E9C0AA5911B4BFF0BA0DF065C578699F3BA940094713538AD642F11F17801C++k = 9+x = 01585389E359E1E21826A2F5BF157156D488ED34541B988746992C4AB145B8C6B6657429E1396134DA35F3C556DF725A318F4F50BABD85CD28661F45627967CBE207+y = 002A2E618C9A8AEDF39F0B55557A27AE938E3088A654EE1CEBB6C825BA263DDB446E0D69E5756057AC840FF56ECF4ABFD87D736C2AE928880F343AA0EA86B9AD2A4E++k = 10+x = 0190EB8F22BDA61F281DFCFE7BB6721EC4CD901D879AC09AC7C34A9246B11ADA8910A2C7C178FCC263299DAA4DA9842093F37C2E411F1A8E819A87FF09A04F2F3320+y = 01EB5D96B8491614BA9DBAEAB3B0CA2BA760C2EEB2144251B20BA97FD78A62EF62D2BF5349D44D9864BB536F6163DC57EBEFF3689639739FAA172954BC98135EC759++k = 11+x = 008A75841259FDEDFF546F1A39573B4315CFED5DC7ED7C17849543EF2C54F2991652F3DBC5332663DA1BD19B1AEBE3191085015C024FA4C9A902ECC0E02DDA0CDB9A+y = 0096FB303FCBBA2129849D0CA877054FB2293ADD566210BD0493ED2E95D4E0B9B82B1BC8A90E8B42A4AB3892331914A95336DCAC80E3F4819B5D58874F92CE48C808++k = 12+x = 01C0D9DCEC93F8221C5DE4FAE9749C7FDE1E81874157958457B6107CF7A5967713A644E90B7C3FB81B31477FEE9A60E938013774C75C530928B17BE69571BF842D8C+y = 014048B5946A4927C0FE3CE1D103A682CA4763FE65AB71494DA45E404ABF6A17C097D6D18843D86FCDB6CC10A6F951B9B630884BA72224F5AE6C79E7B1A3281B17F0++k = 13+x = 007E3E98F984C396AD9CD7865D2B4924861A93F736CDE1B4C2384EEDD2BEAF5B866132C45908E03C996A3550A5E79AB88EE94BEC3B00AB38EFF81887848D32FBCDA7+y = 0108EE58EB6D781FEDA91A1926DAA3ED5A08CED50A386D5421C69C7A67AE5C1E212AC1BD5D5838BC763F26DFDD351CBFBBC36199EAAF9117E9F7291A01FB022A71C9++k = 14+x = 01875BC7DC551B1B65A9E1B8CCFAAF84DED1958B401494116A2FD4FB0BABE0B3199974FC06C8B897222D79DF3E4B7BC744AA6767F6B812EFBF5D2C9E682DD3432D74+y = 005CA4923575DACB5BD2D66290BBABB4BDFB8470122B8E51826A0847CE9B86D7ED62D07781B1B4F3584C11E89BF1D133DC0D5B690F53A87C84BE41669F852700D54A++k = 15+x = 006B6AD89ABCB92465F041558FC546D4300FB8FBCC30B40A0852D697B532DF128E11B91CCE27DBD00FFE7875BD1C8FC0331D9B8D96981E3F92BDE9AFE337BCB8DB55+y = 01B468DA271571391D6A7CE64D2333EDBF63DF0496A9BAD20CBA4B62106997485ED57E9062C899470A802148E2232C96C99246FD90CC446ABDD956343480A1475465++k = 16+x = 01D17D10D8A89C8AD05DDA97DA26AC743B0B2A87F66192FD3F3DD632F8D20B188A52943FF18861CA00A0E5965DA7985630DF0DBF5C8007DCDC533A6C508F81A8402F+y = 007A37343C582D77001FC714B18D3D3E69721335E4C3B800D50EC7CA30C94B6B82C1C182E1398DB547AA0B3075AC9D9988529E3004D28D18633352E272F89BC73ABE++k = 17+x = 01B00DDB707F130EDA13A0B874645923906A99EE9E269FA2B3B4D66524F269250858760A69E674FE0287DF4E799B5681380FF8C3042AF0D1A41076F817A853110AE0+y = 0085683F1D7DB16576DBC111D4E4AEDDD106B799534CF69910A98D68AC2B22A1323DF9DA564EF6DD0BF0D2F6757F16ADF420E6905594C2B755F535B9CB7C70E64647++k = 18+x = 01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D6EDBB8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D+y = 010D06E999885B63535DE3E74D33D9E63D024FB07CE0D196F2552C8E4A00AC84C044234AEB201F7A9133915D1B4B45209B9DA79FE15B19F84FD135D841E2D8F9A86A++k = 19+x = 00998DCCE486419C3487C0F948C2D5A1A07245B77E0755DF547EFFF0ACDB3790E7F1FA3B3096362669679232557D7A45970DFECF431E725BBDE478FF0B2418D6A19B+y = 0137D5DA0626A021ED5CC3942497535B245D67D28AEE2B7BCF4ACC50EEE36545772773AD963FF2EB8CF9B0EC39991631C377F5A4D89EA9FBFE44A9091A695BFD0575++k = 20+x = 018BDD7F1B889598A4653DEEAE39CC6F8CC2BD767C2AB0D93FB12E968FBED342B51709506339CB1049CB11DD48B9BDB3CD5CAD792E43B74E16D8E2603BFB11B0344F+y = 00C5AADBE63F68CA5B6B6908296959BF0AF89EE7F52B410B9444546C550952D311204DA3BDDDC6D4EAE7EDFAEC1030DA8EF837CCB22EEE9CFC94DD3287FED0990F94++k = 112233445566778899+x = 01650048FBD63E8C30B305BF36BD7643B91448EF2206E8A0CA84A140789A99B0423A0A2533EA079CA7E049843E69E5FA2C25A163819110CEC1A30ACBBB3A422A40D8+y = 010C9C64A0E0DB6052DBC5646687D06DECE5E9E0703153EFE9CB816FE025E85354D3C5F869D6DB3F4C0C01B5F97919A5E72CEEBE03042E5AA99112691CFFC2724828++k = 112233445566778899112233445566778899+x = 017E1370D39C9C63925DAEEAC571E21CAAF60BD169191BAEE8352E0F54674443B29786243564ABB705F6FC0FE5FC5D3F98086B67CA0BE7AC8A9DEC421D9F1BC6B37F+y = 01CD559605EAD19FBD99E83600A6A81A0489E6F20306EE0789AE00CE16A6EFEA2F42F7534186CF1C60DF230BD9BCF8CB95E5028AD9820B2B1C0E15597EE54C4614A6++k = 1769805277975163035253775930842367129093741786725376786007349332653323812656658291413435033257677579095366632521448854141275926144187294499863933403633025023+x = 00B45CB84651C9D4F08858B867F82D816E84E94FE4CAE3DA5F65E420B08398D0C5BF019253A6C26D20671BDEF0B8E6C1D348A4B0734687F73AC6A4CBB2E085C68B3F+y = 01C84942BBF538903062170A4BA8B3410D385719BA2037D29CA5248BFCBC8478220FEC79244DCD45D31885A1764DEE479CE20B12CEAB62F9001C7AA4282CE4BE7F56++k = 104748400337157462316262627929132596317243790506798133267698218707528750292682889221414310155907963824712114916552440160880550666043997030661040721887239+x = 01CCEF4CDA108CEBE6568820B54A3CA3A3997E4EF0EDA6C350E7ED3DBB1861EDD80181C650CEBE5440FEBA880F9C8A7A86F8B82659794F6F5B88E501E5DD84E65D7E+y = 01026565F8B195D03C3F6139C3A63EAA1C29F7090AB2A8F75027939EC05109035F1B38E6C508E0C14CE53AB7E2DA33AA28140EDBF3964862FB157119517454E60F07++k = 6703903865078345888141381651430168039496664077350965054288133126549307058741788671148197429777343936466127575938031786147409472627479702469884214509568000+x = 00C1002DC2884EEDADB3F9B468BBEBD55980799852C506D37271FFCD006919DB3A96DF8FE91EF6ED4B9081B1809E8F2C2B28AF5FCBF524147C73CB0B913D6FAB0995+y = 01614E8A62C8293DD2AA6EF27D30974A4FD185019FA8EF4F982DA48698CECF706581F69EE9ED67A9C231EC9D0934D0F674646153273BCBB345E923B1EC1386A1A4AD++k = 1675925643682395305404517165643562251880026958780896531698856737024179880343339878336382412050263431942974939646683480906434632963478257639757341102436352+x = 010ED3E085ECDE1E66874286B5D5642B9D37853A026A0A025C7B84936E2ECEEC5F342E14C80C79CCF814D5AD085C5303F2823251F2B9276F88C9D7A43E387EBD87AC+y = 01BE399A7666B29E79BBF3D277531A97CE05CAC0B49BECE4781E7AEE0D6E80FEE883C76E9F08453DC1ADE4E49300F3D56FEE6A1510DA1B1F12EEAA39A05AA0508119++k = 12785133382149415221402495202586701798620696169446772599038235721862338692190156163951558963856959059232381602864743924427451786769515154396810706943+x = 013070A29B059D317AF37089E40FCB135868F52290EFF3E9F3E32CDADCA18EA234D8589C665A4B8E3D0714DE004A419DEA7091A3BBA97263C438FE9413AA598FD4A5+y = 00238A27FD9E5E7324C8B538EF2E334B71AC2611A95F42F4F2544D8C4A65D2A32A8BAFA15EFD4FC2BD8AB2B0C51F65B680879589F4D5FE8A84CEB17A2E8D3587F011++k = 214524875832249255872206855495734426889477529336261655255492425273322727861341825677722947375406711676372335314043071600934941615185418540320233184489636351+x = 01A3D88799878EC74E66FF1AD8C7DFA9A9B4445A17F0810FF8189DD27AE3B6C580D352476DBDAEB08D7DA0DE3866F7C7FDBEBB8418E19710F1F7AFA88C22280B1404+y = 00B39703D2053EC7B8812BDFEBFD81B4CB76F245FE535A1F1E46801C35DE03C15063A99A203981529C146132863CA0E68544D0F0A638D8A2859D82B4DD266F27C3AE++k = 51140486275567859131139077890835526884648461857823088348651153840508287621366854506831244746531272246620295123104269565867055949378266395604768784399+x = 01D16B4365DEFE6FD356DC1F31727AF2A32C7E86C5AE87ED2950A08BC8653F203C7F7860E80F95AA27C93EA76E8CD094127B15ED42CC5F96DC0A0F9A1C1E31D0D526+y = 006E3710A0F9366E0BB8A14FFE8EBC2722EECF4A123EC9BA98DCCCA335D6FAFD289DC69FD90903C9AC982FEB46DF93F03A7C8C9549D32C1C386D17F37340E63822A8++k = 6651529716025206881035279952881520627841152247212784520914425039312606120198879080839643311347169019249080198239408356563413447402270445462102068592377843+x = 01B1220F67C985E9FC9C588C0C86BB16E6FE4CC11E168A98D701AE4670724B3D030ED9965FADF4207C7A1BE9BE0F40DEF2BBFFF0C7EABCB5B42526CE1D3CAA468F52+y = 006CDAD2860F6D2C37159A5A866D11605F2E7D87430DCFE6E6816AB6423CD9003CA6F2527B9C2A2483C541D456C963D18A0D2A46E158CB2A44C0BF42D562881FB748++k = 3224551824613232232537680077946818660156835288778087344805370397811379731631671254853846826682273677870214778462237171365140390183770226853329363961324241919+x = 00F25E545213C8C074BE38A0612EA9B66336B14A874372548D9716392DFA31CD0D13E94F86CD48B8D43B80B5299144E01245C873B39F6AC6C4FB397746AF034AD67C+y = 01733ABB21147CC27E35F41FAF40290AFD1EEB221D983FFABBD88E5DC8776450A409EACDC1BCA2B9F517289C68645BB96781808FEAE42573C2BB289F16E2AECECE17++k = 12486613128442885430380874043991285080254917488396284953815149251315412600634581539066663092297612040669978017623587752845409653167277021864132608+x = 0172CD22CBE0634B6BFEE24BB1D350F384A945ED618ECAD48AADC6C1BC0DCC107F0FFE9FE14DC929F90153F390C25BE5D3A73A56F9ACCB0C72C768753869732D0DC4+y = 00D249CFB570DA4CC48FB5426A928B43D7922F787373B6182408FBC71706E7527E8414C79167F3C999FF58DE352D238F1FE7168C658D338F72696F2F889A97DE23C5++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005429+x = 018BDD7F1B889598A4653DEEAE39CC6F8CC2BD767C2AB0D93FB12E968FBED342B51709506339CB1049CB11DD48B9BDB3CD5CAD792E43B74E16D8E2603BFB11B0344F+y = 013A552419C09735A49496F7D696A640F50761180AD4BEF46BBBAB93AAF6AD2CEEDFB25C4222392B1518120513EFCF257107C8334DD11163036B22CD78012F66F06B++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005430+x = 00998DCCE486419C3487C0F948C2D5A1A07245B77E0755DF547EFFF0ACDB3790E7F1FA3B3096362669679232557D7A45970DFECF431E725BBDE478FF0B2418D6A19B+y = 00C82A25F9D95FDE12A33C6BDB68ACA4DBA2982D7511D48430B533AF111C9ABA88D88C5269C00D1473064F13C666E9CE3C880A5B2761560401BB56F6E596A402FA8A++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005431+x = 01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D6EDBB8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D+y = 00F2F9166677A49CACA21C18B2CC2619C2FDB04F831F2E690DAAD371B5FF537B3FBBDCB514DFE0856ECC6EA2E4B4BADF646258601EA4E607B02ECA27BE1D27065795++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005432+x = 01B00DDB707F130EDA13A0B874645923906A99EE9E269FA2B3B4D66524F269250858760A69E674FE0287DF4E799B5681380FF8C3042AF0D1A41076F817A853110AE0+y = 017A97C0E2824E9A89243EEE2B1B51222EF94866ACB30966EF56729753D4DD5ECDC20625A9B10922F40F2D098A80E9520BDF196FAA6B3D48AA0ACA4634838F19B9B8++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005433+x = 01D17D10D8A89C8AD05DDA97DA26AC743B0B2A87F66192FD3F3DD632F8D20B188A52943FF18861CA00A0E5965DA7985630DF0DBF5C8007DCDC533A6C508F81A8402F+y = 0185C8CBC3A7D288FFE038EB4E72C2C1968DECCA1B3C47FF2AF13835CF36B4947D3E3E7D1EC6724AB855F4CF8A53626677AD61CFFB2D72E79CCCAD1D8D076438C541++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005434+x = 006B6AD89ABCB92465F041558FC546D4300FB8FBCC30B40A0852D697B532DF128E11B91CCE27DBD00FFE7875BD1C8FC0331D9B8D96981E3F92BDE9AFE337BCB8DB55+y = 004B9725D8EA8EC6E2958319B2DCCC12409C20FB6956452DF345B49DEF9668B7A12A816F9D3766B8F57FDEB71DDCD369366DB9026F33BB954226A9CBCB7F5EB8AB9A++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005435+x = 01875BC7DC551B1B65A9E1B8CCFAAF84DED1958B401494116A2FD4FB0BABE0B3199974FC06C8B897222D79DF3E4B7BC744AA6767F6B812EFBF5D2C9E682DD3432D74+y = 01A35B6DCA8A2534A42D299D6F44544B42047B8FEDD471AE7D95F7B831647928129D2F887E4E4B0CA7B3EE17640E2ECC23F2A496F0AC57837B41BE99607AD8FF2AB5++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005436+x = 007E3E98F984C396AD9CD7865D2B4924861A93F736CDE1B4C2384EEDD2BEAF5B866132C45908E03C996A3550A5E79AB88EE94BEC3B00AB38EFF81887848D32FBCDA7+y = 00F711A7149287E01256E5E6D9255C12A5F7312AF5C792ABDE3963859851A3E1DED53E42A2A7C74389C0D92022CAE340443C9E6615506EE81608D6E5FE04FDD58E36++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005437+x = 01C0D9DCEC93F8221C5DE4FAE9749C7FDE1E81874157958457B6107CF7A5967713A644E90B7C3FB81B31477FEE9A60E938013774C75C530928B17BE69571BF842D8C+y = 00BFB74A6B95B6D83F01C31E2EFC597D35B89C019A548EB6B25BA1BFB54095E83F68292E77BC2790324933EF5906AE4649CF77B458DDDB0A519386184E5CD7E4E80F++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005438+x = 008A75841259FDEDFF546F1A39573B4315CFED5DC7ED7C17849543EF2C54F2991652F3DBC5332663DA1BD19B1AEBE3191085015C024FA4C9A902ECC0E02DDA0CDB9A+y = 016904CFC03445DED67B62F35788FAB04DD6C522A99DEF42FB6C12D16A2B1F4647D4E43756F174BD5B54C76DCCE6EB56ACC923537F1C0B7E64A2A778B06D31B737F7++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005439+x = 0190EB8F22BDA61F281DFCFE7BB6721EC4CD901D879AC09AC7C34A9246B11ADA8910A2C7C178FCC263299DAA4DA9842093F37C2E411F1A8E819A87FF09A04F2F3320+y = 0014A26947B6E9EB456245154C4F35D4589F3D114DEBBDAE4DF4568028759D109D2D40ACB62BB2679B44AC909E9C23A814100C9769C68C6055E8D6AB4367ECA138A6++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005440+x = 01585389E359E1E21826A2F5BF157156D488ED34541B988746992C4AB145B8C6B6657429E1396134DA35F3C556DF725A318F4F50BABD85CD28661F45627967CBE207+y = 01D5D19E736575120C60F4AAAA85D8516C71CF7759AB11E3144937DA45D9C224BB91F2961A8A9FA8537BF00A9130B54027828C93D516D777F0CBC55F15794652D5B1++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005441+x = 000822C40FB6301F7262A8348396B010E25BD4E29D8A9B003E0A8B8A3B05F826298F5BFEA5B8579F49F08B598C1BC8D79E1AB56289B5A6F4040586F9EA54AA78CE68+y = 009CCE6EE2AABD03B7DFB7025491877AC465BB0712161D3F8EA4AF7C219EF988570E76163F55A6EE4B400F45F20F9A3A879660C456BFF6B8ECAC7529BD0EE0E87FE3++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005442+x = 0056D5D1D99D5B7F6346EEB65FDA0B073A0C5F22E0E8F5483228F018D2C2F7114C5D8C308D0ABFC698D8C9A6DF30DCE3BBC46F953F50FDC2619A01CEAD882816ECD4+y = 01C2D2E48264555D5EEF2E27CE85C6297B874A3A7D2FD7DB0F228E242675D93421AA942F0D6C321361D46ADC5CBA6E31E5A061898ED5A2210384A3947436FADADAE4++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005443+x = 01EE4569D6CDB59219532EFF34F94480D195623D30977FD71CF3981506ADE4AB01525FBCCA16153F7394E0727A239531BE8C2F66E95657F380AE23731BEDF79206B9+y = 0021FDAA52F339B0A7951D22D8FAB91C4EEED554448C25A57F718DBF56D9DFE575693548D2F1A99B7362069367B21D8B0DDFC238474AA35F2521E1533287A72BB0E8++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005444+x = 00652BF3C52927A432C73DBC3391C04EB0BF7A596EFDB53F0D24CF03DAB8F177ACE4383C0C6D5E3014237112FEAF137E79A329D7E1E6D8931738D5AB5096EC8F3078+y = 00A41910E42299FE291375D48CEEB57EED6EE327017178D1FFAE1227E8365FCB8F7844976836F8D30C8BCEEABFDEE30A00862E0FF8DA8CAB0807E8C33C17214F6F34++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005445+x = 0035B5DF64AE2AC204C354B483487C9070CDC61C891C5FF39AFC06C5D55541D3CEAC8659E24AFE3D0750E8B88E9F078AF066A1D5025B08E5A5E2FBC87412871902F3+y = 017DF6907BD9ED862D498C1FE8714F4B5449AADE5109191CD1E4A519C01D0E66F80D860D7C1AB45C7ABFADDB08AF56A47A114480510FB9662E261DE0B803CB91B2F2++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005446+x = 01A73D352443DE29195DD91D6A64B5959479B52A6E5B123D9AB9E5AD7A112D7A8DD1AD3F164A3A4832051DA6BD16B59FE21BAEB490862C32EA05A5919D2EDE37AD7D+y = 00C164FC4682059D2226686079393547EB0D0EAA8057D562FCE82D0754E05CAA3113D1D22B30723A8A4FD2A5312E213C38F30EFA36436C5A6FBDA0A7735E11793F1A++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005447+x = 00433C219024277E7E682FCB288148C282747403279B1CCC06352C6E5505D769BE97B3B204DA6EF55507AA104A3A35C5AF41CF2FA364D60FD967F43E3933BA6D783D+y = 010B44733807924D98FF580C1311112C0F4A394AEF83B25688BF54DE5D66F93BD2444C1C882160DAE0946C6C805665CDB70B1503416A123F0B08E41CA9299E0BE4FD++k = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005448+x = 00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66+y = 00E7C6D6958765C43FFBA375A04BD382E426670ABBB6A864BB97E85042E8D8C199D368118D66A10BD9BF3AAF46FEC052F89ECAC38F795D8D3DBF77416B89602E99AF
+ test/Tests.hs view
@@ -0,0 +1,128 @@+-----------------------------------------------------------------------------+-- |+-- Module : Tests+-- Copyright : (c) Marcel Fourné 20[09..19]+-- License : BSD3+-- Maintainer : Marcel Fourné (haskell@marcelfourne.de)+--+-- Test module+--+-----------------------------------------------------------------------------+{-# OPTIONS_GHC -O2 -feager-blackholing #-}++module Tests (tests) where+import Distribution.TestSuite+import Crypto.ECC.Weierstrass.Internal.Curvemath+import Crypto.ECC.Weierstrass.StandardCurves+import Crypto.ECC.Weierstrass.ECDSA as N+import Numeric+import qualified Data.ByteString.Char8 as C8+import qualified Data.ByteString as BS+import qualified Data.ByteString.Base16 as BS16+import qualified Crypto.ECC.Ed25519.Sign as ED+import qualified Crypto.ECC.Ed25519.Internal.Ed25519 as EDi++tests :: IO [Test]+tests = do+ contentP192 <- readFile "test/P192"+ contentP224 <- readFile "test/P224"+ contentP256 <- readFile "test/P256"+ contentP384 <- readFile "test/P384"+ contentP521 <- readFile "test/P521"+ contentEd25519 <- readFile "test/sign.input"+ let nistp192 = Group { groupName = "NIST P192"+ , concurrently = True+ , groupTests =+ map (test "NIST P192" (\x -> affine (ECi (stdc_l p192) (stdc_b p192) (stdc_p p192) (stdc_r p192)) $ pmul (ECi (stdc_l p192) (stdc_b p192) (stdc_p p192) (stdc_r p192)) (ECPp (stdc_xp p192) (stdc_yp p192) 1) x)) $ parse contentP192+ }+ nistp224 = Group { groupName = "NIST P224"+ , concurrently = True+ , groupTests =+ map (test "NIST P224" (\x -> affine (ECi (stdc_l p224) (stdc_b p224) (stdc_p p224) (stdc_r p224)) $ pmul (ECi (stdc_l p224) (stdc_b p224) (stdc_p p224) (stdc_r p224)) (ECPp (stdc_xp p224) (stdc_yp p224) 1) x)) $ parse contentP224+ }+ nistp256 = Group { groupName = "NIST P256"+ , concurrently = True+ , groupTests =+ map (test "NIST P256" (\x -> affine (ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)) $ pmul (ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)) (ECPp (stdc_xp p256) (stdc_yp p256) 1) x)) $ parse contentP256+ }+ nistp384 = Group { groupName = "NIST P384"+ , concurrently = True+ , groupTests =+ map (test "NIST P384" (\x -> affine (ECi (stdc_l p384) (stdc_b p384) (stdc_p p384) (stdc_r p384)) $ pmul (ECi (stdc_l p384) (stdc_b p384) (stdc_p p384) (stdc_r p384)) (ECPp (stdc_xp p384) (stdc_yp p384) 1) x)) $ parse contentP384+ }+ nistp521 = Group { groupName = "NIST P521"+ , concurrently = True+ , groupTests =+ map (test "NIST P521" (\x -> affine (ECi (stdc_l p521) (stdc_b p521) (stdc_p p521) (stdc_r p521)) $ pmul (ECi (stdc_l p521) (stdc_b p521) (stdc_p p521) (stdc_r p521)) (ECPp (stdc_xp p521) (stdc_yp p521) 1) x)) $ parse contentP521+ }+ ed25519 = Group { groupName = "Ed25519"+ , concurrently = True+ , groupTests = map (testEd25519 . C8.pack) $ lines contentEd25519+ }+ ecdsa = Group { groupName = "Ed25519"+ , concurrently = True+ , groupTests = [testECDSA 6196826090020524094612681716217090709820303001652178894146139893013814408531]+ }+ return [ nistp192+ , nistp224+ , nistp256+ , nistp384+ , nistp521+ , ed25519+ , ecdsa+ ]++parse :: String -> [(Integer,Integer, Integer)]+parse content = let l = lines content+ fl = filter (/= "") l+ ex :: [String] -> [(Integer,Integer, Integer)]+ ex (k:x:y:ls) = let k' = read (drop 4 k)+ x' = fst $ head $ readHex (drop 4 x)+ y' = fst $ head $ readHex (drop 4 y)+ in (k',x',y'):(ex ls)+ ex [] = []+ ex _ = error "parse failed"+ in ex fl++test :: String -> (Integer -> (Integer,Integer)) -> (Integer, Integer, Integer) -> Test+test thename f (k,x,y) = let instanz = TestInstance { run = return $ if f k == (x,y) then Finished Pass else Finished $ Fail "fehlgeschlagen"+ , name = thename ++ " with k = " ++ (show k)+ , tags = []+ , options = []+ , setOption = \_ _ -> Right instanz+ }+ in Test instanz++testECDSA :: Integer -> Test+testECDSA rand = let c1 = ECi (stdc_l p256) (stdc_b p256) (stdc_p p256) (stdc_r p256)+ p1 = ECPp (stdc_xp p256) (stdc_yp p256) 1+ privk = 93151144317885463729940025875124971369191600717633105593660251066268358953543+ pub = ECPp 49820351311576200663416054279040683857746363070013834679270516876052449262634 112699216918648906269327207660688102462037435574122213014814143327521473380783 18523244708209522220381629035092551864971849988089188687523906648093563992014+ sig = N.basicecdsa (BS.pack [0..255]) privk rand + Right (r,s) = sig+ instanz = TestInstance { run = return $ Finished $ if N.basicecdsaVerify pub (r,s) (BS.pack [0..255]) then Pass else Fail "fehlgeschlagen"+ , name = "ECDSAp256 sign+verify" ++ " with k = " ++ (show rand)+ , tags = []+ , options = []+ , setOption = \_ _ -> Right instanz+ }+ in Test instanz+++testEd25519 :: BS.ByteString -> Test+testEd25519 line = let x = C8.split ':' line+ sk = fst $ BS16.decode $ head x+ m = fst $ BS16.decode $ x !! 2+ instanz = TestInstance { run = let mytest :: Either String ED.VerifyResult+ mytest = do+ pubkey <- ED.publickey $ EDi.SecKeyBytes sk+ sig <- ED.dsign (EDi.SecKeyBytes $ BS.take 32 sk) m+ res <- ED.dverify pubkey sig m+ pure $ Right res+ in return $ if mytest == Right (Right ED.SigOK) then Finished Pass else Finished $ Fail "fehlgeschlagen"+ , name = "Ed25519" ++ " with x = " ++ (show x) ++ " and sk = " ++ (show sk) ++ " and m = " ++ (show m)+ , tags = []+ , options = []+ , setOption = \_ _ -> Right instanz+ }+ in Test instanz
+ test/sign.input view
file too large to diff