diff --git a/src/Tahoe/SDMF.hs b/src/Tahoe/SDMF.hs index 194439d3f318499df9108c914a171a65029a6eb2..fc31ca9dd98230f2a447c2d85a45898f994e180e 100644 --- a/src/Tahoe/SDMF.hs +++ b/src/Tahoe/SDMF.hs @@ -8,6 +8,8 @@ module Tahoe.SDMF ( import Tahoe.SDMF.Internal.Capability ( Reader (..), + SDMF (..), + Verifier (..), Writer (..), pCapability, pReader, diff --git a/src/Tahoe/SDMF/Internal/Capability.hs b/src/Tahoe/SDMF/Internal/Capability.hs index e259a5b844562b29f6a14a394c9e0fc27ae84ab5..8d42e1c951d8dc8af75bd7fb173252215bc3fe50 100644 --- a/src/Tahoe/SDMF/Internal/Capability.hs +++ b/src/Tahoe/SDMF/Internal/Capability.hs @@ -10,7 +10,6 @@ import Data.Binary (decode) import qualified Data.ByteString as B import qualified Data.ByteString.Base32 as B import qualified Data.ByteString.Lazy as LB -import Data.Maybe (fromMaybe) import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Text.Encoding as T @@ -24,18 +23,21 @@ data Verifier = Verifier { verifierStorageIndex :: StorageIndex , verifierVerificationKeyHash :: Digest SHA256 } + deriving (Eq, Show) -- | A read capability for an SDMF object. data Reader = Reader { readerReadKey :: Read , readerVerifier :: Verifier } + deriving (Eq, Show) -- | A write capability for an SDMF object. data Writer = Writer { writerWriteKey :: Write , writerReader :: Reader } + deriving (Eq, Show) -- | Diminish a write key to a read key and wrap it in a reader capability. deriveReader :: Write -> Digest SHA256 -> Maybe Reader diff --git a/src/Tahoe/SDMF/Internal/Keys.hs b/src/Tahoe/SDMF/Internal/Keys.hs index 47484f0909e5edb9faa3bbfdb68164406bdc58ba..5711b4def2516af8994284e0710e90565bebdb5a 100644 --- a/src/Tahoe/SDMF/Internal/Keys.hs +++ b/src/Tahoe/SDMF/Internal/Keys.hs @@ -46,6 +46,9 @@ newtype Signature = Signature {unSignature :: RSA.PrivateKey} data Write = Write {unWrite :: AES128, writeKeyBytes :: ByteArray.ScrubbedBytes} +instance Eq Write where + (Write _ left) == (Write _ right) = left == right + instance Binary Write where put = putByteString . ByteArray.convert . writeKeyBytes get = do @@ -54,10 +57,30 @@ instance Binary Write where pure Write{..} instance Show Write where - show (Write _ bs) = T.unpack $ T.concat ["<WriteKey ", encodeBase32Unpadded (ByteArray.convert bs), ">"] + show (Write _ bs) = + T.unpack $ + T.concat + [ "<WriteKey " + , T.take 4 . encodeBase32Unpadded . ByteArray.convert $ bs + , "..." + , ">" + ] data Read = Read {unRead :: AES128, readKeyBytes :: ByteArray.ScrubbedBytes} +instance Eq Read where + (Read _ left) == (Read _ right) = left == right + +instance Show Read where + show (Read _ bs) = + T.unpack $ + T.concat + [ "<ReadKey " + , T.take 4 . encodeBase32Unpadded . ByteArray.convert $ bs + , "..." + , ">" + ] + instance Binary Read where put = putByteString . ByteArray.convert . readKeyBytes get = do @@ -65,12 +88,17 @@ instance Binary Read where let (CryptoPassed unRead) = cipherInit readKeyBytes pure Read{..} -instance Show Read where - show (Read _ bs) = T.unpack $ T.concat ["<ReadKey ", encodeBase32Unpadded (ByteArray.convert bs), ">"] -instance Eq Read where - (Read _ left) == (Read _ right) = left == right +newtype StorageIndex = StorageIndex {unStorageIndex :: B.ByteString} deriving newtype (Eq) -newtype StorageIndex = StorageIndex {unStorageIndex :: B.ByteString} +instance Show StorageIndex where + show (StorageIndex si) = + T.unpack $ + T.concat + [ "<SI " + , T.take 4 . encodeBase32Unpadded . ByteArray.convert $ si + , "..." + , ">" + ] newtype WriteEnablerMaster = WriteEnablerMaster ByteArray.ScrubbedBytes @@ -256,3 +284,12 @@ signatureKeyFromBytes bs = do -- | Encrypt the signature key for inclusion in the SDMF share itself. encryptSignatureKey :: Write -> Signature -> B.ByteString encryptSignatureKey Write{unWrite} = ctrCombine unWrite nullIV . signatureKeyToBytes + +{- | Replace most of the tail of a string with a short placeholder. If the + string is not much longer than `n` then the result might not actually be + shorter. + + TODO: Deduplicate this between here and tahoe-chk. +-} +shorten :: Int -> T.Text -> T.Text +shorten n = (<> "...") . T.take n diff --git a/test/Spec.hs b/test/Spec.hs index 24ebcb92ebd9ed66bf2dbfe4d41ec43cf7310784..0519fe026e534c2817fa26afad506e15ea542a3e 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -148,9 +148,13 @@ tests = validRead = "URI:SSK-RO:ro7pnpq6duaduuolookwbv5lqy:xlwog3jxbgsuaddh3bsofwmyhncv7fanmo7ujhqiy26usx2v2neq" validVerify = "URI:SSK-Verifier:gz4s2zkkqy2geblvv77atyoppi:xlwog3jxbgsuaddh3bsofwmyhncv7fanmo7ujhqiy26usx2v2neq" - parsed = rights $ parse Tahoe.SDMF.pCapability "<test>" <$> [validWrite, validVerify, validRead] + parsed = rights $ parse Tahoe.SDMF.pCapability "<test>" <$> [validWrite, validRead, validVerify] assertEqual "parsing failed" 3 (length parsed) + let [Tahoe.SDMF.SDMFWriter writeCap, Tahoe.SDMF.SDMFReader readCap, Tahoe.SDMF.SDMFVerifier verifyCap] = parsed + + assertEqual "derived reader /= parsed reader" (Tahoe.SDMF.writerReader writeCap) readCap + assertEqual "derived verifier /= parsed verifier" (Tahoe.SDMF.readerVerifier readCap) verifyCap , testProperty "Share round-trips through bytes" $ property $ do share <- forAll shares