module Crypto.PubKey.ECC.ECDSA
( module Crypto.Types.PubKey.ECDSA
, signWith
, sign
, verify
) where
import Control.Monad
import Crypto.Random
import Data.Bits (shiftR)
import Data.ByteString (ByteString)
import Crypto.Number.ModArithmetic (inverse)
import Crypto.Number.Serialize
import Crypto.Number.Generate
import Crypto.Types.PubKey.ECDSA
import Crypto.Types.PubKey.ECC
import Crypto.PubKey.HashDescr
import Crypto.PubKey.ECC.Prim
signWith :: Integer
-> PrivateKey
-> HashFunction
-> ByteString
-> Maybe Signature
signWith :: Integer
-> PrivateKey -> HashFunction -> ByteString -> Maybe Signature
signWith k :: Integer
k (PrivateKey curve :: Curve
curve d :: Integer
d) hash :: HashFunction
hash msg :: ByteString
msg = do
let z :: Integer
z = HashFunction -> ByteString -> Integer -> Integer
tHash HashFunction
hash ByteString
msg Integer
n
CurveCommon _ _ g :: Point
g n :: Integer
n _ = Curve -> CurveCommon
common_curve Curve
curve
let point :: Point
point = Curve -> Integer -> Point -> Point
pointMul Curve
curve Integer
k Point
g
Integer
r <- case Point
point of
PointO -> Maybe Integer
forall a. Maybe a
Nothing
Point x :: Integer
x _ -> Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Maybe Integer) -> Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
n
Integer
kInv <- Integer -> Integer -> Maybe Integer
inverse Integer
k Integer
n
let s :: Integer
s = Integer
kInv Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
z Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
r Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
d) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
n
Bool -> Maybe () -> Maybe ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Integer
r Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| Integer
s Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0) Maybe ()
forall a. Maybe a
Nothing
Signature -> Maybe Signature
forall (m :: * -> *) a. Monad m => a -> m a
return (Signature -> Maybe Signature) -> Signature -> Maybe Signature
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Signature
Signature Integer
r Integer
s
sign :: CPRG g => g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g)
sign :: g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g)
sign rng :: g
rng pk :: PrivateKey
pk hash :: HashFunction
hash msg :: ByteString
msg =
case Integer
-> PrivateKey -> HashFunction -> ByteString -> Maybe Signature
signWith Integer
k PrivateKey
pk HashFunction
hash ByteString
msg of
Nothing -> g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g)
forall g.
CPRG g =>
g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g)
sign g
rng' PrivateKey
pk HashFunction
hash ByteString
msg
Just sig :: Signature
sig -> (Signature
sig, g
rng')
where n :: Integer
n = CurveCommon -> Integer
ecc_n (CurveCommon -> Integer)
-> (Curve -> CurveCommon) -> Curve -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Curve -> CurveCommon
common_curve (Curve -> Integer) -> Curve -> Integer
forall a b. (a -> b) -> a -> b
$ PrivateKey -> Curve
private_curve PrivateKey
pk
(k :: Integer
k, rng' :: g
rng') = g -> Integer -> Integer -> (Integer, g)
forall g. CPRG g => g -> Integer -> Integer -> (Integer, g)
generateBetween g
rng 1 (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1)
verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool
verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool
verify _ (PublicKey _ PointO) _ _ = Bool
False
verify hash :: HashFunction
hash pk :: PublicKey
pk@(PublicKey curve :: Curve
curve q :: Point
q) (Signature r :: Integer
r s :: Integer
s) msg :: ByteString
msg
| Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< 1 Bool -> Bool -> Bool
|| Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
n Bool -> Bool -> Bool
|| Integer
s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< 1 Bool -> Bool -> Bool
|| Integer
s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
n = Bool
False
| Bool
otherwise = Bool -> (Integer -> Bool) -> Maybe Integer -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Integer
r Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
==) (Maybe Integer -> Bool) -> Maybe Integer -> Bool
forall a b. (a -> b) -> a -> b
$ do
Integer
w <- Integer -> Integer -> Maybe Integer
inverse Integer
s Integer
n
let z :: Integer
z = HashFunction -> ByteString -> Integer -> Integer
tHash HashFunction
hash ByteString
msg Integer
n
u1 :: Integer
u1 = Integer
z Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
w Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
n
u2 :: Integer
u2 = Integer
r Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
w Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
n
g' :: Point
g' = Curve -> Integer -> Point -> Point
pointMul Curve
curve Integer
u1 Point
g
q' :: Point
q' = Curve -> Integer -> Point -> Point
pointMul Curve
curve Integer
u2 Point
q
x :: Point
x = Curve -> Point -> Point -> Point
pointAdd Curve
curve Point
g' Point
q'
case Point
x of
PointO -> Maybe Integer
forall a. Maybe a
Nothing
Point x1 :: Integer
x1 _ -> Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Maybe Integer) -> Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer
x1 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
n
where n :: Integer
n = CurveCommon -> Integer
ecc_n CurveCommon
cc
g :: Point
g = CurveCommon -> Point
ecc_g CurveCommon
cc
cc :: CurveCommon
cc = Curve -> CurveCommon
common_curve (Curve -> CurveCommon) -> Curve -> CurveCommon
forall a b. (a -> b) -> a -> b
$ PublicKey -> Curve
public_curve PublicKey
pk
tHash :: HashFunction -> ByteString -> Integer -> Integer
tHash :: HashFunction -> ByteString -> Integer -> Integer
tHash hash :: HashFunction
hash m :: ByteString
m n :: Integer
n
| Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 = Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
shiftR Integer
e Int
d
| Bool
otherwise = Integer
e
where e :: Integer
e = ByteString -> Integer
os2ip (ByteString -> Integer) -> ByteString -> Integer
forall a b. (a -> b) -> a -> b
$ HashFunction
hash ByteString
m
d :: Int
d = Integer -> Int
log2 Integer
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Integer -> Int
log2 Integer
n
log2 :: Integer -> Int
log2 = Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Double -> Int) -> (Integer -> Double) -> Integer -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double -> Double
forall a. Floating a => a -> a -> a
logBase (2 :: Double) (Double -> Double) -> (Integer -> Double) -> Integer -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral