{"id":15831505,"url":"https://github.com/somajitdey/juff","last_synced_at":"2025-06-25T16:02:42.090Z","repository":{"id":163920160,"uuid":"335676103","full_name":"SomajitDey/JuFF","owner":"SomajitDey","description":"Git-based secure messaging \u0026 file Sharing -- all from just a single bash script !! No long-term cloud storage of user data. Fully transparent and semi-decentralized. Text-based UI. Uses free services only...no hosting costs.","archived":false,"fork":false,"pushed_at":"2021-03-12T16:11:41.000Z","size":180,"stargazers_count":4,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2024-10-12T12:24:24.907Z","etag":null,"topics":["bash","chat","curl","file-sharing","foss","git","gpg","gpg-encryption","gpg-signatures","linux","messaging","privacy","public-key-encryption","secure-file-exchange","secure-messenger","semi-decentralized","terminal-based","texting","unix","wsl"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SomajitDey.png","metadata":{"files":{"readme":"readme.txt","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-03T15:53:55.000Z","updated_at":"2024-01-19T10:28:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"24759898-e2e2-4d95-a86a-5c3073296084","html_url":"https://github.com/SomajitDey/JuFF","commit_stats":{"total_commits":178,"total_committers":3,"mean_commits":"59.333333333333336","dds":0.1573033707865169,"last_synced_commit":"cd003cd532a7d05b30a732315770a0744d1ff430"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SomajitDey%2FJuFF","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SomajitDey%2FJuFF/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SomajitDey%2FJuFF/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SomajitDey%2FJuFF/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SomajitDey","download_url":"https://codeload.github.com/SomajitDey/JuFF/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243695454,"owners_count":20332622,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["bash","chat","curl","file-sharing","foss","git","gpg","gpg-encryption","gpg-signatures","linux","messaging","privacy","public-key-encryption","secure-file-exchange","secure-messenger","semi-decentralized","terminal-based","texting","unix","wsl"],"created_at":"2024-10-05T12:03:48.040Z","updated_at":"2025-03-15T06:32:34.549Z","avatar_url":"https://github.com/SomajitDey.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"JuFF---Just For Fun (C)2021, Somajit Dey \u003cdey.somajit@gmail.com\u003e\nLicense: GPL-v3-or-later\n\n\"Hello World. I am JuFF :)\"\n\nJuFF is a secure messaging \u0026 file-sharing app run from an open bash script,\nwith git as its backend. All messages and files going through JuFF are strongly\nencrypted and signed using GNU Privacy Guard. There is no long-term cloud storage\ninvolved, your files and texts live in a server only for a short while (i.e. until \nyou download them or till a preset expiry), and that too in a fully encrypted form.\n\nThe most exciting thing other than its promise of security is its minimalism. JuFF\ncomes as a single bash script! You just need to have bash, git \u0026 curl installed;\nand they usually are in standard Linux systems, including WSL. Just run JuFF.bash \nand you have a totally secure chat+file-sharing app!\n\nSo lets see how it all works.\n\nIn GitHub, JuFF has a dedicated repo. You get an access token to it from me or others\nalready using juFF, so that you can use JuFF without having a GitHub account yourself.\nThis access token is just an entry ticket to JuFF if you will, not your password \nor anything that private. JuFF asks for that token from you on the first run only, and \nnever again once your local inbox is setup.\n\nOn the first run, JuFF sets up the local inbox on your system, asks for your name \u0026 email\n, creates a private-public key-pair corresponding to that name \u0026 email combination and\ngives you your key-ID and a private my_JuFF.key file that holds your private key and SHA-256\npassphrase. So, save that file someplace safe as you would need it to gain access to your JuFF \naccount on any other machine. Now you just gotta email that key-ID to me. In the background,\nJuFF sends your public key to me. I then verify your public key with the keyID you send over \nemail, and hence your email verification is done. Following that, the public key is hosted\nat Somajit/JuFF-KeyServer at GitHub.\n\nNow you can start sending texts and share files with people whose public keys are already \nhosted. Because of the email verification done before hosting every public key, you can trust\nall the keys found at the abovementioned key-server. In future, the registration might become \nautomated, and the KeyID might need to be sent to a public mailing-list instead. (See the end\nof this text for more future directions).\n\nFile sharing is easy. Just enter the absolute path of the file to be sent at the appropriate \nprompt, or if you are using a Linux-box, just drag-n-drop the file at the prompt.\n\nJuFF is not meant for syncing across multiple devices. However, that by no means reduces \nportability. All data assciated with your JuFF account stays within your JuFF inbox. Therefore, \nyou can just carry it with you, on a thumbdrive e.g., or sync it with your cloud storage account\nsuch as Dropbox, Google Drive, Onedrive or Pcloud. On a new machine, just direct JuFF to that\ninbox, and it takes on from there. At your option, you can also keep your JuFF inbox encrypted.\nHowever, JuFF won't do that encryption as of now, you gotta do it on your own.\n\nWhat happens when you send something?\n\nFirst it gets signed with your private key and encrypted with the recipient's public key. Hence,\nonly the recipent will be able to decrypt it and verify your signature using your public key.\nNow, it gets sent to an ephemeral file-hosting server such as file.io, oshi.at or 0x0.st\nThe great thing about these servers is that they are free and file hosting is transient...the\nhosted files either expire after a set time or get deleted as soon as you download them.\nFollowing the upload to these servers you get a download link, which JuFF then pushes to git\nafter signing and encrypting with your private key. So git does not host your encrypted \ncorrespondence, but rather its download link only. This keeps the repo size managable and makes\nyour correspondence ultimately untraceable. No one can read the links hosted at git other than \nthe desired recipient, as these are encrypted...hence no one else can download something and \nmake it get deleted from the server. \n\nThe rest of the story is simple. The recipent pulls from the repo, sees your pushed commit and\nextracts the URLs therefrom. JuFF then pulls your public key from the key-server to verify your\nsignature. Once everthing is found in order, the files are downloaded and decrypted and your \nsignatures on them verified. Now your correspondence is saved in your recipients local inbox.\n\nSpecifics:\n\nSo how secure is git as a backend? Especially when I am giving every participant access to push\nto the repo. Anyone can rewrite git history or edit or delete your previous commit(s), right?\nTrue, but here comes GitHub in play. The branch where JuFF pushes is a protected branch that\ndoes not allow force pushes. The branch is also restricted to be a linear branch only and branch\ndeletion is not allowed. Also the access tokens I am giving out cannot delete the repo.\n\nSo the only worry left is what if someone edits or deletes some of your commits and pushes. Well,\ngit is a VCS folks, keeping track is its job. All JuFF needs to do is to track the git history \nsince the last pull it performed on its side. When you run JuFF, it pulls and then tracks every \nsingle commit since the last time it pulled in reverse chronological order. This is made simpler\nbecause every legitimate commit in JuFF would only add files, and not edit any. This is possible\nbecause every URL filename is timestamped and contain the author's userid, which makes it unique.\n\nSuppose I commited something for you when you were offline. Someone else corrupted it and commited \nagain. Your JuFF then first sees the corrupted commit and caches the files unique to that commit.\nFor this, it uses git restore. It then sees my original commit and again caches the files unique to\nmy commit. If a file was edited by the attacker, then that file would already have a copy in the \ncache. So, when reading from my commit, JuFF simply replaces the (corrupt) file in the cache with\nmy original. If on the other hand, the attacker simply deleted a file from my commit, JuFF would\ngit restore that file from my commit and cache it.\n\nOnce the cache is built by running through all the commits individually this way, downloading starts\nfrom the decrypted URLs. Once download is successful, the URL file is removed from the cache. So on \nthe next run, if JuFF finds URL files lying in the cache from a previous run, it attempts to download \nthem again. Thus, nothing is lost even if you face connection problems.\n\nWhat if you lose your private key or my_JuFF.key?\n\nYou simply tell JuFF to create a new key-pair for you. Then again you email me the new key-ID as an \nauthorization to change your public key on the key-server. Once I update your public key, all new \ncorrespondence would use that new public key only. Even if an attacker gets hold of your old\nprivate key, he won't be able to succeed, because the recipient won't be able to match his signature \nagainst your updated public key.\n\nHow is this implemented? The public keys are imported just in time and not stored apriori. And here\nis another key thing. To verify files unique to a commit, JuFF imports only that version of the \npublic key that is present in the last commit in the key-server before the commit-timestamp of the \nsaid commit in the JuFF repo. For illustration, suppose A commits at time t in the JuFF repo. For all\nintents and purposes, A would only use the private key corresponding to last hosted his public key. \nHence, the correct public key for decrypting A's commit, would be available in the last key-server \ncommit before time t! Thats what JuFF imports. What if X now steals the private key of A and commits\nto JuFF? If A is prompt in responding to the theft, that commit would happen only after A has published \na new public key. Hence, all recipients then on would import A's latest public key for the attacker's \nlatest commit, and the attacker would be defeated. This way, we don't need revocation certificates \nanymore.\n\nFuture work:\n\n1) Users may choose to be anonymous. If a user chooses to be so, his/her JuFF account will be the SHA-256\nhash of his/her name#email. So, spammers cannot get his/her validated email id from the JuFF key-server.\nSomeone who knows his/her name \u0026 email both, however, will be able to send him/her messages. But one can\nstill choose a name and not tell others about it...which then makes his/her JuFF account totally anonymous \neven if others know his/her email id.\n\n2) JuFF can be made to make only signed commits to the JuFF repo. The public keys may already be added to\nGitHub so every commit can be verified and displayed as such, for transparency.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomajitdey%2Fjuff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsomajitdey%2Fjuff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomajitdey%2Fjuff/lists"}