193 lines
7.7 KiB
Haskell
193 lines
7.7 KiB
Haskell
{-# LANGUAGE PackageImports #-}
|
|
module ECDSATesting(
|
|
ecdsaTasks
|
|
)
|
|
where
|
|
|
|
import Crypto.Hash(SHA224(..),SHA256(..),SHA384(..),SHA512(..))
|
|
import Crypto.Number.Generate(generateBetween)
|
|
import Crypto.PubKey.ECC.ECDSA(PrivateKey(..),PublicKey(..),Signature(..),signWith)
|
|
import Crypto.PubKey.ECC.Generate(generate)
|
|
import Crypto.PubKey.ECC.Prim(scalarGenerate,pointAdd,pointNegate,pointDouble,pointBaseMul,pointMul,pointAddTwoMuls)
|
|
import Crypto.PubKey.ECC.Types(Curve,CurveName(..),Point(..),common_curve,curveSizeBits,ecc_n,getCurveByName)
|
|
import "cryptonite" Crypto.Random(DRG(..),getRandomBytes,withDRG)
|
|
import qualified Data.ByteString as S
|
|
import qualified Data.Map.Strict as Map
|
|
import Math(showX,showBin)
|
|
import RFC6979(generateKStream)
|
|
import Task(Task(..))
|
|
import Utils(HashAlg(..),generateHash,runHash,showHash)
|
|
|
|
curves :: [(String, Curve)]
|
|
curves = [("P192", getCurveByName SEC_p192r1),
|
|
("P224", getCurveByName SEC_p224r1),
|
|
("P256", getCurveByName SEC_p256r1),
|
|
("P384", getCurveByName SEC_p384r1),
|
|
("P521", getCurveByName SEC_p521r1)]
|
|
|
|
negateTest :: String -> Curve -> Task
|
|
negateTest name curve = Task {
|
|
taskName = name ++ " point negation",
|
|
taskFile = "../testdata/ecc/negate/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg) =
|
|
let (scalar, drg') = withDRG drg (scalarGenerate curve)
|
|
point = pointBaseMul curve scalar
|
|
dbl = pointNegate curve point
|
|
in case (point, dbl) of
|
|
(PointO, _) -> go (memory0, drg')
|
|
(_, PointO) -> go (memory0, drg')
|
|
(Point basex basey, Point dblx dbly) ->
|
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
|
("a", showX dblx), ("b", showX dbly)]
|
|
in (res, scalar, (memory0, drg'))
|
|
|
|
doubleTest :: String -> Curve -> Task
|
|
doubleTest name curve = Task {
|
|
taskName = name ++ " point doubling",
|
|
taskFile = "../testdata/ecc/double/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg) =
|
|
let (scalar, drg') = withDRG drg (scalarGenerate curve)
|
|
point = pointBaseMul curve scalar
|
|
dbl = pointDouble curve point
|
|
in case (point, dbl) of
|
|
(PointO, _) -> go (memory0, drg')
|
|
(_, PointO) -> go (memory0, drg')
|
|
(Point basex basey, Point dblx dbly) ->
|
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
|
("a", showX dblx), ("b", showX dbly)]
|
|
in (res, scalar, (memory0, drg'))
|
|
|
|
addTest :: String -> Curve -> Task
|
|
addTest name curve = Task {
|
|
taskName = name ++ " point addition",
|
|
taskFile = "../testdata/ecc/add/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg0) =
|
|
let (scalar1, drg1) = withDRG drg0 (scalarGenerate curve)
|
|
(scalar2, drg2) = withDRG drg1 (scalarGenerate curve)
|
|
point1 = pointBaseMul curve scalar1
|
|
point2 = pointBaseMul curve scalar2
|
|
pointr = pointAdd curve point1 point2
|
|
in case (point1, point2, pointr) of
|
|
(Point x1 y1, Point x2 y2, Point xr yr) ->
|
|
let res = Map.fromList [("x", showX x1), ("y", showX y1),
|
|
("u", showX x2), ("v", showX y2),
|
|
("a", showX xr), ("b", showX yr)]
|
|
in (res, scalar1, (memory0, drg2))
|
|
_ ->
|
|
go (memory0, drg2)
|
|
|
|
scaleTest :: String -> Curve -> Task
|
|
scaleTest name curve = Task {
|
|
taskName = name ++ " point scaling",
|
|
taskFile = "../testdata/ecc/scale/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg0) =
|
|
let (scalar0, drg1) = withDRG drg0 (scalarGenerate curve)
|
|
(scalar1, drg2) = withDRG drg1 (scalarGenerate curve)
|
|
(negbs, drg3) = randomBytesGenerate 1 drg2
|
|
[negbyte] = S.unpack negbs
|
|
k = if odd negbyte then scalar1 else -scalar1
|
|
point = pointBaseMul curve scalar0
|
|
respnt = pointMul curve k point
|
|
in case (point, respnt) of
|
|
(PointO, _) -> go (memory0, drg3)
|
|
(_, PointO) -> go (memory0, drg3)
|
|
(Point basex basey, Point resx resy) ->
|
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
|
("k", showX k),
|
|
("a", showX resx), ("b", showX resy)]
|
|
in (res, scalar0, (memory0, drg3))
|
|
|
|
addScaleTest :: String -> Curve -> Task
|
|
addScaleTest name curve = Task {
|
|
taskName = name ++ " point addition of two scalings",
|
|
taskFile = "../testdata/ecc/add_scale2/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg0) =
|
|
let (scalar1, drg1) = withDRG drg0 (scalarGenerate curve)
|
|
(scalar2, drg2) = withDRG drg1 (scalarGenerate curve)
|
|
(n, drg3) = withDRG drg2 (scalarGenerate curve)
|
|
(m, drg4) = withDRG drg3 (scalarGenerate curve)
|
|
point1 = pointBaseMul curve scalar1
|
|
point2 = pointBaseMul curve scalar2
|
|
pointr = pointAddTwoMuls curve n point1 m point2
|
|
in case (point1, point2, pointr) of
|
|
(Point x1 y1, Point x2 y2, Point xr yr) ->
|
|
let res = Map.fromList [("x", showX x1), ("y", showX y1),
|
|
("p", showX x2), ("q", showX y2),
|
|
("n", showX n), ("m", showX m),
|
|
("r", showX xr), ("s", showX yr)]
|
|
in (res, scalar1, (memory0, drg4))
|
|
_ ->
|
|
go (memory0, drg4)
|
|
|
|
|
|
signTest :: String -> Curve -> Task
|
|
signTest name curve = Task {
|
|
taskName = name ++ " curve signing",
|
|
taskFile = "../testdata/ecc/sign/" ++ name ++ ".test",
|
|
taskTest = go,
|
|
taskCount = 1000
|
|
}
|
|
where
|
|
go (memory0, drg0) =
|
|
let ((pub, priv), drg1) = withDRG drg0 (generate curve)
|
|
(msg, drg2) = withDRG drg1 $ do x <- generateBetween 0 256
|
|
getRandomBytes (fromIntegral x)
|
|
(hash, drg3) = withDRG drg2 generateHash
|
|
n = ecc_n (common_curve curve)
|
|
PrivateKey _ d = priv
|
|
kStream = generateKStream hash msg d n (curveSizeBits curve)
|
|
findGoodK stream =
|
|
case stream of
|
|
[] ->
|
|
go (memory0, drg3)
|
|
(k : restks) ->
|
|
case signWith' k priv hash msg of
|
|
Nothing ->
|
|
findGoodK restks
|
|
Just sig ->
|
|
let PublicKey _ (Point x y) = pub
|
|
res = Map.fromList [("d", showX d), ("k", showX k),
|
|
("x", showX x), ("y", showX y),
|
|
("m", showBin msg), ("h", showHash hash),
|
|
("n", showBin (runHash hash msg)),
|
|
("r", showX (sign_r sig)),
|
|
("s", showX (sign_s sig))]
|
|
in (res, d, (memory0, drg3))
|
|
in findGoodK kStream
|
|
|
|
signWith' :: Integer -> PrivateKey -> HashAlg -> S.ByteString -> Maybe Signature
|
|
signWith' k priv Sha224 msg = signWith k priv SHA224 msg
|
|
signWith' k priv Sha256 msg = signWith k priv SHA256 msg
|
|
signWith' k priv Sha384 msg = signWith k priv SHA384 msg
|
|
signWith' k priv Sha512 msg = signWith k priv SHA512 msg
|
|
|
|
generateTasks :: (String, Curve) -> [Task]
|
|
generateTasks (name, curve) = [negateTest name curve,
|
|
doubleTest name curve,
|
|
addTest name curve,
|
|
scaleTest name curve,
|
|
addScaleTest name curve,
|
|
signTest name curve]
|
|
|
|
ecdsaTasks :: [Task]
|
|
ecdsaTasks = concatMap generateTasks curves |