-----------------------------------------------------------------------------
-- |
-- 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 Trustworthy #-}

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 qualified Crypto.Hash.SHA512 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 :: ByteString
-> Integer -> Integer -> Either String (Integer, Integer)
basicecdsa ByteString
bs Integer
dA Integer
k = 
  let curve :: EC Integer
curve = Int -> Integer -> Integer -> Integer -> EC Integer
ECi (StandardCurve -> Int
stdc_l StandardCurve
p256) (StandardCurve -> Integer
stdc_b StandardCurve
p256) (StandardCurve -> Integer
stdc_p StandardCurve
p256) (StandardCurve -> Integer
stdc_r StandardCurve
p256)
      bPoint :: ECPF Integer
bPoint = Integer -> Integer -> Integer -> ECPF Integer
ECPp  (StandardCurve -> Integer
stdc_xp StandardCurve
p256) (StandardCurve -> Integer
stdc_yp StandardCurve
p256) Integer
1
      order :: Integer
order = StandardCurve -> Integer
stdc_r StandardCurve
p256
      Right Integer
z = ByteString -> Either String Integer
Ed.getFPrime32 (ByteString -> Either String Integer)
-> ByteString -> Either String Integer
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
h ByteString
bs
      (Integer
x1,Integer
_) = EC Integer -> ECPF Integer -> (Integer, Integer)
forall a. EC a -> ECPF a -> (Integer, Integer)
affine EC Integer
curve (ECPF Integer -> (Integer, Integer))
-> ECPF Integer -> (Integer, Integer)
forall a b. (a -> b) -> a -> b
$ EC Integer -> ECPF Integer -> Integer -> ECPF Integer
forall a. EC a -> ECPF a -> Integer -> ECPF a
pmul EC Integer
curve ECPF Integer
bPoint Integer
k
      r :: Integer
r = Integer
x1 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
order
      s :: Integer
s = Integer -> Integer -> Integer -> Integer
FP.mulr Integer
order (Integer -> Integer -> Integer
FP.inv Integer
order Integer
k) (Integer -> Integer -> Integer
FP.add Integer
z (Integer -> Integer -> Integer -> Integer
FP.mulr Integer
order Integer
r Integer
dA))
  in if Integer
r Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0 Bool -> Bool -> Bool
&& Integer
s Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0
     then (Integer, Integer) -> Either String (Integer, Integer)
forall a b. b -> Either a b
Right (Integer
r,Integer
s)
     else String -> Either String (Integer, Integer)
forall a b. a -> Either a b
Left String
"fail"

-- | basic ECDSA verification
basicecdsaVerify :: ECPF Integer -> (Integer,Integer) -> BS.ByteString -> Bool
basicecdsaVerify :: ECPF Integer -> (Integer, Integer) -> ByteString -> Bool
basicecdsaVerify ECPF Integer
dB (Integer
r,Integer
s) ByteString
m = let curve :: EC Integer
curve =  Int -> Integer -> Integer -> Integer -> EC Integer
ECi (StandardCurve -> Int
stdc_l StandardCurve
p256) (StandardCurve -> Integer
stdc_b StandardCurve
p256) (StandardCurve -> Integer
stdc_p StandardCurve
p256) (StandardCurve -> Integer
stdc_r StandardCurve
p256)
                                  order :: Integer
order = StandardCurve -> Integer
stdc_r StandardCurve
p256
                                  bPoint :: ECPF Integer
bPoint = Integer -> Integer -> Integer -> ECPF Integer
ECPp  (StandardCurve -> Integer
stdc_xp StandardCurve
p256) (StandardCurve -> Integer
stdc_yp StandardCurve
p256) Integer
1
                                  Right Integer
z = ByteString -> Either String Integer
Ed.getFPrime32 (ByteString -> Either String Integer)
-> ByteString -> Either String Integer
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
h ByteString
m
                                  w :: Integer
w = Integer -> Integer -> Integer
FP.inv Integer
order Integer
s
                                  u1 :: Integer
u1 = Integer -> Integer -> Integer -> Integer
FP.mulr Integer
order Integer
z Integer
w
                                  u2 :: Integer
u2 = Integer -> Integer -> Integer -> Integer
FP.mulr Integer
order Integer
r Integer
w
                                  point :: ECPF Integer
point = EC Integer -> ECPF Integer -> ECPF Integer -> ECPF Integer
forall a. EC a -> ECPF a -> ECPF a -> ECPF a
padd EC Integer
curve (EC Integer -> ECPF Integer -> Integer -> ECPF Integer
forall a. EC a -> ECPF a -> Integer -> ECPF a
pmul EC Integer
curve ECPF Integer
bPoint Integer
u1) (EC Integer -> ECPF Integer -> Integer -> ECPF Integer
forall a. EC a -> ECPF a -> Integer -> ECPF a
pmul EC Integer
curve ECPF Integer
dB Integer
u2)
                                  (Integer
x1,Integer
_) = EC Integer -> ECPF Integer -> (Integer, Integer)
forall a. EC a -> ECPF a -> (Integer, Integer)
affine EC Integer
curve ECPF Integer
point
                              in Bool -> Bool
not (EC Integer -> ECPF Integer -> Bool
forall a. EC a -> ECPF a -> Bool
isinf EC Integer
curve ECPF Integer
dB) Bool -> Bool -> Bool
&& EC Integer -> ECPF Integer -> Bool
forall a. EC a -> ECPF a -> Bool
ison EC Integer
curve ECPF Integer
dB Bool -> Bool -> Bool
&& EC Integer -> ECPF Integer -> Bool
forall a. EC a -> ECPF a -> Bool
isinf EC Integer
curve (EC Integer -> ECPF Integer -> Integer -> ECPF Integer
forall a. EC a -> ECPF a -> Integer -> ECPF a
pmul EC Integer
curve ECPF Integer
dB Integer
order) Bool -> Bool -> Bool
&& Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
order Bool -> Bool -> Bool
&& Integer
s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
order Bool -> Bool -> Bool
&& Bool -> Bool
not (EC Integer -> ECPF Integer -> Bool
forall a. EC a -> ECPF a -> Bool
isinf EC Integer
curve ECPF Integer
point) Bool -> Bool -> Bool
&& Integer
x1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
r

-- | using SHA-256
h :: BS.ByteString -> BS.ByteString
-- h bs = BSL.toStrict $ H.bytestringDigest $ H.sha256 $ BSL.fromStrict bs
h :: ByteString -> ByteString
h = ByteString -> ByteString
H.hash