-- | Structured representations of SDMF capabilities.
module Tahoe.SDMF.Internal.Capability where

import Prelude hiding (Read)

import Control.Applicative ((<|>))
import Control.Monad (void)
import Crypto.Hash (digestFromByteString)
import Data.Binary (decode)
import qualified Data.ByteArray as ByteArray
import qualified Data.ByteString as B
import qualified Data.ByteString.Base32 as B
import qualified Data.ByteString.Lazy as LB
import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Void (Void)
import Data.Word (Word16)
import Tahoe.CHK.SHA256d (Digest' (Digest'), SHA256d)
import Tahoe.Capability (ConfidentialShowable (..))
import Tahoe.SDMF.Internal.Keys (
    Read (readKeyBytes),
    StorageIndex (StorageIndex, unStorageIndex),
    Write (writeKeyBytes),
    deriveReadKey,
    deriveStorageIndex,
    readKeyBytes,
    showBase32,
 )
import Text.Megaparsec (
    ErrorFancy (ErrorFail),
    Parsec,
    count,
    failure,
    fancyFailure,
    oneOf,
 )
import Text.Megaparsec.Char (char, string)

-- | Any kind of SDMF capability.
data SDMF
    = SDMFVerifier Verifier
    | SDMFReader Reader
    | SDMFWriter Writer
    deriving (SDMF -> SDMF -> Bool
(SDMF -> SDMF -> Bool) -> (SDMF -> SDMF -> Bool) -> Eq SDMF
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SDMF -> SDMF -> Bool
$c/= :: SDMF -> SDMF -> Bool
== :: SDMF -> SDMF -> Bool
$c== :: SDMF -> SDMF -> Bool
Eq, Int -> SDMF -> ShowS
[SDMF] -> ShowS
SDMF -> String
(Int -> SDMF -> ShowS)
-> (SDMF -> String) -> ([SDMF] -> ShowS) -> Show SDMF
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SDMF] -> ShowS
$cshowList :: [SDMF] -> ShowS
show :: SDMF -> String
$cshow :: SDMF -> String
showsPrec :: Int -> SDMF -> ShowS
$cshowsPrec :: Int -> SDMF -> ShowS
Show)

instance ConfidentialShowable SDMF where
    confidentiallyShow :: SDMF -> Text
confidentiallyShow = SDMF -> Text
dangerRealShow

-- | A verify capability for an SDMF object.
data Verifier = Verifier
    { Verifier -> StorageIndex
verifierStorageIndex :: StorageIndex
    , Verifier -> Digest' SHA256d
verifierVerificationKeyHash :: Digest' SHA256d
    }
    deriving (Verifier -> Verifier -> Bool
(Verifier -> Verifier -> Bool)
-> (Verifier -> Verifier -> Bool) -> Eq Verifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Verifier -> Verifier -> Bool
$c/= :: Verifier -> Verifier -> Bool
== :: Verifier -> Verifier -> Bool
$c== :: Verifier -> Verifier -> Bool
Eq, Int -> Verifier -> ShowS
[Verifier] -> ShowS
Verifier -> String
(Int -> Verifier -> ShowS)
-> (Verifier -> String) -> ([Verifier] -> ShowS) -> Show Verifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Verifier] -> ShowS
$cshowList :: [Verifier] -> ShowS
show :: Verifier -> String
$cshow :: Verifier -> String
showsPrec :: Int -> Verifier -> ShowS
$cshowsPrec :: Int -> Verifier -> ShowS
Show)

instance Ord Verifier where
    Verifier
a <= :: Verifier -> Verifier -> Bool
<= Verifier
b = Verifier -> StorageIndex
verifierStorageIndex Verifier
a StorageIndex -> StorageIndex -> Bool
forall a. Ord a => a -> a -> Bool
<= Verifier -> StorageIndex
verifierStorageIndex Verifier
b

instance ConfidentialShowable Verifier where
    confidentiallyShow :: Verifier -> Text
confidentiallyShow = SDMF -> Text
dangerRealShow (SDMF -> Text) -> (Verifier -> SDMF) -> Verifier -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Verifier -> SDMF
SDMFVerifier

-- | A read capability for an SDMF object.
data Reader = Reader
    { Reader -> Read
readerReadKey :: Read
    , Reader -> Verifier
readerVerifier :: Verifier
    }
    deriving (Reader -> Reader -> Bool
(Reader -> Reader -> Bool)
-> (Reader -> Reader -> Bool) -> Eq Reader
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Reader -> Reader -> Bool
$c/= :: Reader -> Reader -> Bool
== :: Reader -> Reader -> Bool
$c== :: Reader -> Reader -> Bool
Eq, Int -> Reader -> ShowS
[Reader] -> ShowS
Reader -> String
(Int -> Reader -> ShowS)
-> (Reader -> String) -> ([Reader] -> ShowS) -> Show Reader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Reader] -> ShowS
$cshowList :: [Reader] -> ShowS
show :: Reader -> String
$cshow :: Reader -> String
showsPrec :: Int -> Reader -> ShowS
$cshowsPrec :: Int -> Reader -> ShowS
Show)

instance Ord Reader where
    Reader
a <= :: Reader -> Reader -> Bool
<= Reader
b = Reader -> Verifier
readerVerifier Reader
a Verifier -> Verifier -> Bool
forall a. Ord a => a -> a -> Bool
<= Reader -> Verifier
readerVerifier Reader
b

instance ConfidentialShowable Reader where
    confidentiallyShow :: Reader -> Text
confidentiallyShow = SDMF -> Text
dangerRealShow (SDMF -> Text) -> (Reader -> SDMF) -> Reader -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reader -> SDMF
SDMFReader

-- | A write capability for an SDMF object.
data Writer = Writer
    { Writer -> Write
writerWriteKey :: Write
    , Writer -> Reader
writerReader :: Reader
    }
    deriving (Writer -> Writer -> Bool
(Writer -> Writer -> Bool)
-> (Writer -> Writer -> Bool) -> Eq Writer
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Writer -> Writer -> Bool
$c/= :: Writer -> Writer -> Bool
== :: Writer -> Writer -> Bool
$c== :: Writer -> Writer -> Bool
Eq, Int -> Writer -> ShowS
[Writer] -> ShowS
Writer -> String
(Int -> Writer -> ShowS)
-> (Writer -> String) -> ([Writer] -> ShowS) -> Show Writer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Writer] -> ShowS
$cshowList :: [Writer] -> ShowS
show :: Writer -> String
$cshow :: Writer -> String
showsPrec :: Int -> Writer -> ShowS
$cshowsPrec :: Int -> Writer -> ShowS
Show)

instance Ord Writer where
    Writer
a <= :: Writer -> Writer -> Bool
<= Writer
b = Writer -> Reader
writerReader Writer
a Reader -> Reader -> Bool
forall a. Ord a => a -> a -> Bool
<= Writer -> Reader
writerReader Writer
b

instance ConfidentialShowable Writer where
    confidentiallyShow :: Writer -> Text
confidentiallyShow = SDMF -> Text
dangerRealShow (SDMF -> Text) -> (Writer -> SDMF) -> Writer -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer -> SDMF
SDMFWriter

-- | Diminish a write key to a read key and wrap it in a reader capability.
deriveReader :: Write -> Digest' SHA256d -> Maybe Reader
deriveReader :: Write -> Digest' SHA256d -> Maybe Reader
deriveReader Write
w Digest' SHA256d
fingerprint = Read -> Verifier -> Reader
Reader (Read -> Verifier -> Reader)
-> Maybe Read -> Maybe (Verifier -> Reader)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Read
readKey Maybe (Verifier -> Reader) -> Maybe Verifier -> Maybe Reader
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Verifier
verifier
  where
    readKey :: Maybe Read
readKey = Write -> Maybe Read
deriveReadKey Write
w
    verifier :: Maybe Verifier
verifier = (Read -> Digest' SHA256d -> Verifier)
-> Digest' SHA256d -> Read -> Verifier
forall a b c. (a -> b -> c) -> b -> a -> c
flip Read -> Digest' SHA256d -> Verifier
deriveVerifier Digest' SHA256d
fingerprint (Read -> Verifier) -> Maybe Read -> Maybe Verifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Read
readKey

-- | Diminish a read key to a verify key and wrap it in a verifier capability.
deriveVerifier :: Read -> Digest' SHA256d -> Verifier
deriveVerifier :: Read -> Digest' SHA256d -> Verifier
deriveVerifier Read
readKey = StorageIndex -> Digest' SHA256d -> Verifier
Verifier StorageIndex
storageIndex
  where
    storageIndex :: StorageIndex
storageIndex = Read -> StorageIndex
deriveStorageIndex Read
readKey

type Parser = Parsec Void T.Text

-- | A parser for any kind of SDMF capability type.
pCapability :: Parser SDMF
pCapability :: Parser SDMF
pCapability = (Verifier -> SDMF
SDMFVerifier (Verifier -> SDMF)
-> ParsecT Void Text Identity Verifier -> Parser SDMF
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Verifier
pVerifier) Parser SDMF -> Parser SDMF -> Parser SDMF
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Reader -> SDMF
SDMFReader (Reader -> SDMF)
-> ParsecT Void Text Identity Reader -> Parser SDMF
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Reader
pReader) Parser SDMF -> Parser SDMF -> Parser SDMF
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Writer -> SDMF
SDMFWriter (Writer -> SDMF)
-> ParsecT Void Text Identity Writer -> Parser SDMF
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Writer
pWriter)

-- | A parser for an SDMF verifier capability.
pVerifier :: Parser Verifier
pVerifier :: ParsecT Void Text Identity Verifier
pVerifier = (StorageIndex -> Digest' SHA256d -> Verifier)
-> (StorageIndex, Digest' SHA256d) -> Verifier
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry StorageIndex -> Digest' SHA256d -> Verifier
Verifier ((StorageIndex, Digest' SHA256d) -> Verifier)
-> ParsecT Void Text Identity (StorageIndex, Digest' SHA256d)
-> ParsecT Void Text Identity Verifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> (ByteString -> StorageIndex)
-> ParsecT Void Text Identity (StorageIndex, Digest' SHA256d)
forall a. Text -> (ByteString -> a) -> Parser (a, Digest' SHA256d)
pPieces Text
"URI:SSK-Verifier:" ByteString -> StorageIndex
StorageIndex

-- | A parser for an SDMF reader capability.
pReader :: Parser Reader
pReader :: ParsecT Void Text Identity Reader
pReader = do
    (Read
readKey, Digest' SHA256d
verificationKeyHash) <- Text -> (ByteString -> Read) -> Parser (Read, Digest' SHA256d)
forall a. Text -> (ByteString -> a) -> Parser (a, Digest' SHA256d)
pPieces Text
"URI:SSK-RO:" (ByteString -> Read
forall a. Binary a => ByteString -> a
decode (ByteString -> Read)
-> (ByteString -> ByteString) -> ByteString -> Read
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LB.fromStrict)
    let verifier :: Verifier
verifier = Read -> Digest' SHA256d -> Verifier
deriveVerifier Read
readKey Digest' SHA256d
verificationKeyHash
    Reader -> ParsecT Void Text Identity Reader
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Reader -> ParsecT Void Text Identity Reader)
-> Reader -> ParsecT Void Text Identity Reader
forall a b. (a -> b) -> a -> b
$ Read -> Verifier -> Reader
Reader Read
readKey Verifier
verifier

-- | A parser for an SDMF writer capability.
pWriter :: Parser Writer
pWriter :: ParsecT Void Text Identity Writer
pWriter = do
    (Write
writeKey, Digest' SHA256d
verificationKeyHash) <- Text -> (ByteString -> Write) -> Parser (Write, Digest' SHA256d)
forall a. Text -> (ByteString -> a) -> Parser (a, Digest' SHA256d)
pPieces Text
"URI:SSK:" (ByteString -> Write
forall a. Binary a => ByteString -> a
decode (ByteString -> Write)
-> (ByteString -> ByteString) -> ByteString -> Write
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LB.fromStrict)
    let reader :: Maybe Reader
reader = Write -> Digest' SHA256d -> Maybe Reader
deriveReader Write
writeKey Digest' SHA256d
verificationKeyHash
    case Write -> Reader -> Writer
Writer Write
writeKey (Reader -> Writer) -> Maybe Reader -> Maybe Writer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Reader
reader of
        Maybe Writer
Nothing -> Maybe (ErrorItem (Token Text))
-> Set (ErrorItem (Token Text))
-> ParsecT Void Text Identity Writer
forall e s (m :: * -> *) a.
MonadParsec e s m =>
Maybe (ErrorItem (Token s)) -> Set (ErrorItem (Token s)) -> m a
failure Maybe (ErrorItem (Token Text))
forall a. Maybe a
Nothing Set (ErrorItem (Token Text))
forall a. Monoid a => a
mempty
        Just Writer
writer -> Writer -> ParsecT Void Text Identity Writer
forall (f :: * -> *) a. Applicative f => a -> f a
pure Writer
writer

{- | A parser for two base32-encoded bytestrings with some given prefix,
 formatted as they are in the string representation of an SDMF capability.
-}
pPieces ::
    -- | The prefix to expect.
    T.Text ->
    -- | A function to convert the first bytestring to a result value.
    (B.ByteString -> a) ->
    -- | A parser for the two pieces of the SDMF capability.
    Parser (a, Digest' SHA256d)
pPieces :: Text -> (ByteString -> a) -> Parser (a, Digest' SHA256d)
pPieces Text
prefix ByteString -> a
convertSecret = do
    ParsecT Void Text Identity Text -> ParsecT Void Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT Void Text Identity Text -> ParsecT Void Text Identity ())
-> ParsecT Void Text Identity Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Tokens Text -> ParsecT Void Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Text
Tokens Text
prefix
    a
secret <- ByteString -> a
convertSecret (ByteString -> a)
-> ParsecT Void Text Identity ByteString
-> ParsecT Void Text Identity a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Word16 -> ParsecT Void Text Identity ByteString
pBase32 String
rfc3548Alphabet Word16
128
    ParsecT Void Text Identity Char -> ParsecT Void Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT Void Text Identity Char -> ParsecT Void Text Identity ())
-> ParsecT Void Text Identity Char -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Token Text -> ParsecT Void Text Identity (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
Token Text
':'
    ByteString
digestBytes <- String -> Word16 -> ParsecT Void Text Identity ByteString
pBase32 String
rfc3548Alphabet Word16
256
    case ByteString -> Maybe (Digest SHA256d)
forall a ba.
(HashAlgorithm a, ByteArrayAccess ba) =>
ba -> Maybe (Digest a)
digestFromByteString ByteString
digestBytes of
        Maybe (Digest SHA256d)
Nothing -> Maybe (ErrorItem (Token Text))
-> Set (ErrorItem (Token Text)) -> Parser (a, Digest' SHA256d)
forall e s (m :: * -> *) a.
MonadParsec e s m =>
Maybe (ErrorItem (Token s)) -> Set (ErrorItem (Token s)) -> m a
failure Maybe (ErrorItem (Token Text))
forall a. Maybe a
Nothing Set (ErrorItem (Token Text))
forall a. Monoid a => a
mempty
        Just Digest SHA256d
verificationKeyHash ->
            (a, Digest' SHA256d) -> Parser (a, Digest' SHA256d)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
secret, Digest SHA256d -> Digest' SHA256d
forall a. Digest a -> Digest' a
Digest' Digest SHA256d
verificationKeyHash)

{- | A parser combinator for an arbitrary byte string of a fixed length,
 encoded using base32.

 TODO: Avoid duplicating this implementation here and in tahoe-chk.
-}
pBase32 ::
    -- | The alphabet to use.  For example, *rfc3548Alphabet*.
    [Char] ->
    -- | The number of bits in the encoded byte string.
    Word16 ->
    -- | A parser for the byte string.  Strings that are not valid base32 will
    -- be rejected.  Strings that are the wrong length are *not necessarily*
    -- currently rejected!  Please fix that, somebody.
    Parser B.ByteString
pBase32 :: String -> Word16 -> ParsecT Void Text Identity ByteString
pBase32 String
alpha Word16
bits = do
    Text
b32Text <- ParsecT Void Text Identity Text
pBase32Text
    (Text -> ParsecT Void Text Identity ByteString)
-> (ByteString -> ParsecT Void Text Identity ByteString)
-> Either Text ByteString
-> ParsecT Void Text Identity ByteString
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Set (ErrorFancy Void) -> ParsecT Void Text Identity ByteString
forall e s (m :: * -> *) a.
MonadParsec e s m =>
Set (ErrorFancy e) -> m a
fancyFailure (Set (ErrorFancy Void) -> ParsecT Void Text Identity ByteString)
-> (Text -> Set (ErrorFancy Void))
-> Text
-> ParsecT Void Text Identity ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorFancy Void -> Set (ErrorFancy Void)
forall a. a -> Set a
Set.singleton (ErrorFancy Void -> Set (ErrorFancy Void))
-> (Text -> ErrorFancy Void) -> Text -> Set (ErrorFancy Void)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ErrorFancy Void
forall e. String -> ErrorFancy e
ErrorFail (String -> ErrorFancy Void)
-> (Text -> String) -> Text -> ErrorFancy Void
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) ByteString -> ParsecT Void Text Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Either Text ByteString
decodeBase32Text Text
b32Text)
  where
    decodeBase32Text :: Text -> Either Text ByteString
decodeBase32Text = ByteString -> Either Text ByteString
B.decodeBase32Unpadded (ByteString -> Either Text ByteString)
-> (Text -> ByteString) -> Text -> Either Text ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8
    pBase32Text :: ParsecT Void Text Identity Text
pBase32Text = Text -> Char -> Text
T.snoc (Text -> Char -> Text)
-> ParsecT Void Text Identity Text
-> ParsecT Void Text Identity (Char -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Text
stem ParsecT Void Text Identity (Char -> Text)
-> ParsecT Void Text Identity Char
-> ParsecT Void Text Identity Text
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void Text Identity Char
trailer

    -- Determine how many full characters to expect along with how many bits
    -- are left to expect encoded in the final character.
    (Word16
full, Word16
extra) = Word16
bits Word16 -> Word16 -> (Word16, Word16)
forall a. Integral a => a -> a -> (a, a)
`divMod` Word16
5

    -- Match the base32 characters that represent the full 5 bits
    -- possible.  fromIntegral is okay here because `full` is only a
    -- Word16 and will definitely fit safely into the Int count wants.
    stem :: Parser T.Text
    stem :: ParsecT Void Text Identity Text
stem = String -> Text
T.pack (String -> Text)
-> ParsecT Void Text Identity String
-> ParsecT Void Text Identity Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int
-> ParsecT Void Text Identity Char
-> ParsecT Void Text Identity String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count (Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
full) ([Token Text] -> ParsecT Void Text Identity (Token Text)
forall (f :: * -> *) e s (m :: * -> *).
(Foldable f, MonadParsec e s m) =>
f (Token s) -> m (Token s)
oneOf String
[Token Text]
alpha)

    -- Match the final character that represents fewer than 5 bits.
    trailer :: Parser Char
    trailer :: ParsecT Void Text Identity Char
trailer = [Token Text] -> ParsecT Void Text Identity (Token Text)
forall (f :: * -> *) e s (m :: * -> *).
(Foldable f, MonadParsec e s m) =>
f (Token s) -> m (Token s)
oneOf ([Token Text] -> ParsecT Void Text Identity (Token Text))
-> [Token Text] -> ParsecT Void Text Identity (Token Text)
forall a b. (a -> b) -> a -> b
$ String -> Word16 -> String
trailingChars String
alpha Word16
extra

    -- XXX The real trailing character set is smaller than this.  This
    -- parser will let through invalid characters that result in giving us
    -- possibly too many bits.
    trailingChars :: [Char] -> Word16 -> [Char]
    trailingChars :: String -> Word16 -> String
trailingChars String
alpha' Word16
_ = String
alpha'

{- | The RFC3548 standard alphabet used by Gnutella, Content-Addressable Web,
 THEX, Bitzi, Web-Calculus...
-}
rfc3548Alphabet :: [Char]
rfc3548Alphabet :: String
rfc3548Alphabet = String
"abcdefghijklmnopqrstuvwxyz234567"

-- | Show an SDMF capability, including all secret information.
{-# DEPRECATED dangerRealShow "Use the ConfidentialShowable instance" #-}
dangerRealShow :: SDMF -> T.Text
dangerRealShow :: SDMF -> Text
dangerRealShow (SDMFVerifier Verifier{StorageIndex
verifierStorageIndex :: StorageIndex
verifierStorageIndex :: Verifier -> StorageIndex
verifierStorageIndex, Digest' SHA256d
verifierVerificationKeyHash :: Digest' SHA256d
verifierVerificationKeyHash :: Verifier -> Digest' SHA256d
verifierVerificationKeyHash}) =
    [Text] -> Text
T.concat
        [ Text
"URI:SSK-Verifier:"
        , ByteString -> Text
showBase32 (ByteString -> Text)
-> (StorageIndex -> ByteString) -> StorageIndex -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StorageIndex -> ByteString
unStorageIndex (StorageIndex -> Text) -> StorageIndex -> Text
forall a b. (a -> b) -> a -> b
$ StorageIndex
verifierStorageIndex
        , Text
":"
        , ByteString -> Text
showBase32 (ByteString -> Text)
-> (Digest' SHA256d -> ByteString) -> Digest' SHA256d -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest' SHA256d -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (Digest' SHA256d -> Text) -> Digest' SHA256d -> Text
forall a b. (a -> b) -> a -> b
$ Digest' SHA256d
verifierVerificationKeyHash
        ]
dangerRealShow (SDMFReader Reader{Read
readerReadKey :: Read
readerReadKey :: Reader -> Read
readerReadKey, Verifier
readerVerifier :: Verifier
readerVerifier :: Reader -> Verifier
readerVerifier}) =
    [Text] -> Text
T.concat
        [ Text
"URI:SSK-RO:"
        , ByteString -> Text
showBase32 (ByteString -> Text) -> (Read -> ByteString) -> Read -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (ScrubbedBytes -> ByteString)
-> (Read -> ScrubbedBytes) -> Read -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Read -> ScrubbedBytes
readKeyBytes (Read -> Text) -> Read -> Text
forall a b. (a -> b) -> a -> b
$ Read
readerReadKey
        , Text
":"
        , ByteString -> Text
showBase32 (ByteString -> Text)
-> (Verifier -> ByteString) -> Verifier -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest' SHA256d -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (Digest' SHA256d -> ByteString)
-> (Verifier -> Digest' SHA256d) -> Verifier -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Verifier -> Digest' SHA256d
verifierVerificationKeyHash (Verifier -> Text) -> Verifier -> Text
forall a b. (a -> b) -> a -> b
$ Verifier
readerVerifier
        ]
dangerRealShow (SDMFWriter Writer{Write
writerWriteKey :: Write
writerWriteKey :: Writer -> Write
writerWriteKey, Reader
writerReader :: Reader
writerReader :: Writer -> Reader
writerReader}) =
    [Text] -> Text
T.concat
        [ Text
"URI:SSK:"
        , ByteString -> Text
showBase32 (ByteString -> Text) -> (Write -> ByteString) -> Write -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (ScrubbedBytes -> ByteString)
-> (Write -> ScrubbedBytes) -> Write -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Write -> ScrubbedBytes
writeKeyBytes (Write -> Text) -> Write -> Text
forall a b. (a -> b) -> a -> b
$ Write
writerWriteKey
        , Text
":"
        , ByteString -> Text
showBase32 (ByteString -> Text) -> (Reader -> ByteString) -> Reader -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest' SHA256d -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (Digest' SHA256d -> ByteString)
-> (Reader -> Digest' SHA256d) -> Reader -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Verifier -> Digest' SHA256d
verifierVerificationKeyHash (Verifier -> Digest' SHA256d)
-> (Reader -> Verifier) -> Reader -> Digest' SHA256d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reader -> Verifier
readerVerifier (Reader -> Text) -> Reader -> Text
forall a b. (a -> b) -> a -> b
$ Reader
writerReader
        ]