module Network.CryptoConditions.Json
( parseJsonPreimage
, parseJsonPrefix
, parseJsonThreshold
, parseJsonEd25519
, toJsonPreimage
, toJsonPrefix
, toJsonThreshold
, toJsonEd25519
, fromB64
, toB64
) where
import Crypto.PubKey.Ed25519
import Crypto.Error
import Data.Aeson
import Data.Aeson.Types
import qualified Data.ByteArray as BA
import Data.ByteString as BS
import Data.Text
import Data.Text.Encoding
import Data.Word
import Network.CryptoConditions.Encoding
import Network.CryptoConditions.Impl
parseJsonThreshold :: (IsCondition c, FromJSON c) => (Word16 -> [c] -> c) -> Object -> Parser c
parseJsonThreshold f obj = f <$> obj .: "threshold" <*> obj .: "subfulfillments"
parseJsonEd25519 :: IsCondition c => (PublicKey -> Maybe Signature -> c) -> Object -> Parser c
parseJsonEd25519 f obj = do
pub <- obj .: "publicKey" >>= parseKey publicKey
msig <- obj .:? "signature" >>= mapM (parseKey signature)
pure $ f pub msig
parseJsonPrefix :: (IsCondition c, FromJSON c) => (ByteString -> Int -> c -> c) -> Object -> Parser c
parseJsonPrefix f obj = do
pre <- obj .: "prefix" >>= fromB64
f pre <$> obj .: "maxMessageLength" <*> obj .: "subfulfillment"
parseJsonPreimage :: IsCondition c => (ByteString -> c) -> Object -> Parser c
parseJsonPreimage f obj =
f <$> (obj .: "preimage" >>= fromB64)
toJsonPreimage :: ByteString -> Value
toJsonPreimage img = object ["type" .= String "preimage-sha-256", "preimage" .= toB64 img]
toJsonPrefix :: (IsCondition c, ToJSON c) => ByteString -> Int -> c -> Value
toJsonPrefix pre mml sub =
object [ "type".= String "prefix-sha-256"
, "prefix" .= toB64 pre
, "subfulfillment" .= sub
]
toJsonThreshold :: (IsCondition c, ToJSON c) => Word16 -> [c] -> Value
toJsonThreshold threshold subs =
object [ "type" .= String "threshold-sha-256"
, "threshold" .= threshold
, "subfulfillments" .= subs
]
toJsonEd25519 :: PublicKey -> Maybe Signature -> Value
toJsonEd25519 pk msig =
let sigItem = maybe [] (\sig -> ["signature" .= keyToJson sig]) msig
in object $ ["type" .= String "ed25519-sha-256", "publicKey" .= keyToJson pk] ++ sigItem
fromB64 :: Text -> Parser ByteString
fromB64 = either fail pure . b64DecodeStripped . encodeUtf8
parseKey :: (ByteString -> CryptoFailable b) -> Text -> Parser b
parseKey f bs = do
bin <- either fail pure $ b64DecodeStripped $ encodeUtf8 bs
onCryptoFailure (fail . show) pure $ f bin
keyToJson :: BA.ByteArrayAccess k => k -> Value
keyToJson = String . decodeUtf8 . b64EncodeStripped . BS.pack . BA.unpack
toB64 :: ByteString -> Value
toB64 = String . decodeUtf8 . b64EncodeStripped