{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- | A key evolving signatures implementation.
--
-- It is a naive recursive implementation of the sum composition from
-- section 3.1 of the \"MMM\" paper:
--
-- /Composition and Efficiency Tradeoffs for Forward-Secure Digital Signatures/
-- By Tal Malkin, Daniele Micciancio and Sara Miner
-- <https://eprint.iacr.org/2001/034>
--
-- Specfically we do the binary sum composition directly as in the paper, and
-- then use that in a nested\/recursive fashion to construct a 7-level deep
-- binary tree version.
--
-- This relies on "Cardano.Crypto.KES.CompactSingle" for the base case.
--
-- Compared to the implementation in 'Cardano.Crypto.KES.Sum', this flavor
-- stores only one VerKey in the branch node.
--
-- Consider the following Merkle tree:
--
-- @
--       (A)
--      /   \
--   (B)     (C)
--   / \     / \
-- (D) (E) (F) (G)
--      ^
--  0   1   2   3
-- @
--
-- The caret points at leaf node E, indicating that the current period is 1.
-- The signatures for leaf nodes D through G all contain their respective
-- DSIGN keys; the signature for branch node B however only holds the signature
-- for node E, and the VerKey for node D. It can reconstruct its own VerKey
-- from these two. The signature for branch node A (the root node), then, only
-- contains the VerKey for node C, and the signature for node B. In other
-- words, the number of individual hashes to be stored equals the depth of the
-- Merkle tree. Compare that to the older, naive 'SumKES', where each branch
-- node stores two VerKeys: here, the number of keys to store is the depth of
-- the tree times two.
--
-- Note that when we verify such a signature, we need to also compare the
-- ultimate VerKey at the root against the one passed in externally, because
-- all VerKeys until that point have been derived from the (user-supplied, so
-- untrusted) signature. But we only need to do this once, at the tree root,
-- so we split up the verification into two parts: verifying a signature
-- against its embedded VerKey, and comparing that VerKey against the
-- externally supplied target key.
module Cardano.Crypto.KES.CompactSum (
    CompactSumKES
  , VerKeyKES (..)
  , SignKeyKES (..)
  , SigKES (..)

    -- * Type aliases for powers of binary sums
  , CompactSum0KES
  , CompactSum1KES
  , CompactSum2KES
  , CompactSum3KES
  , CompactSum4KES
  , CompactSum5KES
  , CompactSum6KES
  , CompactSum7KES
  ) where

import           Data.Proxy (Proxy(..))
import           Data.Typeable (Typeable)
import           GHC.Generics (Generic)
import qualified Data.ByteString as BS
import           Control.Monad (guard)
import           NoThunks.Class (NoThunks)

import           Cardano.Binary (FromCBOR (..), ToCBOR (..))

import           Cardano.Crypto.Seed
import           Cardano.Crypto.Util
import           Cardano.Crypto.Hash.Class
import           Cardano.Crypto.KES.Class
import           Cardano.Crypto.KES.CompactSingle (CompactSingleKES)
import           Control.DeepSeq (NFData)


-- | A 2^0 period KES
type CompactSum0KES d   = CompactSingleKES d

-- | A 2^1 period KES
type CompactSum1KES d h = CompactSumKES h (CompactSum0KES d)

-- | A 2^2 period KES
type CompactSum2KES d h = CompactSumKES h (CompactSum1KES d h)

-- | A 2^3 period KES
type CompactSum3KES d h = CompactSumKES h (CompactSum2KES d h)

-- | A 2^4 period KES
type CompactSum4KES d h = CompactSumKES h (CompactSum3KES d h)

-- | A 2^5 period KES
type CompactSum5KES d h = CompactSumKES h (CompactSum4KES d h)

-- | A 2^6 period KES
type CompactSum6KES d h = CompactSumKES h (CompactSum5KES d h)

-- | A 2^7 period KES
type CompactSum7KES d h = CompactSumKES h (CompactSum6KES d h)


-- | A composition of two KES schemes to give a KES scheme with the sum of
-- the time periods.
--
-- While we could do this with two independent KES schemes (i.e. two types)
-- we only need it for two instances of the same scheme, and we save
-- substantially on the size of the type and runtime dictionaries if we do it
-- this way, especially when we start applying it recursively.
--
data CompactSumKES h d

instance (NFData (SigKES d), NFData (VerKeyKES d)) =>
  NFData (SigKES (CompactSumKES h d)) where

instance (NFData (SignKeyKES d), NFData (VerKeyKES d)) =>
  NFData (SignKeyKES (CompactSumKES h d)) where

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => KESAlgorithm (CompactSumKES h d) where

    type SeedSizeKES (CompactSumKES h d) = SeedSizeKES d

    --
    -- Key and signature types
    --

    -- | From Section 3,1:
    --
    -- The verification key @vk@ for the sum scheme is the hash of the
    -- verification keys @vk_0, vk_1@ of the two constituent schemes.
    --
    newtype VerKeyKES (CompactSumKES h d) =
              VerKeyCompactSumKES (Hash h (VerKeyKES d, VerKeyKES d))
        deriving (forall x.
 VerKeyKES (CompactSumKES h d)
 -> Rep (VerKeyKES (CompactSumKES h d)) x)
-> (forall x.
    Rep (VerKeyKES (CompactSumKES h d)) x
    -> VerKeyKES (CompactSumKES h d))
-> Generic (VerKeyKES (CompactSumKES h d))
forall x.
Rep (VerKeyKES (CompactSumKES h d)) x
-> VerKeyKES (CompactSumKES h d)
forall x.
VerKeyKES (CompactSumKES h d)
-> Rep (VerKeyKES (CompactSumKES h d)) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall h d x.
Rep (VerKeyKES (CompactSumKES h d)) x
-> VerKeyKES (CompactSumKES h d)
forall h d x.
VerKeyKES (CompactSumKES h d)
-> Rep (VerKeyKES (CompactSumKES h d)) x
$cto :: forall h d x.
Rep (VerKeyKES (CompactSumKES h d)) x
-> VerKeyKES (CompactSumKES h d)
$cfrom :: forall h d x.
VerKeyKES (CompactSumKES h d)
-> Rep (VerKeyKES (CompactSumKES h d)) x
Generic
        deriving newtype VerKeyKES (CompactSumKES h d) -> ()
(VerKeyKES (CompactSumKES h d) -> ())
-> NFData (VerKeyKES (CompactSumKES h d))
forall a. (a -> ()) -> NFData a
forall h d. VerKeyKES (CompactSumKES h d) -> ()
rnf :: VerKeyKES (CompactSumKES h d) -> ()
$crnf :: forall h d. VerKeyKES (CompactSumKES h d) -> ()
NFData

    -- | From Figure 3: @(sk_0, r_1, vk_0, vk_1)@
    --
    data SignKeyKES (CompactSumKES h d) =
           SignKeyCompactSumKES !(SignKeyKES d)
                         !Seed
                         !(VerKeyKES d)
                         !(VerKeyKES d)
        deriving (forall x.
 SignKeyKES (CompactSumKES h d)
 -> Rep (SignKeyKES (CompactSumKES h d)) x)
-> (forall x.
    Rep (SignKeyKES (CompactSumKES h d)) x
    -> SignKeyKES (CompactSumKES h d))
-> Generic (SignKeyKES (CompactSumKES h d))
forall x.
Rep (SignKeyKES (CompactSumKES h d)) x
-> SignKeyKES (CompactSumKES h d)
forall x.
SignKeyKES (CompactSumKES h d)
-> Rep (SignKeyKES (CompactSumKES h d)) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall h d x.
Rep (SignKeyKES (CompactSumKES h d)) x
-> SignKeyKES (CompactSumKES h d)
forall h d x.
SignKeyKES (CompactSumKES h d)
-> Rep (SignKeyKES (CompactSumKES h d)) x
$cto :: forall h d x.
Rep (SignKeyKES (CompactSumKES h d)) x
-> SignKeyKES (CompactSumKES h d)
$cfrom :: forall h d x.
SignKeyKES (CompactSumKES h d)
-> Rep (SignKeyKES (CompactSumKES h d)) x
Generic

    -- | Figure 3 gives: @(sigma, vk_0, vk_1)@ - however, we store only the
    -- \"off-side\" VK in the branch, and calculate the \"on-side\" one from
    -- the leaf VK (stored in the leaf node, see 'CompactSingleKES') and the
    -- \"off-side\" VK's along the Merkle path.
    --
    data SigKES (CompactSumKES h d) =
           SigCompactSumKES !(SigKES d) -- includes VerKeys for the Merkle subpath
                     !(VerKeyKES d)
        deriving (forall x.
 SigKES (CompactSumKES h d) -> Rep (SigKES (CompactSumKES h d)) x)
-> (forall x.
    Rep (SigKES (CompactSumKES h d)) x -> SigKES (CompactSumKES h d))
-> Generic (SigKES (CompactSumKES h d))
forall x.
Rep (SigKES (CompactSumKES h d)) x -> SigKES (CompactSumKES h d)
forall x.
SigKES (CompactSumKES h d) -> Rep (SigKES (CompactSumKES h d)) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall h d x.
Rep (SigKES (CompactSumKES h d)) x -> SigKES (CompactSumKES h d)
forall h d x.
SigKES (CompactSumKES h d) -> Rep (SigKES (CompactSumKES h d)) x
$cto :: forall h d x.
Rep (SigKES (CompactSumKES h d)) x -> SigKES (CompactSumKES h d)
$cfrom :: forall h d x.
SigKES (CompactSumKES h d) -> Rep (SigKES (CompactSumKES h d)) x
Generic


    --
    -- Metadata and basic key operations
    --

    algorithmNameKES :: proxy (CompactSumKES h d) -> String
algorithmNameKES proxy (CompactSumKES h d)
_ = String -> String
mungeName (Proxy d -> String
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> String
algorithmNameKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d))

    deriveVerKeyKES :: SignKeyKES (CompactSumKES h d) -> VerKeyKES (CompactSumKES h d)
deriveVerKeyKES (SignKeyCompactSumKES _ _ vk_0 vk_1) =
        Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
forall h d.
Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
VerKeyCompactSumKES ((VerKeyKES d, VerKeyKES d) -> Hash h (VerKeyKES d, VerKeyKES d)
forall d h.
(KESAlgorithm d, HashAlgorithm h) =>
(VerKeyKES d, VerKeyKES d) -> Hash h (VerKeyKES d, VerKeyKES d)
hashPairOfVKeys (VerKeyKES d
vk_0, VerKeyKES d
vk_1))

    -- The verification key in this scheme is actually a hash already
    -- however the type of hashVerKeyKES says the caller gets to choose
    -- the hash, not the implementation. So that's why we have to hash
    -- the hash here. We could alternatively provide a "key identifier"
    -- function and let the implementation choose what that is.
    hashVerKeyKES :: VerKeyKES (CompactSumKES h d)
-> Hash h (VerKeyKES (CompactSumKES h d))
hashVerKeyKES (VerKeyCompactSumKES vk) = Hash h (Hash h (VerKeyKES d, VerKeyKES d))
-> Hash h (VerKeyKES (CompactSumKES h d))
forall h a b. Hash h a -> Hash h b
castHash ((Hash h (VerKeyKES d, VerKeyKES d) -> ByteString)
-> Hash h (VerKeyKES d, VerKeyKES d)
-> Hash h (Hash h (VerKeyKES d, VerKeyKES d))
forall h a. HashAlgorithm h => (a -> ByteString) -> a -> Hash h a
hashWith Hash h (VerKeyKES d, VerKeyKES d) -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes Hash h (VerKeyKES d, VerKeyKES d)
vk)


    --
    -- Core algorithm operations
    --

    type Signable   (CompactSumKES h d) = Signable   d
    type ContextKES (CompactSumKES h d) = ContextKES d

    signKES :: ContextKES (CompactSumKES h d)
-> Period
-> a
-> SignKeyKES (CompactSumKES h d)
-> SigKES (CompactSumKES h d)
signKES ContextKES (CompactSumKES h d)
ctxt Period
t a
a (SignKeyCompactSumKES sk _r_1 vk_0 vk_1) =
        SigKES d -> VerKeyKES d -> SigKES (CompactSumKES h d)
forall h d. SigKES d -> VerKeyKES d -> SigKES (CompactSumKES h d)
SigCompactSumKES SigKES d
sigma VerKeyKES d
vk_other
      where
        (SigKES d
sigma, VerKeyKES d
vk_other)
          | Period
t Period -> Period -> Bool
forall a. Ord a => a -> a -> Bool
< Period
_T    = (ContextKES d -> Period -> a -> SignKeyKES d -> SigKES d
forall v a.
(KESAlgorithm v, Signable v a, HasCallStack) =>
ContextKES v -> Period -> a -> SignKeyKES v -> SigKES v
signKES ContextKES d
ContextKES (CompactSumKES h d)
ctxt  Period
t       a
a SignKeyKES d
sk, VerKeyKES d
vk_1)
          | Bool
otherwise = (ContextKES d -> Period -> a -> SignKeyKES d -> SigKES d
forall v a.
(KESAlgorithm v, Signable v a, HasCallStack) =>
ContextKES v -> Period -> a -> SignKeyKES v -> SigKES v
signKES ContextKES d
ContextKES (CompactSumKES h d)
ctxt (Period
t Period -> Period -> Period
forall a. Num a => a -> a -> a
- Period
_T) a
a SignKeyKES d
sk, VerKeyKES d
vk_0)

        _T :: Period
_T = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
totalPeriodsKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)

    verifyKES :: ContextKES (CompactSumKES h d)
-> VerKeyKES (CompactSumKES h d)
-> Period
-> a
-> SigKES (CompactSumKES h d)
-> Either String ()
verifyKES = ContextKES (CompactSumKES h d)
-> VerKeyKES (CompactSumKES h d)
-> Period
-> a
-> SigKES (CompactSumKES h d)
-> Either String ()
forall v a.
(OptimizedKESAlgorithm v, Signable v a, HasCallStack) =>
ContextKES v
-> VerKeyKES v -> Period -> a -> SigKES v -> Either String ()
verifyOptimizedKES

    updateKES :: ContextKES (CompactSumKES h d)
-> SignKeyKES (CompactSumKES h d)
-> Period
-> Maybe (SignKeyKES (CompactSumKES h d))
updateKES ContextKES (CompactSumKES h d)
ctx (SignKeyCompactSumKES sk r_1 vk_0 vk_1) Period
t
      | Period
tPeriod -> Period -> Period
forall a. Num a => a -> a -> a
+Period
1 Period -> Period -> Bool
forall a. Ord a => a -> a -> Bool
<  Period
_T = do SignKeyKES d
sk' <- ContextKES d -> SignKeyKES d -> Period -> Maybe (SignKeyKES d)
forall v.
(KESAlgorithm v, HasCallStack) =>
ContextKES v -> SignKeyKES v -> Period -> Maybe (SignKeyKES v)
updateKES ContextKES d
ContextKES (CompactSumKES h d)
ctx SignKeyKES d
sk Period
t
                       SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall (m :: * -> *) a. Monad m => a -> m a
return (SignKeyKES (CompactSumKES h d)
 -> Maybe (SignKeyKES (CompactSumKES h d)))
-> SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall a b. (a -> b) -> a -> b
$ SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
forall h d.
SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
SignKeyCompactSumKES SignKeyKES d
sk' Seed
r_1 VerKeyKES d
vk_0 VerKeyKES d
vk_1
      | Period
tPeriod -> Period -> Period
forall a. Num a => a -> a -> a
+Period
1 Period -> Period -> Bool
forall a. Eq a => a -> a -> Bool
== Period
_T = do let sk' :: SignKeyKES d
sk' = Seed -> SignKeyKES d
forall v. KESAlgorithm v => Seed -> SignKeyKES v
genKeyKES Seed
r_1
                       SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall (m :: * -> *) a. Monad m => a -> m a
return (SignKeyKES (CompactSumKES h d)
 -> Maybe (SignKeyKES (CompactSumKES h d)))
-> SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall a b. (a -> b) -> a -> b
$ SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
forall h d.
SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
SignKeyCompactSumKES SignKeyKES d
sk' Seed
zero VerKeyKES d
vk_0 VerKeyKES d
vk_1
      | Bool
otherwise = do SignKeyKES d
sk' <- ContextKES d -> SignKeyKES d -> Period -> Maybe (SignKeyKES d)
forall v.
(KESAlgorithm v, HasCallStack) =>
ContextKES v -> SignKeyKES v -> Period -> Maybe (SignKeyKES v)
updateKES ContextKES d
ContextKES (CompactSumKES h d)
ctx SignKeyKES d
sk (Period
t Period -> Period -> Period
forall a. Num a => a -> a -> a
- Period
_T)
                       SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall (m :: * -> *) a. Monad m => a -> m a
return (SignKeyKES (CompactSumKES h d)
 -> Maybe (SignKeyKES (CompactSumKES h d)))
-> SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall a b. (a -> b) -> a -> b
$ SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
forall h d.
SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
SignKeyCompactSumKES SignKeyKES d
sk' Seed
r_1 VerKeyKES d
vk_0 VerKeyKES d
vk_1
      where
        _T :: Period
_T = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
totalPeriodsKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        zero :: Seed
zero = Proxy d -> Seed
forall d. KESAlgorithm d => Proxy d -> Seed
zeroSeed (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)

    totalPeriodsKES :: proxy (CompactSumKES h d) -> Period
totalPeriodsKES  proxy (CompactSumKES h d)
_ = Period
2 Period -> Period -> Period
forall a. Num a => a -> a -> a
* Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
totalPeriodsKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)


    --
    -- Key generation
    --

    seedSizeKES :: proxy (CompactSumKES h d) -> Period
seedSizeKES proxy (CompactSumKES h d)
_ = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
seedSizeKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
    genKeyKES :: Seed -> SignKeyKES (CompactSumKES h d)
genKeyKES Seed
r = SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
forall h d.
SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
SignKeyCompactSumKES SignKeyKES d
sk_0 Seed
r1 VerKeyKES d
vk_0 VerKeyKES d
vk_1
      where
        (Seed
r0, Seed
r1) = Proxy h -> Seed -> (Seed, Seed)
forall h (proxy :: * -> *).
HashAlgorithm h =>
proxy h -> Seed -> (Seed, Seed)
expandSeed (Proxy h
forall k (t :: k). Proxy t
Proxy :: Proxy h) Seed
r

        sk_0 :: SignKeyKES d
sk_0 = Seed -> SignKeyKES d
forall v. KESAlgorithm v => Seed -> SignKeyKES v
genKeyKES Seed
r0
        vk_0 :: VerKeyKES d
vk_0 = SignKeyKES d -> VerKeyKES d
forall v. KESAlgorithm v => SignKeyKES v -> VerKeyKES v
deriveVerKeyKES SignKeyKES d
sk_0

        sk_1 :: SignKeyKES d
sk_1 = Seed -> SignKeyKES d
forall v. KESAlgorithm v => Seed -> SignKeyKES v
genKeyKES Seed
r1
        vk_1 :: VerKeyKES d
vk_1 = SignKeyKES d -> VerKeyKES d
forall v. KESAlgorithm v => SignKeyKES v -> VerKeyKES v
deriveVerKeyKES SignKeyKES d
sk_1


    --
    -- raw serialise/deserialise
    --

    sizeVerKeyKES :: proxy (CompactSumKES h d) -> Period
sizeVerKeyKES  proxy (CompactSumKES h d)
_ = Proxy h -> Period
forall h (proxy :: * -> *). HashAlgorithm h => proxy h -> Period
sizeHash       (Proxy h
forall k (t :: k). Proxy t
Proxy :: Proxy h)
    sizeSignKeyKES :: proxy (CompactSumKES h d) -> Period
sizeSignKeyKES proxy (CompactSumKES h d)
_ = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSignKeyKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
                     Period -> Period -> Period
forall a. Num a => a -> a -> a
+ Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
seedSizeKES    (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
                     Period -> Period -> Period
forall a. Num a => a -> a -> a
+ Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeVerKeyKES  (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d) Period -> Period -> Period
forall a. Num a => a -> a -> a
* Period
2
    sizeSigKES :: proxy (CompactSumKES h d) -> Period
sizeSigKES     proxy (CompactSumKES h d)
_ = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSigKES     (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
                     Period -> Period -> Period
forall a. Num a => a -> a -> a
+ Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeVerKeyKES  (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)

    rawSerialiseVerKeyKES :: VerKeyKES (CompactSumKES h d) -> ByteString
rawSerialiseVerKeyKES  (VerKeyCompactSumKES  vk) = Hash h (VerKeyKES d, VerKeyKES d) -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes Hash h (VerKeyKES d, VerKeyKES d)
vk

    rawSerialiseSignKeyKES :: SignKeyKES (CompactSumKES h d) -> ByteString
rawSerialiseSignKeyKES (SignKeyCompactSumKES sk r_1 vk_0 vk_1) =
      [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
        [ SignKeyKES d -> ByteString
forall v. KESAlgorithm v => SignKeyKES v -> ByteString
rawSerialiseSignKeyKES SignKeyKES d
sk
        , Seed -> ByteString
getSeedBytes Seed
r_1
        , VerKeyKES d -> ByteString
forall v. KESAlgorithm v => VerKeyKES v -> ByteString
rawSerialiseVerKeyKES VerKeyKES d
vk_0
        , VerKeyKES d -> ByteString
forall v. KESAlgorithm v => VerKeyKES v -> ByteString
rawSerialiseVerKeyKES VerKeyKES d
vk_1
        ]

    rawSerialiseSigKES :: SigKES (CompactSumKES h d) -> ByteString
rawSerialiseSigKES (SigCompactSumKES sigma vk_other) =
      [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat
        [ SigKES d -> ByteString
forall v. KESAlgorithm v => SigKES v -> ByteString
rawSerialiseSigKES SigKES d
sigma
        , VerKeyKES d -> ByteString
forall v. KESAlgorithm v => VerKeyKES v -> ByteString
rawSerialiseVerKeyKES VerKeyKES d
vk_other
        ]

    rawDeserialiseVerKeyKES :: ByteString -> Maybe (VerKeyKES (CompactSumKES h d))
rawDeserialiseVerKeyKES = (Hash h (VerKeyKES d, VerKeyKES d)
 -> VerKeyKES (CompactSumKES h d))
-> Maybe (Hash h (VerKeyKES d, VerKeyKES d))
-> Maybe (VerKeyKES (CompactSumKES h d))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
forall h d.
Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
VerKeyCompactSumKES  (Maybe (Hash h (VerKeyKES d, VerKeyKES d))
 -> Maybe (VerKeyKES (CompactSumKES h d)))
-> (ByteString -> Maybe (Hash h (VerKeyKES d, VerKeyKES d)))
-> ByteString
-> Maybe (VerKeyKES (CompactSumKES h d))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Hash h (VerKeyKES d, VerKeyKES d))
forall h a. HashAlgorithm h => ByteString -> Maybe (Hash h a)
hashFromBytes

    rawDeserialiseSignKeyKES :: ByteString -> Maybe (SignKeyKES (CompactSumKES h d))
rawDeserialiseSignKeyKES ByteString
b = do
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (ByteString -> Int
BS.length ByteString
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Period -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Period
size_total)
        SignKeyKES d
sk   <- ByteString -> Maybe (SignKeyKES d)
forall v. KESAlgorithm v => ByteString -> Maybe (SignKeyKES v)
rawDeserialiseSignKeyKES ByteString
b_sk
        let r :: Seed
r = ByteString -> Seed
mkSeedFromBytes          ByteString
b_r
        VerKeyKES d
vk_0 <- ByteString -> Maybe (VerKeyKES d)
forall v. KESAlgorithm v => ByteString -> Maybe (VerKeyKES v)
rawDeserialiseVerKeyKES  ByteString
b_vk0
        VerKeyKES d
vk_1 <- ByteString -> Maybe (VerKeyKES d)
forall v. KESAlgorithm v => ByteString -> Maybe (VerKeyKES v)
rawDeserialiseVerKeyKES  ByteString
b_vk1
        SignKeyKES (CompactSumKES h d)
-> Maybe (SignKeyKES (CompactSumKES h d))
forall (m :: * -> *) a. Monad m => a -> m a
return (SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
forall h d.
SignKeyKES d
-> Seed
-> VerKeyKES d
-> VerKeyKES d
-> SignKeyKES (CompactSumKES h d)
SignKeyCompactSumKES SignKeyKES d
sk Seed
r VerKeyKES d
vk_0 VerKeyKES d
vk_1)
      where
        b_sk :: ByteString
b_sk  = Period -> Period -> ByteString -> ByteString
slice Period
off_sk  Period
size_sk ByteString
b
        b_r :: ByteString
b_r   = Period -> Period -> ByteString -> ByteString
slice Period
off_r   Period
size_r  ByteString
b
        b_vk0 :: ByteString
b_vk0 = Period -> Period -> ByteString -> ByteString
slice Period
off_vk0 Period
size_vk ByteString
b
        b_vk1 :: ByteString
b_vk1 = Period -> Period -> ByteString -> ByteString
slice Period
off_vk1 Period
size_vk ByteString
b

        size_sk :: Period
size_sk    = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSignKeyKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        size_r :: Period
size_r     = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
seedSizeKES    (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        size_vk :: Period
size_vk    = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeVerKeyKES  (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        size_total :: Period
size_total = Proxy (CompactSumKES h d) -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSignKeyKES (Proxy (CompactSumKES h d)
forall k (t :: k). Proxy t
Proxy :: Proxy (CompactSumKES h d))

        off_sk :: Period
off_sk     = Period
0 :: Word
        off_r :: Period
off_r      = Period
size_sk
        off_vk0 :: Period
off_vk0    = Period
off_r Period -> Period -> Period
forall a. Num a => a -> a -> a
+ Period
size_r
        off_vk1 :: Period
off_vk1    = Period
off_vk0 Period -> Period -> Period
forall a. Num a => a -> a -> a
+ Period
size_vk

    rawDeserialiseSigKES :: ByteString -> Maybe (SigKES (CompactSumKES h d))
rawDeserialiseSigKES ByteString
b = do
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (ByteString -> Int
BS.length ByteString
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Period -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Period
size_total)
        SigKES d
sigma <- ByteString -> Maybe (SigKES d)
forall v. KESAlgorithm v => ByteString -> Maybe (SigKES v)
rawDeserialiseSigKES    ByteString
b_sig
        VerKeyKES d
vk  <- ByteString -> Maybe (VerKeyKES d)
forall v. KESAlgorithm v => ByteString -> Maybe (VerKeyKES v)
rawDeserialiseVerKeyKES ByteString
b_vk
        SigKES (CompactSumKES h d) -> Maybe (SigKES (CompactSumKES h d))
forall (m :: * -> *) a. Monad m => a -> m a
return (SigKES d -> VerKeyKES d -> SigKES (CompactSumKES h d)
forall h d. SigKES d -> VerKeyKES d -> SigKES (CompactSumKES h d)
SigCompactSumKES SigKES d
sigma VerKeyKES d
vk)
      where
        b_sig :: ByteString
b_sig = Period -> Period -> ByteString -> ByteString
slice Period
off_sig Period
size_sig ByteString
b
        b_vk :: ByteString
b_vk  = Period -> Period -> ByteString -> ByteString
slice Period
off_vk  Period
size_vk  ByteString
b

        size_sig :: Period
size_sig   = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSigKES    (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        size_vk :: Period
size_vk    = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeVerKeyKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        size_total :: Period
size_total = Proxy (CompactSumKES h d) -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
sizeSigKES    (Proxy (CompactSumKES h d)
forall k (t :: k). Proxy t
Proxy :: Proxy (CompactSumKES h d))

        off_sig :: Period
off_sig    = Period
0 :: Word
        off_vk :: Period
off_vk     = Period
size_sig

instance (KESAlgorithm (CompactSumKES h d), OptimizedKESAlgorithm d, HashAlgorithm h) => OptimizedKESAlgorithm (CompactSumKES h d) where
    verifySigKES :: ContextKES (CompactSumKES h d)
-> Period -> a -> SigKES (CompactSumKES h d) -> Either String ()
verifySigKES ContextKES (CompactSumKES h d)
ctxt Period
t a
a (SigCompactSumKES sigma _) =
      ContextKES d -> Period -> a -> SigKES d -> Either String ()
forall v a.
(OptimizedKESAlgorithm v, Signable v a, HasCallStack) =>
ContextKES v -> Period -> a -> SigKES v -> Either String ()
verifySigKES ContextKES d
ContextKES (CompactSumKES h d)
ctxt Period
t' a
a SigKES d
sigma
      where
        _T :: Period
_T = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
totalPeriodsKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        t' :: Period
t' | Period
t Period -> Period -> Bool
forall a. Ord a => a -> a -> Bool
< Period
_T = Period
t
           | Bool
otherwise = Period
t Period -> Period -> Period
forall a. Num a => a -> a -> a
- Period
_T

    verKeyFromSigKES :: ContextKES (CompactSumKES h d)
-> Period
-> SigKES (CompactSumKES h d)
-> VerKeyKES (CompactSumKES h d)
verKeyFromSigKES ContextKES (CompactSumKES h d)
ctxt Period
t (SigCompactSumKES sigma vk_other) =
      Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
forall h d.
Hash h (VerKeyKES d, VerKeyKES d) -> VerKeyKES (CompactSumKES h d)
VerKeyCompactSumKES (Hash h (VerKeyKES d, VerKeyKES d)
 -> VerKeyKES (CompactSumKES h d))
-> Hash h (VerKeyKES d, VerKeyKES d)
-> VerKeyKES (CompactSumKES h d)
forall a b. (a -> b) -> a -> b
$ (VerKeyKES d, VerKeyKES d) -> Hash h (VerKeyKES d, VerKeyKES d)
forall d h.
(KESAlgorithm d, HashAlgorithm h) =>
(VerKeyKES d, VerKeyKES d) -> Hash h (VerKeyKES d, VerKeyKES d)
hashPairOfVKeys (VerKeyKES d
vk_0, VerKeyKES d
vk_1)
      where
        _T :: Period
_T = Proxy d -> Period
forall v (proxy :: * -> *). KESAlgorithm v => proxy v -> Period
totalPeriodsKES (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)
        t' :: Period
t' | Period
t Period -> Period -> Bool
forall a. Ord a => a -> a -> Bool
< Period
_T = Period
t
           | Bool
otherwise = Period
t Period -> Period -> Period
forall a. Num a => a -> a -> a
- Period
_T
        (VerKeyKES d
vk_0, VerKeyKES d
vk_1) | Period
t Period -> Period -> Bool
forall a. Ord a => a -> a -> Bool
< Period
_T = (ContextKES d -> Period -> SigKES d -> VerKeyKES d
forall v.
OptimizedKESAlgorithm v =>
ContextKES v -> Period -> SigKES v -> VerKeyKES v
verKeyFromSigKES ContextKES d
ContextKES (CompactSumKES h d)
ctxt Period
t' SigKES d
sigma, VerKeyKES d
vk_other)
                     | Bool
otherwise = (VerKeyKES d
vk_other, ContextKES d -> Period -> SigKES d -> VerKeyKES d
forall v.
OptimizedKESAlgorithm v =>
ContextKES v -> Period -> SigKES v -> VerKeyKES v
verKeyFromSigKES ContextKES d
ContextKES (CompactSumKES h d)
ctxt Period
t' SigKES d
sigma)

--
-- VerKey instances
--

deriving instance HashAlgorithm h => Show (VerKeyKES (CompactSumKES h d))
deriving instance Eq   (VerKeyKES (CompactSumKES h d))

instance (KESAlgorithm d) => NoThunks (SignKeyKES (CompactSumKES h d))

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => ToCBOR (VerKeyKES (CompactSumKES h d)) where
  toCBOR :: VerKeyKES (CompactSumKES h d) -> Encoding
toCBOR = VerKeyKES (CompactSumKES h d) -> Encoding
forall v. KESAlgorithm v => VerKeyKES v -> Encoding
encodeVerKeyKES
  encodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (VerKeyKES (CompactSumKES h d)) -> Size
encodedSizeExpr forall t. ToCBOR t => Proxy t -> Size
_size = Proxy (VerKeyKES (CompactSumKES h d)) -> Size
forall v. KESAlgorithm v => Proxy (VerKeyKES v) -> Size
encodedVerKeyKESSizeExpr

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => FromCBOR (VerKeyKES (CompactSumKES h d)) where
  fromCBOR :: Decoder s (VerKeyKES (CompactSumKES h d))
fromCBOR = Decoder s (VerKeyKES (CompactSumKES h d))
forall v s. KESAlgorithm v => Decoder s (VerKeyKES v)
decodeVerKeyKES


--
-- SignKey instances
--

deriving instance KESAlgorithm d => Show (SignKeyKES (CompactSumKES h d))

instance (OptimizedKESAlgorithm d) => NoThunks (VerKeyKES  (CompactSumKES h d))

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => ToCBOR (SignKeyKES (CompactSumKES h d)) where
  toCBOR :: SignKeyKES (CompactSumKES h d) -> Encoding
toCBOR = SignKeyKES (CompactSumKES h d) -> Encoding
forall v. KESAlgorithm v => SignKeyKES v -> Encoding
encodeSignKeyKES
  encodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (SignKeyKES (CompactSumKES h d)) -> Size
encodedSizeExpr forall t. ToCBOR t => Proxy t -> Size
_size = Proxy (SignKeyKES (CompactSumKES h d)) -> Size
forall v. KESAlgorithm v => Proxy (SignKeyKES v) -> Size
encodedSignKeyKESSizeExpr

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => FromCBOR (SignKeyKES (CompactSumKES h d)) where
  fromCBOR :: Decoder s (SignKeyKES (CompactSumKES h d))
fromCBOR = Decoder s (SignKeyKES (CompactSumKES h d))
forall v s. KESAlgorithm v => Decoder s (SignKeyKES v)
decodeSignKeyKES


--
-- Sig instances
--

deriving instance KESAlgorithm d => Show (SigKES (CompactSumKES h d))
deriving instance KESAlgorithm d => Eq   (SigKES (CompactSumKES h d))

instance KESAlgorithm d => NoThunks (SigKES (CompactSumKES h d))

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => ToCBOR (SigKES (CompactSumKES h d)) where
  toCBOR :: SigKES (CompactSumKES h d) -> Encoding
toCBOR = SigKES (CompactSumKES h d) -> Encoding
forall v. KESAlgorithm v => SigKES v -> Encoding
encodeSigKES
  encodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (SigKES (CompactSumKES h d)) -> Size
encodedSizeExpr forall t. ToCBOR t => Proxy t -> Size
_size = Proxy (SigKES (CompactSumKES h d)) -> Size
forall v. KESAlgorithm v => Proxy (SigKES v) -> Size
encodedSigKESSizeExpr

instance (OptimizedKESAlgorithm d, HashAlgorithm h, Typeable d)
      => FromCBOR (SigKES (CompactSumKES h d)) where
  fromCBOR :: Decoder s (SigKES (CompactSumKES h d))
fromCBOR = Decoder s (SigKES (CompactSumKES h d))
forall v s. KESAlgorithm v => Decoder s (SigKES v)
decodeSigKES