{-# 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
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"
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
h :: BS.ByteString -> BS.ByteString
h bs = BSL.toStrict $ H.bytestringDigest $ H.sha256 $ BSL.fromStrict bs