module Crypto.PubKey.DSA
( Params(..)
, Signature(..)
, PublicKey(..)
, PrivateKey(..)
, generatePrivate
, calculatePublic
, sign
, signWith
, verify
) where
import Crypto.Random
import Data.Maybe
import Data.ByteString (ByteString)
import Crypto.Number.ModArithmetic (expFast, expSafe, inverse)
import Crypto.Number.Serialize
import Crypto.Number.Generate
import Crypto.Types.PubKey.DSA
import Crypto.PubKey.HashDescr
generatePrivate :: CPRG g => g -> Params -> (PrivateNumber, g)
generatePrivate :: g -> Params -> (PrivateNumber, g)
generatePrivate rng :: g
rng (Params _ _ q :: PrivateNumber
q) = g -> PrivateNumber -> (PrivateNumber, g)
forall g. CPRG g => g -> PrivateNumber -> (PrivateNumber, g)
generateMax g
rng PrivateNumber
q
calculatePublic :: Params -> PrivateNumber -> PublicNumber
calculatePublic :: Params -> PrivateNumber -> PrivateNumber
calculatePublic (Params p :: PrivateNumber
p g :: PrivateNumber
g _) x :: PrivateNumber
x = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
expSafe PrivateNumber
g PrivateNumber
x PrivateNumber
p
signWith :: Integer
-> PrivateKey
-> HashFunction
-> ByteString
-> Maybe Signature
signWith :: PrivateNumber
-> PrivateKey -> HashFunction -> ByteString -> Maybe Signature
signWith k :: PrivateNumber
k pk :: PrivateKey
pk hash :: HashFunction
hash msg :: ByteString
msg
| PrivateNumber
r PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| PrivateNumber
s PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = Maybe Signature
forall a. Maybe a
Nothing
| Bool
otherwise = Signature -> Maybe Signature
forall a. a -> Maybe a
Just (Signature -> Maybe Signature) -> Signature -> Maybe Signature
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Signature
Signature PrivateNumber
r PrivateNumber
s
where
(Params p :: PrivateNumber
p g :: PrivateNumber
g q :: PrivateNumber
q) = PrivateKey -> Params
private_params PrivateKey
pk
x :: PrivateNumber
x = PrivateKey -> PrivateNumber
private_x PrivateKey
pk
kInv :: PrivateNumber
kInv = Maybe PrivateNumber -> PrivateNumber
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe PrivateNumber -> PrivateNumber)
-> Maybe PrivateNumber -> PrivateNumber
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
inverse PrivateNumber
k PrivateNumber
q
hm :: PrivateNumber
hm = ByteString -> PrivateNumber
os2ip (ByteString -> PrivateNumber) -> ByteString -> PrivateNumber
forall a b. (a -> b) -> a -> b
$ HashFunction
hash ByteString
msg
r :: PrivateNumber
r = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
expSafe PrivateNumber
g PrivateNumber
k PrivateNumber
p PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
q
s :: PrivateNumber
s = (PrivateNumber
kInv PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* (PrivateNumber
hm PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
+ PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
r)) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
q
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 PrivateNumber
-> PrivateKey -> HashFunction -> ByteString -> Maybe Signature
signWith PrivateNumber
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 (Params _ _ q :: PrivateNumber
q) = PrivateKey -> Params
private_params PrivateKey
pk
(k :: PrivateNumber
k, rng' :: g
rng') = g -> PrivateNumber -> (PrivateNumber, g)
forall g. CPRG g => g -> PrivateNumber -> (PrivateNumber, g)
generateMax g
rng PrivateNumber
q
verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool
verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool
verify hash :: HashFunction
hash pk :: PublicKey
pk (Signature r :: PrivateNumber
r s :: PrivateNumber
s) m :: ByteString
m
| PrivateNumber
r PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 Bool -> Bool -> Bool
|| PrivateNumber
r PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
>= PrivateNumber
q Bool -> Bool -> Bool
|| PrivateNumber
s PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 Bool -> Bool -> Bool
|| PrivateNumber
s PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
>= PrivateNumber
q = Bool
False
| Bool
otherwise = PrivateNumber
v PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
r
where (Params p :: PrivateNumber
p g :: PrivateNumber
g q :: PrivateNumber
q) = PublicKey -> Params
public_params PublicKey
pk
y :: PrivateNumber
y = PublicKey -> PrivateNumber
public_y PublicKey
pk
hm :: PrivateNumber
hm = ByteString -> PrivateNumber
os2ip (ByteString -> PrivateNumber) -> ByteString -> PrivateNumber
forall a b. (a -> b) -> a -> b
$ HashFunction
hash ByteString
m
w :: PrivateNumber
w = Maybe PrivateNumber -> PrivateNumber
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe PrivateNumber -> PrivateNumber)
-> Maybe PrivateNumber -> PrivateNumber
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
inverse PrivateNumber
s PrivateNumber
q
u1 :: PrivateNumber
u1 = (PrivateNumber
hmPrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
*PrivateNumber
w) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
q
u2 :: PrivateNumber
u2 = (PrivateNumber
rPrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
*PrivateNumber
w) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
q
v :: PrivateNumber
v = ((PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
expFast PrivateNumber
g PrivateNumber
u1 PrivateNumber
p) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* (PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
expFast PrivateNumber
y PrivateNumber
u2 PrivateNumber
p)) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
p PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
q