diff --git a/encode-ssk/Main.hs b/encode-ssk/Main.hs index cc50fb611105491eef02c21ce3c8d22e89af94e7..c69d3928855b566f738f70939148be54c2cccb46 100644 --- a/encode-ssk/Main.hs +++ b/encode-ssk/Main.hs @@ -7,6 +7,7 @@ import qualified Data.ByteString.Lazy as LB import qualified Data.Text as T import qualified Data.Text.IO as T import System.IO (stdin) +import Tahoe.Capability (confidentiallyShow) import qualified Tahoe.SDMF as SDMF import qualified Tahoe.SDMF.Keys as SDMF.Keys @@ -23,7 +24,7 @@ main = do let si = SDMF.Keys.unStorageIndex . SDMF.verifierStorageIndex . SDMF.readerVerifier . SDMF.writerReader $ writeCap mapM_ (uncurry (writeShare si)) (zip [0 :: Int ..] shareBytes) - T.putStrLn (SDMF.dangerRealShow (SDMF.SDMFWriter writeCap)) + T.putStrLn $ confidentiallyShow writeCap where e = 0x10001 writeShare si shnum = LB.writeFile $ (T.unpack . T.toLower . encodeBase32Unpadded $ si) <> "." <> show shnum diff --git a/flake.lock b/flake.lock index cc4e271876731b0a439efc6906977e7346233167..e3c3233096af1d811160f64a5fff53f189cea36d 100644 --- a/flake.lock +++ b/flake.lock @@ -32,6 +32,22 @@ "type": "github" } }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -95,6 +111,36 @@ "type": "github" } }, + "flake-utils_5": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1676283394, + "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -118,6 +164,29 @@ } }, "gitignore_2": { + "inputs": { + "nixpkgs": [ + "tahoe-capabilities", + "hs-flake-utils", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_3": { "inputs": { "nixpkgs": [ "tahoe-chk", @@ -167,6 +236,27 @@ "nixpkgs": "nixpkgs_2", "pre-commit-hooks": "pre-commit-hooks_2" }, + "locked": { + "lastModified": 1681762240, + "narHash": "sha256-+PLx9xHBvV70dA7Gy/+YTH1w3PcSOrGV0z0rGxts8jU=", + "ref": "main", + "rev": "a51e591b7fdf8881ac0237452691df7b1aceecd3", + "revCount": 10, + "type": "git", + "url": "https://whetstone.private.storage/jcalderone/hs-flake-utils.git" + }, + "original": { + "ref": "main", + "type": "git", + "url": "https://whetstone.private.storage/jcalderone/hs-flake-utils.git" + } + }, + "hs-flake-utils_3": { + "inputs": { + "flake-utils": "flake-utils_6", + "nixpkgs": "nixpkgs_3", + "pre-commit-hooks": "pre-commit-hooks_3" + }, "locked": { "lastModified": 1677773826, "narHash": "sha256-xJmOtHugr4k2zNhP/AF6JdIUnIEyM+TEspLn2n5kloc=", @@ -230,6 +320,22 @@ "type": "github" } }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1673800717, + "narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1677624842, @@ -246,6 +352,22 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1677624842, + "narHash": "sha256-4DF9DbDuK4/+KYx0L6XcPBeDHUFVCtzok2fWtwXtb5w=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d70f5cd5c3bef45f7f52698f39e7cc7a89daa7f0", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat", @@ -278,13 +400,13 @@ "inputs": { "flake-compat": "flake-compat_2", "flake-utils": [ - "tahoe-chk", + "tahoe-capabilities", "hs-flake-utils", "flake-utils" ], "gitignore": "gitignore_2", "nixpkgs": [ - "tahoe-chk", + "tahoe-capabilities", "hs-flake-utils", "nixpkgs" ], @@ -304,6 +426,36 @@ "type": "github" } }, + "pre-commit-hooks_3": { + "inputs": { + "flake-compat": "flake-compat_3", + "flake-utils": [ + "tahoe-chk", + "hs-flake-utils", + "flake-utils" + ], + "gitignore": "gitignore_3", + "nixpkgs": [ + "tahoe-chk", + "hs-flake-utils", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_3" + }, + "locked": { + "lastModified": 1677722096, + "narHash": "sha256-7mjVMvCs9InnrRybBfr5ohqcOz+pyEX8m22C1XsDilg=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "61a3511668891c68ebd19d40122150b98dc2fe3b", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", @@ -312,6 +464,7 @@ "hs-flake-utils", "nixpkgs" ], + "tahoe-capabilities": "tahoe-capabilities", "tahoe-chk": "tahoe-chk" } }, @@ -330,7 +483,7 @@ "type": "github" } }, - "tahoe-chk": { + "tahoe-capabilities": { "inputs": { "flake-utils": "flake-utils_3", "hs-flake-utils": "hs-flake-utils_2", @@ -339,6 +492,29 @@ "nixpkgs" ] }, + "locked": { + "lastModified": 1686164259, + "narHash": "sha256-T0U5B/DH+XDEXfBG7cHlTcMec4aUTDd+HH8Bsv0C71Y=", + "ref": "refs/heads/main", + "rev": "f0a11218007f6c2fe0f6b5e09e0993fe253f6e23", + "revCount": 9, + "type": "git", + "url": "https://whetstone.private.storage/PrivateStorage/tahoe-capabilities" + }, + "original": { + "type": "git", + "url": "https://whetstone.private.storage/PrivateStorage/tahoe-capabilities" + } + }, + "tahoe-chk": { + "inputs": { + "flake-utils": "flake-utils_5", + "hs-flake-utils": "hs-flake-utils_3", + "nixpkgs": [ + "hs-flake-utils", + "nixpkgs" + ] + }, "locked": { "lastModified": 1683552888, "narHash": "sha256-h9pgP/LYPtUr5CeCAhqt1XJyAqKTnkQxuIygiTulU/U=", diff --git a/flake.nix b/flake.nix index 83a55daf90f52f5b4226788555a4212847ba0f50..9ee3d72aabb1d248a287ae32ffe927047cf85166 100644 --- a/flake.nix +++ b/flake.nix @@ -10,6 +10,10 @@ url = "git+https://whetstone.private.storage/PrivateStorage/tahoe-chk?ref=refs/tags/0.1.0.1"; inputs.nixpkgs.follows = "hs-flake-utils/nixpkgs"; }; + tahoe-capabilities = { + url = "git+https://whetstone.private.storage/PrivateStorage/tahoe-capabilities"; + inputs.nixpkgs.follows = "hs-flake-utils/nixpkgs"; + }; }; outputs = { @@ -18,6 +22,7 @@ flake-utils, hs-flake-utils, tahoe-chk, + tahoe-capabilities, }: let ulib = flake-utils.lib; ghcVersion = "ghc8107"; @@ -34,6 +39,7 @@ packageName = "tahoe-ssk"; hsPkgsOverrides = hprev: hfinal: { tahoe-chk = tahoe-chk.outputs.packages.${system}.default; + tahoe-capabilities = tahoe-capabilities.outputs.packages.${system}.default; }; }; in { @@ -65,6 +71,8 @@ -- another way. Here, we get them from the Nix store. -- tahoe-chk ${tahoe-chk} + -- tahoe-capabilities + ${tahoe-capabilities} EOF ''; } diff --git a/src/Tahoe/SDMF/Internal/Capability.hs b/src/Tahoe/SDMF/Internal/Capability.hs index ba5acbf0698e6e9247aa60d0c52d992fcb6104c2..0e6249bc2d6a5ab1440d1e2ff68e9426b967a620 100644 --- a/src/Tahoe/SDMF/Internal/Capability.hs +++ b/src/Tahoe/SDMF/Internal/Capability.hs @@ -16,6 +16,7 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T import Data.Void (Void) import Data.Word (Word16) +import Tahoe.Capability (ConfidentialShowable (..)) import Tahoe.SDMF.Internal.Keys ( Read (readKeyBytes), StorageIndex (StorageIndex, unStorageIndex), @@ -42,6 +43,9 @@ data SDMF | SDMFWriter Writer deriving (Eq, Show) +instance ConfidentialShowable SDMF where + confidentiallyShow = dangerRealShow + -- | A verify capability for an SDMF object. data Verifier = Verifier { verifierStorageIndex :: StorageIndex @@ -49,6 +53,9 @@ data Verifier = Verifier } deriving (Eq, Show) +instance ConfidentialShowable Verifier where + confidentiallyShow = dangerRealShow . SDMFVerifier + -- | A read capability for an SDMF object. data Reader = Reader { readerReadKey :: Read @@ -56,6 +63,9 @@ data Reader = Reader } deriving (Eq, Show) +instance ConfidentialShowable Reader where + confidentiallyShow = dangerRealShow . SDMFReader + -- | A write capability for an SDMF object. data Writer = Writer { writerWriteKey :: Write @@ -63,6 +73,9 @@ data Writer = Writer } deriving (Eq, Show) +instance ConfidentialShowable Writer where + confidentiallyShow = dangerRealShow . SDMFWriter + -- | Diminish a write key to a read key and wrap it in a reader capability. deriveReader :: Write -> Digest SHA256 -> Maybe Reader deriveReader w fingerprint = Reader <$> readKey <*> verifier @@ -170,6 +183,7 @@ rfc3548Alphabet :: [Char] rfc3548Alphabet = "abcdefghijklmnopqrstuvwxyz234567" -- | Show an SDMF capability, including all secret information. +{-# DEPRECATED dangerRealShow "Use the ConfidentialShowable instance" #-} dangerRealShow :: SDMF -> T.Text dangerRealShow (SDMFVerifier Verifier{verifierStorageIndex, verifierVerificationKeyHash}) = T.concat diff --git a/tahoe-ssk.cabal b/tahoe-ssk.cabal index f6b99a4bff38c047d29ccb320e14d1bd1d21fd2e..380aeb6b7b7ed3a40dd74448def01014ceb33514 100644 --- a/tahoe-ssk.cabal +++ b/tahoe-ssk.cabal @@ -104,6 +104,7 @@ library , cryptonite , megaparsec , memory + , tahoe-capabilities , text , x509 @@ -143,6 +144,7 @@ test-suite tahoe-ssk-test , hedgehog , megaparsec , memory + , tahoe-capabilities , tahoe-chk , tahoe-ssk , tasty @@ -181,5 +183,6 @@ executable encode-ssk , binary , bytestring , cryptonite + , tahoe-capabilities , tahoe-ssk , text diff --git a/test/Spec.hs b/test/Spec.hs index 70e7b1e1cf493701c3be927dc74c9694210a8cd0..30a209f7f909b1b94e1dc1d41a35f9f144a83762 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -8,8 +8,8 @@ import Hedgehog ( tripping, ) -import Control.Monad.Fail (MonadFail) import Control.Monad (when) +import Control.Monad.Fail (MonadFail) import Control.Monad.IO.Class (liftIO) import Crypto.Cipher.Types (makeIV) import Crypto.Hash (digestFromByteString) @@ -27,6 +27,7 @@ import Generators (capabilities, encodingParameters, genRSAKeys, ivLength, share import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import System.IO (hSetEncoding, stderr, stdout, utf8) +import Tahoe.Capability (confidentiallyShow) import qualified Tahoe.SDMF import Tahoe.SDMF.Internal.Capability (deriveVerifier) import Tahoe.SDMF.Internal.Keys (signatureKeyFromBytes, signatureKeyToBytes) @@ -144,13 +145,13 @@ tests = "write enabler: expected /= derived" expectedWriteEnabler (fmtKey derivedWriteEnabler) - , testCase "known-correct SDMF capability strings round-trip through parse . dangerRealShow" $ do + , testCase "known-correct SDMF capability strings round-trip through parse . confidentiallyShow" $ do let validWrite = "URI:SSK:vbopclzrkxces6okoqfarapmou:xlwog3jxbgsuaddh3bsofwmyhncv7fanmo7ujhqiy26usx2v2neq" validRead = "URI:SSK-RO:ro7pnpq6duaduuolookwbv5lqy:xlwog3jxbgsuaddh3bsofwmyhncv7fanmo7ujhqiy26usx2v2neq" validVerify = "URI:SSK-Verifier:gz4s2zkkqy2geblvv77atyoppi:xlwog3jxbgsuaddh3bsofwmyhncv7fanmo7ujhqiy26usx2v2neq" parsed = rights $ parse Tahoe.SDMF.pCapability "<test>" <$> [validWrite, validRead, validVerify] - serialized = Tahoe.SDMF.dangerRealShow <$> parsed + serialized = confidentiallyShow <$> parsed assertEqual "parsing failed" 3 (length parsed) assertEqual "original /= serialized" [validWrite, validRead, validVerify] serialized @@ -160,13 +161,13 @@ tests = derivedVerifier = Tahoe.SDMF.readerVerifier readCap assertEqual "derived reader /= parsed reader" derivedReader readCap - assertEqual "serialized derived reader /= original" (Tahoe.SDMF.dangerRealShow . Tahoe.SDMF.SDMFReader $ derivedReader) validRead + assertEqual "serialized derived reader /= original" (confidentiallyShow derivedReader) validRead assertEqual "derived verifier /= parsed verifier" derivedVerifier verifyCap - assertEqual "serialized derived verifier /= original" (Tahoe.SDMF.dangerRealShow . Tahoe.SDMF.SDMFVerifier $ derivedVerifier) validVerify - , testProperty "SDMF capabilities round-trip through dangerRealShow . parse pCapability" $ + assertEqual "serialized derived verifier /= original" (confidentiallyShow derivedVerifier) validVerify + , testProperty "SDMF capabilities round-trip through confidentiallyShow . parse pCapability" $ property $ do cap <- forAll capabilities - tripping cap Tahoe.SDMF.dangerRealShow (parse Tahoe.SDMF.pCapability "<text>") + tripping cap confidentiallyShow (parse Tahoe.SDMF.pCapability "<text>") , testProperty "Share round-trips through bytes" $ property $ do share <- forAll shares