{"id":15373040,"url":"https://github.com/vi/chaoticfs","last_synced_at":"2026-05-27T12:32:05.513Z","repository":{"id":4848671,"uuid":"6003055","full_name":"vi/chaoticfs","owner":"vi","description":"Encrypting FUSE filesystem with \"false bottom\" allowing exposing the data only partially","archived":false,"fork":false,"pushed_at":"2015-09-29T11:22:49.000Z","size":161,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-19T21:52:39.585Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-09-28T21:00:59.000Z","updated_at":"2015-09-29T11:22:50.000Z","dependencies_parsed_at":"2022-09-10T18:22:01.209Z","dependency_job_id":null,"html_url":"https://github.com/vi/chaoticfs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vi/chaoticfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fchaoticfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fchaoticfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fchaoticfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fchaoticfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vi","download_url":"https://codeload.github.com/vi/chaoticfs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vi%2Fchaoticfs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33566872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T13:54:09.048Z","updated_at":"2026-05-27T12:32:05.495Z","avatar_url":"https://github.com/vi.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"chaoticfs is special encrypting \nFUSE-based filesystem that allows you to \n[partially expose](http://en.wikipedia.org/wiki/Plausible_deniability#Use_in_cryptography) \nyour data by using multiple entry points.\nThe filesystem is geared towards simplicity and\nnot stores any \"extra\" things like timestamps or\nsequence numbers which can make the task of\nreliably hiding the presence of additional data\ncomplexier.\n\n\nFeatures\n===\n* Random block allocation everywhere except of the first\ndirectory block that is the part of password, so no\nstatistical issues in the \"free space\" when partial\ndata is exposed;\n* No (access, modification, creation) dates and times;\n* No unencrypted signatures. The storage is a plain\nfile that looks like just a block of random data;\n* Easy extending: just append random data to storage\n(note: extension event is noticeable in statistics\nof free blocks).\n* Deleted files gets shredded (simple single\noverwrite by random data) by default;\n* Directories are stored as the whole thing \neach time, no \"holes\" for deleted files in directories;\n* No \"100% exposure\" possible by design.\nThere should be about 5% (by default) of some reserved \nunused random data which _maybe_ holds additional branchs.\nThere are additional random writes to unused blocks \nfrom time to time by default.\n* Blocks saving is randomized using 32-bit IVs. Each block write operation uses a new IV. Default cipher mode is nOFB to make IV affect the whole block.\n* Directory information is saved automatically from time to time. You should unmount chaoticfs properly to be sure about your data although, there's (currently) no \"dirty_writeback_centisecs\", only \"dirty_bytes\"...\n\nMisfeatures\n===\n* \n\n        Hacky unrefactored C cod\n        Segmentation fault\n        \n* O(n) in many places, no indexes;\n* The whole metadata (filenames, block lists) \nis kept in memory and serialized to storage at once\n* No fsck/recovery utility (yet)\n* No symlinks, attributes, sparse files \nand other advanced filesystem features\n* Not designed to be fast\n* Not designed to be reliable\n* Not designed to hold many files or big files\n* No tool to access the filesystem when\nFUSE is not available (yet)\n\nUsage\n===\n\nBasic commands\n---\n1. Generate some random file\n\n        $ dd if=/dev/urandom bs=1M count=100 of=data.rnd\n        \n2. Choose the blockpassword and mount the file\n\n        $ ./chaoticfs data.rnd  m\n        Enter the comma-separated blockpasswords list (example: \"2sK1m49se,5sldmIqaa,853svmqpsd\")\n        33password\n        No entries loaded, creating default entry\n        \n    Blockpassword is a password with embedded block number (the leading numeric part of the password). chaoticfs can reject a blockpassword in case of busy block.\n        \n3. Create something to make chaoticfs save the directory\n\n        $ mkdir m/test\n        $ fusermount -u m\n        \n4. Create another branch\n\n        ./chaoticfs data.rnd  m\n        Enter the comma-separated blockpasswords list (example: \"2sK1m49se,5sldmIqaa,853svmqpsd\")\n        33password,42secret\n        No entries loaded, creating default entry\n        echo qqq \u003e m/qqq\n        fusermount -u m\n        \n    The last specified blockpassword is the visible branch.\n    All other blockpasswords are only for marking which blocks should be preserved.\n        \nMessages:\n---\n* `No entries loaded, creating default entry` - can't load \nthe directory from the last blockpassword.\nIf you are creating a branch, then continue.\nIf it is because of incorrect password, then unmount and retry (otherwise you can overwrite the correct entry).\n\n* `No entries loaded for auxiliary branch, maybe need better password` - \ncan't load the directory for non-last blockpassword.\nchaoticfs aborts in this case.\n\n* `Duplicate/used block number` - trying to point the new blockpassword to already used block. Just choose some other block number (the leading numeric part of the password). Should not happen when not trying to create a branch. chaoticfs aborts in this case.\n\n* `Block number is out of range` - Block number from your password is too big. Choose smaller or extend the storage file.\n\n* `Directory loaded successfully` - Successfully read all directories.\n\nConcerns\n---\n* Don't rely on safety of the storage.\nUse SHA1SUMS, unmount, remount and check SHA1SUMS to be sure.\nYou can backup chaoticfs storage (~~comparing backups\nshould not releal too much info~~ /\\* TODO \\*/).\n* Other things can point to the \"missing\" secret parts\nof the directory.\n* Wrong password + unnoticed message or empiness of the directory =\u003e defuct branch. Forget to specify some branch =\u003e spoiled data in that branch.\n* Just the usage of chaoticfs (or similar \n\"false bottom\"-centered things) means you\nare hiding something. You will look silly if you disclose\nonly one branch...  \n    Use 3-10 branches and keep the actual number\n    of branches secret. \n    Combined with the previous point it means that\n    secure usage of this version of chaoticfs is\n    a bit inconvenient.\n    \nFilesystem format\n===\n\nBlock level\n---\nThe filesystem is made of fixed size blocks\n(BLOCK_SIZE, by default 8192).\nEach block can be free or contain [part of] directory or file content.\n\"Superblock\" is just the first directory's block.\nEach block is numbered from 0 to (fize_size/block_size-1).\n\nEach block is encrypted (by default rijndael-256\n in nOFB mode) with a key and\n 32-bit initialization vector. \n Trailing bytes of the IV buffer are \n initialized with zeroes. \n \nFor file's content, IV is generated \n randomly each time the block is written.\n The IV is stored in the directory.\n\nFor directory's content, IV is big-endian \n 32-bit block number; but directory blocks get\n addititionally \"scrambled\" by XORing the first\n 4 bytes longint over all remaining longints.\n ~~This is to make updated directory content\n appear to be completely random when comparing backups\n of chaoticfs storage.~~\n (I'm calling this \"Poor man's IV\")\n \n    \nDirectory\n---\nThere is only one directory per branch which \nstores all files and directories in the branch,\nidentified by the full path. Each entry of the\ndirectory is called direntry\n(\"mydirent\" structure in the code)\n\nDirectory is represented by empty file \nwith the path ending in \"/\".\n\nFile's path must not end in \"/\".\n\nThere always should be a \"/\" direntry.\n\nEach direntry have path, file length and block list fields.\nBlock list is the list of block numbers together with\nIVs for decryption.\n\nSerialized directory\n---\n\nThe directory is saved to dirent blocks.\nThe first dirent block number is stored in the\npassword itself.\n\nEach dirent block has a header and one or more entries.\n\nHeader is 8 random bytes, then 8-byte signature \"RndAllV0\".\n\nEach entry represents a direntry.\nIf direntry's block list can't fit in the block,\nanother \"duplicate\" dirent gets created\nwith nonzero block index offset.\n\nEach entry consists of:\n\n* direntry path's string length - 4 bytes, big endian;\n* direntry path - variable number of bytes;\n* file length - 8 bytes, big endian;\n* number of blocks in this entry - 4 bytes, big endian;\n* block index offset in this entry - 4 bytes, big endian;\n* block idexes and IVs - zero of more bytes\n    * a block index - 4 bypes, big endian;\n    * the IV for this block - 4 bytes.\n* block number for the next entry - 4 bytes, big endian;\n* offset in the block for the next entry -\n            4 bytes, big endian;\n* reserved - 8 bytes.\n            \nIf the block number and offset both equal to zero then this\nis the last direntry.\n\nExample:\n\n    #block 2:\n    \\x34\\xF5\\x12\\x46\\x79\\x12\\x15\\x05  # random bytes\n    RndAllV0 # signature\n    \n    \\x00\\x00\\x00\\x01 # name length\n    / # name\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 # file length\n    \\x00\\x00\\x00\\x00 # no blocks at all for directories\n    \\x00\\x00\\x00\\x00 # no blocks at all for directories\n    # no blocks\n    \\x00\\x00\\x00\\x02 # the next entry is also in block 2\n    \\x00\\x00\\x00\\x35 # the next direntry is at offset 53\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 - reserved\n    \n    \\x00\\x00\\x00\\x06 # name length\n    /qwer/ # name\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 # file length\n    \\x00\\x00\\x00\\x00 # no blocks at all for directories\n    \\x00\\x00\\x00\\x00 # no blocks at all for directories\n    # no blocks\n    \\x00\\x00\\x00\\x02 # the next entry is also in block 2\n    \\x00\\x00\\x00\\x5F # the next direntry is at offset 95\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 reserved\n    \n    \\x00\\x00\\x00\\x10 # name length\n    /qwer/secret.txt # name\n    \\x00\\x00\\x00\\x00\\x00\\x00\\xE0\\x00 # file length\n    \\x00\\x00\\x00\\x05 # only pointing to 5 first blocks here\n    \\x00\\x00\\x00\\x00 # first block is file's 0'th block\n    \\x00\\x00\\x23\\x5C # file's block 0 is has index 9015\n    \\x49\\xF4\\xF9\\xCC # file's block 0 use IV 49F9F9CC\n    \\x00\\x00\\x20\\xBF # file's block 1 is has index 9015\n    \\x44\\x56\\x23\\xC2 # file's block 1 use IV 445623C2\n    \\x00\\x00\\x12\\x05 # file's block 2 is has index 4613\n    \\x23\\xCD\\x98\\xD3 # file's block 2 use IV 23CD98D3\n    \\x00\\x00\\x03\\x45 # file's block 3 is has index 837\n    \\x6F\\xD4\\x23\\xB6 # file's block 3 use IV 6FD423B6\n    \\x00\\x00\\x04\\x23 # file's block 4 is has index 1059\n    \\x23\\x5D\\xF8\\x6F # file's block 4 use IV 235DF86F\n    \\x00\\x00\\x0F\\xDC # the next entry is in block 4045\n    \\x00\\x00\\x00\\x10 # the next direntry is at offset 16\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 reserved\n    \n    --\n    #block 4045:\n    \\x98\\xCF\\xDE\\xBF\\x93\\x23\\xF3\\xFF  # random bytes\n    RndAllV0 # signature\n    \\x00\\x00\\x00\\x00\\x00\\x00\\xE0\\x00 # file length\n    \\x00\\x00\\x00\\x02 # pointing to 2 remaining blocks here\n    \\x00\\x00\\x00\\x05 # first block here is file's 5'th block\n    \\x00\\x00\\x37\\x3D # file's block 5 is has index 14301\n    \\x8C\\xCC\\x32\\xDD # file's block 5 use IV 8CCC32DD\n    \\x00\\x00\\x34\\x12 # file's block 6 is has index 13330\n    \\xD3\\x97\\x57\\xC7 # file's block 6 use IV D49757C7\n    \\x00\\x00\\x00\\x00 # no next entry\n    \\x00\\x00\\x00\\x00 # no next entry\n    \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 reserved\n    \n    \n\n\nUse `--debug-print` to see the dump the directory.\n\nTodo\n===\n1. At least minimal refactor (split to multiple source files, isolate layers)\n2. Implement non-FUSE-based tool to access chaoricfs\n3. FTP interface to chaoticfs (to use in Windows)?\n4. Fsck/recovery tool? \n5. Change filesystem format for things to be O(log n), proper sudden shutdown behaviour, etc. to make it \"chaotic good\" system.\n6. Access to multiple branches using parts \n    of path to discriminate.\n    Storing of passwords file in \"master\" branch\n    to avoid typing lengthy password list for\n    all branchs every time on mount.\n\nFor just a normal encrypting FUSE filesystem see [EncFS](http://www.arg0.net/encfs).\n\nCreate issues on GitHub's tracker if you want\nsomething to be improved.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fchaoticfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvi%2Fchaoticfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvi%2Fchaoticfs/lists"}