{"id":34503619,"url":"https://github.com/santrancisco/relaysecret","last_synced_at":"2026-03-11T23:35:37.984Z","repository":{"id":39735501,"uuid":"294323704","full_name":"santrancisco/relaysecret","owner":"santrancisco","description":"A simple app which let you share file securely :) ","archived":false,"fork":false,"pushed_at":"2022-07-20T04:01:00.000Z","size":283,"stargazers_count":108,"open_issues_count":1,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-25T13:45:01.905Z","etag":null,"topics":["cryptography","fileshare","lambda","terraform"],"latest_commit_sha":null,"homepage":"https://www.relaysecret.com/ ","language":"JavaScript","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/santrancisco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-10T06:33:10.000Z","updated_at":"2025-12-03T17:35:04.000Z","dependencies_parsed_at":"2022-07-09T13:47:28.104Z","dependency_job_id":null,"html_url":"https://github.com/santrancisco/relaysecret","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/santrancisco/relaysecret","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santrancisco%2Frelaysecret","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santrancisco%2Frelaysecret/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santrancisco%2Frelaysecret/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santrancisco%2Frelaysecret/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/santrancisco","download_url":"https://codeload.github.com/santrancisco/relaysecret/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santrancisco%2Frelaysecret/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30407118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T22:36:59.286Z","status":"ssl_error","status_checked_at":"2026-03-11T22:36:57.544Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cryptography","fileshare","lambda","terraform"],"created_at":"2025-12-24T02:36:24.462Z","updated_at":"2026-03-11T23:35:32.976Z","avatar_url":"https://github.com/santrancisco.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Why another file sharing app?\n\nSeveral reasons:\n\n - Because firefoxsend was taken down and the walkthrough to deploy it is too complicated. \n - Magicwormhole is great but needs client app installed\n - Some solutions look amazing but turn out the plaintext is sent to the server and all encryption are done on the server side\n - Many solutions are well written, looks great but the code are complex, some even use websocket, others use webrtc ... with tons of dependency which make it impossible to review and prone to supply chain attack on each rebuild.\n - Other issues such as 3rd party tracking cookie is found, too much backend code that may be proned to attacks\n\n What relaysecret aim for:\n  - Extremely simple code to handle api calls (1 lambda function)\n  - File upload/download operation is all done by S3 signed url means no maintainance whatsover or worry about RCE on your server.\n  - Extremely simple frontend code with minimal javascript and no 3rd party dependency (everything is done using standard webcrypto)\n  - No complicated websocket, webrtc... no need for realtime refresh ... there is literally a button to refresh the list of files in room mode.\n\nHow do you \"scan for virus\" ? Do you send my files to Virustotal?\n\nAfter decrypting the content, a sha1 hash of the data is computed and send back to our lambda to fetch Virustotal scan result for that hash. So PLEASE PLEASE PLEASE do not put a single line with your ultimate 5 characters long AD password in it if you worry someone may MITM your traffic, discover the sha1 and run bruteforce on it. \n\n## Relay Secret\n\nVisit [https://www.relaysecret.com/](https://www.relaysecret.com/) to try it out.\n\nThis project has 3 parts:\n\n - The simple backend lambda function to generate signed url for user to upload, download and delete files from S3 \n - The frontend with half of the code took from [this project writen by meixler](https://github.com/meixler/web-browser-based-file-encryption-decryption/blob/master/web-browser-based-file-encryption-decryption.html) with some extra fetch calls sprinkel ontop to handle ajax calls to the lambda and upload/download from s3\n - The terraform code which deploy a lambda function, an api gateway and our encrypted s3 bucket with special CORs policy and expire rules to make it all work ;)\n\n\n## Room mode\n\nVisit [https://www.relaysecret.com/tunnel](https://www.relaysecret.com/tunnel) to try it out.\n\nThis mode let you create a \"room\". By visiting the URL above in another broser or device, entering the same room name, users can share and decrypt files from the same room. Note that all files in room will expire after 1 day.\n\nRoom mode does not generate a random temporary key material which you will find after the hash (#) in the URL. The key material here is simply the sha256 of the roomname itself so in a way, the roomname IS THE DEFAULT PASSWORD for files (if no extra password is used). Of course, same as before, the roomname or the tempkey stays in browser and do not go back to the server.\n\nUsers are encouraged to add password for extra protection. This password, same as before, will be used together with the sha256 value of the room name to make it much harder to bruteforce.\n\n## Process flow\n\n### Upload file\n\n - Frontend code visits lambda function to get a S3 signed POST url for file upload\n - Frontend code encrypt the data and upload encrypted blob to S3 bucket + tag object with original filename (this is still in plaintext)\n - Frontend code generates download url\n\n### Retrieve file\n\n - User visits `https://{server}/{object-key}#{key-material}`. Note that the key-material never leaves browser because it is behind anchor tag. User can choose to add his own password for extra security\n - Frontend code get signed url for the encrypted blob from the lambda\n - Frontend code download the encrypted blob and use key-material, combine with user provided password (if needed) to decrypt the blob and retrieve the plaintext content\n\n### Expire/Delete file\n\n - object-key is in the format: {numberofdaytilexpired}/{uniqueID} . The s3 bucket lifecycle policy is configured base on prefix \"numberofdaytilexpired\" and thus we can trust s3 to do its clean up automatically.\n - If the object is tagged with \"deleteondownload\", the delete ajax calls is triggered automatically after user click download the file\n - Users always have option to delete the file manually after every download if deleteondownload is not set.\n\n\n## Cryptography\n\nAll cryptography operations are implemented using using the Web Crypto API. Files are encrypted using AES-CBC 256-bit symmetric encryption. The encryption key is derived from the password and a random salt using PBKDF2 derivation with 10000 iterations of SHA256 hashing.\n\n## Deploy your own\n\nBackend can be deployed with terraform:\n    - Go into `./terraform/` and copy terraform.tfvars.example to terraform.tfvars and add your own Virtus Total key as well as your AWS account ID\n    - run `terraform apply` \n    - Note down the output which contains the API address for our frontend.\n    - Modify `./frontend/assets/config.js` with the API address above\n\nNow you just need to test it by hosting the frontend code somewhere. Note that webcrypto is ONLY AVAILABLE from \"secure origin\". Chrome requires the page to be loaded in \"https\" or from \"localhost\". to quickly test everything, you can try using python to host it locally `python3 -m http.server 8888` and visit localhost:8888 in the browser.\n\n\n## License\nThis project is licensed under the GPL-3.0 open source license.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsantrancisco%2Frelaysecret","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsantrancisco%2Frelaysecret","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsantrancisco%2Frelaysecret/lists"}