<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aayush </title>
    <description>The latest articles on DEV Community by Aayush  (@aayushbankar).</description>
    <link>https://dev.to/aayushbankar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3676316%2F602dbc63-785f-4453-a356-dd4e3397243a.jpeg</url>
      <title>DEV Community: Aayush </title>
      <link>https://dev.to/aayushbankar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aayushbankar"/>
    <language>en</language>
    <item>
      <title>How I Built an End-to-End Encrypted File Sharing App with Flask and ChaCha20 in 30 Days</title>
      <dc:creator>Aayush </dc:creator>
      <pubDate>Fri, 23 Jan 2026 17:20:26 +0000</pubDate>
      <link>https://dev.to/aayushbankar/how-i-built-an-end-to-end-encrypted-file-sharing-app-with-flask-and-chacha20-in-30-days-9k8</link>
      <guid>https://dev.to/aayushbankar/how-i-built-an-end-to-end-encrypted-file-sharing-app-with-flask-and-chacha20-in-30-days-9k8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAayushbankar%2Fonetimeshare%2Fmain%2Fdocs%2Fimages%2Fui%2Fupload_success.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAayushbankar%2Fonetimeshare%2Fmain%2Fdocs%2Fimages%2Fui%2Fupload_success.png" alt="OneTimeShare Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built a self-destructing file sharing app in 30 days. Files are encrypted with ChaCha20-Poly1305, passwords are hashed with Argon2id, and everything deletes after one download. On launch day, I found a race condition that would have let attackers bypass my password limit. Here's the full story.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Aayushbankar" rel="noopener noreferrer"&gt;
        Aayushbankar
      &lt;/a&gt; / &lt;a href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;
        onetimeshare
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Secure, one-time file sharing web app
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🚀 One-Time Secure File/Text Sharing App&lt;/h1&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;30-Day Build Challenge&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5d23c606fa875c95ae6c0861c4ccdea5317f003e6296d4b4f6bb95edf74ddec9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d4c6976652d737563636573733f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/5d23c606fa875c95ae6c0861c4ccdea5317f003e6296d4b4f6bb95edf74ddec9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d4c6976652d737563636573733f7374796c653d666c61742d737175617265" alt="Status"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/Aayushbankar/onetimeshare/actions/workflows/ci.yml/badge.svg"&gt;&lt;img src="https://github.com/Aayushbankar/onetimeshare/actions/workflows/ci.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/bd60a4108b5c97c94efda272f457a32229cbd573eac70cd83d6ad63f13ee2b8b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e67756167652d507974686f6e2d79656c6c6f773f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/bd60a4108b5c97c94efda272f457a32229cbd573eac70cd83d6ad63f13ee2b8b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e67756167652d507974686f6e2d79656c6c6f773f7374796c653d666c61742d737175617265" alt="Language"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/152aa2a37725b9fd554b28ff24d270f6071c67927a63e6d635a55c8e188e20c7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/152aa2a37725b9fd554b28ff24d270f6071c67927a63e6d635a55c8e188e20c7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e3f7374796c653d666c61742d737175617265" alt="License"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7d9b26faae100e1e30249832edaf475d869255c2bf33642db916b94f5e27ddf0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4465706c6f796d656e742d52656e6465722d707572706c653f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/7d9b26faae100e1e30249832edaf475d869255c2bf33642db916b94f5e27ddf0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4465706c6f796d656e742d52656e6465722d707572706c653f7374796c653d666c61742d737175617265" alt="Deployment"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔴 LIVE DEMO&lt;/strong&gt;: &lt;a href="https://onetimeshare.onrender.com" rel="nofollow noopener noreferrer"&gt;https://onetimeshare.onrender.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📸 Screenshots&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Aayushbankar/onetimeshare/docs/images/ui/home.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAayushbankar%2Fonetimeshare%2Fdocs%2Fimages%2Fui%2Fhome.png" alt="Home Page" width="45%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Aayushbankar/onetimeshare/docs/images/ui/upload_success.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAayushbankar%2Fonetimeshare%2Fdocs%2Fimages%2Fui%2Fupload_success.png" alt="Upload Success" width="45%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Aayushbankar/onetimeshare/docs/images/ui/download.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAayushbankar%2Fonetimeshare%2Fdocs%2Fimages%2Fui%2Fdownload.png" alt="Download Page" width="45%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Aayushbankar/onetimeshare/docs/images/ui/admin_dashboard.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAayushbankar%2Fonetimeshare%2Fdocs%2Fimages%2Fui%2Fadmin_dashboard.png" alt="Admin Dashboard" width="45%"&gt;&lt;/a&gt;
&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🧐 The Problem&lt;/h2&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Sharing sensitive information (API keys, passwords, configuration files) via email, Discord, or WhatsApp is insecure. Third-party services like Pastebin or WeTransfer store your data on their servers, creating a privacy risk.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;💡 The Solution&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Build a lightweight, containerized Python web application&lt;/strong&gt; that allows you to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload a file or text snippet.&lt;/li&gt;
&lt;li&gt;Generate a unique, secure link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permanently delete&lt;/strong&gt; the data from the server immediately after it is viewed once (or after a short timer expires).&lt;/li&gt;
&lt;/ol&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project Overview&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Build a secure, one-time file sharing application within 30 days.
&lt;strong&gt;Timeline&lt;/strong&gt;: December 24, 2025 → January 24, 2026
&lt;strong&gt;Tech Stack&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Python / Flask&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: Dockerized Redis (Ephemeral storage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerization&lt;/strong&gt;: Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI&lt;/strong&gt;: Bootstrap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD&lt;/strong&gt;: GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Quick Start (Docker - Recommended)&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;The fastest way…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;







&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every developer has done it.&lt;/p&gt;

&lt;p&gt;Shared an API key in Slack. Sent a &lt;code&gt;.env&lt;/code&gt; file over WhatsApp. Pasted credentials into a Discord DM.&lt;/p&gt;

&lt;p&gt;These messages live forever. They're indexed. They're searchable. They're a breach waiting to happen.&lt;/p&gt;

&lt;p&gt;I wanted a tool where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Files are encrypted at rest (the server can't read them)&lt;/li&gt;
&lt;li&gt;Files delete themselves after one download&lt;/li&gt;
&lt;li&gt;Password protection is zero-knowledge (the key never touches the server)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Existing tools either store data indefinitely, require accounts, or cost enterprise money.&lt;/p&gt;

&lt;p&gt;So I built my own. In 30 days. In public.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flask (Python 3.13)&lt;/td&gt;
&lt;td&gt;Lightweight, flexible, I know it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;TTL auto-expiry = perfect for ephemeral data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ChaCha20-Poly1305&lt;/td&gt;
&lt;td&gt;Constant-time, used by Signal, no AES-NI needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;KDF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Argon2id&lt;/td&gt;
&lt;td&gt;Memory-hard, GPU-resistant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker + Render&lt;/td&gt;
&lt;td&gt;Free tier, Gunicorn-ready&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why ChaCha20 over AES-GCM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AES-GCM performance varies based on hardware (AES-NI). ChaCha20-Poly1305 is software-optimized and constant-time everywhere — critical for containerized deployments where you don't control the CPU.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Build: Week by Week
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Week 1: Foundation (Days 1-7)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Day 1:&lt;/strong&gt; Flask application factory, Dockerfile, docker-compose with Redis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 2:&lt;/strong&gt; Core upload endpoint. UUID filenames (path traversal prevention), extension validation, 20MB limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 3:&lt;/strong&gt; The first "graveyard" moment.&lt;/p&gt;

&lt;p&gt;I built an entire &lt;code&gt;RedisService&lt;/code&gt; class. Flask ignored it completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bug:&lt;/strong&gt; Missing &lt;code&gt;__init__.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two hours. Zero bytes of actual code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 6:&lt;/strong&gt; Atomic self-destruct with Redis &lt;code&gt;WATCH/MULTI/EXEC&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hgetall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;multi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Week 1 Bug Count:&lt;/strong&gt; 29&lt;/p&gt;




&lt;h3&gt;
  
  
  Week 2: The Security Core (Days 8-14)
&lt;/h3&gt;

&lt;p&gt;This is where 80% of the bugs lived.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 10: The HTTP Statelessness Disaster&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I implemented password retry limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# THE BUG
&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;block_user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;26 bugs in one day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All from the same root cause: I forgot that HTTP is stateless. Python variables don't persist across requests. The retry counter had to live in Redis.&lt;/p&gt;

&lt;p&gt;The lesson: &lt;em&gt;Every persistent state must be externalized.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 14: The DoS I Built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My "security" feature: delete files after 5 wrong passwords.&lt;/p&gt;

&lt;p&gt;The attack I didn't consider: anyone could delete anyone's file by sending 5 wrong passwords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Lock files, don't delete them. Deletion = DoS vector.&lt;/p&gt;




&lt;h3&gt;
  
  
  Week 3: Encryption and Hardening (Days 15-21)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Day 16: Streaming Encryption&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The naive approach: read entire file into memory, encrypt, write back.&lt;/p&gt;

&lt;p&gt;The problem: 500MB file = 500MB RAM = OOM kill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; 64KB streaming chunks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt_file_chunked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;base_nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Unique per file
&lt;/span&gt;    &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChaCha20Poly1305&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;outfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;chunk_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;chunk_nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;increment_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;outfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;big&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;outfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;chunk_num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base_nonce&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical detail:&lt;/strong&gt; Nonce = &lt;code&gt;base_nonce + chunk_number&lt;/code&gt; using arithmetic addition. XOR would cause collisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 20: Load Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ran Locust across 3 tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1 (30 users):&lt;/strong&gt; 174 RPS, 355ms p95&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2 (100 users):&lt;/strong&gt; 116 RPS, 1.3s p95&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3 (300 users):&lt;/strong&gt; 97 RPS, 3.5s p95&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Grade A, 0% error rate. Production-ready.&lt;/p&gt;




&lt;h3&gt;
  
  
  Week 4: Launch (Days 22-30)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Days 22-25:&lt;/strong&gt; CI/CD (GitHub Actions), Playwright E2E tests, security headers (CSP, HSTS, X-Frame-Options).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 29:&lt;/strong&gt; Deep security audit. Fixed nonce edge cases, added constant-time comparison.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 30:&lt;/strong&gt; The audit that almost didn't happen.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Day 30 Crisis
&lt;/h2&gt;

&lt;p&gt;9 PM. Launch day. Everything ready.&lt;/p&gt;

&lt;p&gt;I almost shipped.&lt;/p&gt;

&lt;p&gt;Then I ran one more pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Critical Bug #1: Race Condition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# THE BUG
&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;attempt_to_unlock&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;attempt_to_unlock&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;redis_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store_file_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The attack:&lt;/strong&gt; 50 parallel requests hit this simultaneously.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All 50 read &lt;code&gt;attempts = 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;All 50 compute &lt;code&gt;attempts = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;All 50 write &lt;code&gt;attempts = 1&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 50 password guesses for the price of 1. My "5 attempt limit" was fiction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Atomic increment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# THE FIX
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment_file_attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hincrby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attempt_to_unlock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;HINCRBY&lt;/code&gt; is atomic. Redis serializes operations. No race condition possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Critical Bug #2: Missing CSRF
&lt;/h3&gt;

&lt;p&gt;Admin login had no CSRF token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The attack:&lt;/strong&gt; Login CSRF. Attacker forces victim to log into attacker's account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Flask-WTF. 15 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│                     CLIENT                           │
│  Browser → Drag/Drop → Password (Optional)          │
└─────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────┐
│                 FLASK + GUNICORN                     │
│  Routes (HTTP) → Services (Logic) → Utils (Crypto)  │
└─────────────────────────────────────────────────────┘
                          │
           ┌──────────────┼──────────────┐
           ▼                             ▼
┌──────────────────────┐    ┌─────────────────────────┐
│       REDIS          │    │    ENCRYPTED DISK       │
│  Metadata (TTL: 5h)  │    │  ChaCha20-Poly1305      │
│  Atomic Counters     │    │  UUID Filenames         │
│  Rate Limit State    │    │  64KB Chunks            │
└──────────────────────┘    └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Stats
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Days&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commits&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bugs Fixed&lt;/td&gt;
&lt;td&gt;100+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Critical Vulns (Day 30)&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lines of Code&lt;/td&gt;
&lt;td&gt;~5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Key Lessons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Read-Modify-Write = Race Condition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're incrementing anything in a distributed system, use atomic operations. Always.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Security is Logic, Not Libraries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had ChaCha20. I had Argon2. I still had a brute-force bypass in the application logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Final Audit is Non-Negotiable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I'd shipped on Day 29, I'd be writing an incident report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Build in Public Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The pressure of knowing people were watching made me do the extra audit. That audit caught the race condition.&lt;/p&gt;




&lt;h2&gt;
  
  
  Future Roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] S3 integration for files &amp;gt; 20MB&lt;/li&gt;
&lt;li&gt;[ ] Public API for CLI access&lt;/li&gt;
&lt;li&gt;[ ] Mobile-optimized UI&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://onetimeshare.onrender.com" rel="noopener noreferrer"&gt;onetimeshare.onrender.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;github.com/Aayushbankar/onetimeshare&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you learned something, I'd appreciate a follow. I build in public and document everything — including the failures.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the scariest bug you've found on launch day?&lt;/strong&gt; 👇&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>python</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Day 0: Launching OneTimeShare30 - My 30-Day Public Build Challenge</title>
      <dc:creator>Aayush </dc:creator>
      <pubDate>Wed, 24 Dec 2025 17:38:11 +0000</pubDate>
      <link>https://dev.to/aayushbankar/day-0-launching-onetimeshare30-my-30-day-public-build-challenge-4cb2</link>
      <guid>https://dev.to/aayushbankar/day-0-launching-onetimeshare30-my-30-day-public-build-challenge-4cb2</guid>
      <description>&lt;h1&gt;
  
  
  Day 0: Launching #OneTimeShare30 - A 30-Day Public Build Challenge
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1556075798-4825dfaaf498%3Fixlib%3Drb-4.0.3%26auto%3Dformat%26fit%3Dcrop%26w%3D1200%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1556075798-4825dfaaf498%3Fixlib%3Drb-4.0.3%26auto%3Dformat%26fit%3Dcrop%26w%3D1200%26q%3D80" alt="OneTimeShare Banner" width="1200" height="795"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Lukas Blazek on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Date:&lt;/strong&gt; December 24, 2025&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Status:&lt;/strong&gt; Planning Phase&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;github.com/Aayushbankar/onetimeshare&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Hashtag:&lt;/strong&gt; &lt;a href="https://twitter.com/hashtag/OneTimeShare30" rel="noopener noreferrer"&gt;#OneTimeShare30&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Twitter:&lt;/strong&gt; &lt;a href="https://twitter.com/enthusiadev" rel="noopener noreferrer"&gt;@enthusiadev&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Linkedin:&lt;/strong&gt; &lt;a href="https://linkedin.com/aayushbankar" rel="noopener noreferrer"&gt;@aayushbankar &lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🎄 Christmas Eve Announcement
&lt;/h2&gt;

&lt;p&gt;It's December 24th, 10:00 PM, and I'm sitting here on Christmas Eve with an idea that won't wait. Starting tomorrow, I'm embarking on a 30-day public build challenge to create something I genuinely need: &lt;strong&gt;a secure, one-time file sharing application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why today? Why not wait until after the holidays? Because good ideas don't follow calendars, and the problem I'm solving doesn't take time off.&lt;/p&gt;
&lt;h2&gt;
  
  
  🧐 The Problem That Keeps Me Up at Night
&lt;/h2&gt;

&lt;p&gt;As a developer and student, I constantly face this dilemma:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I share this API key/config file/password securely &lt;em&gt;right now&lt;/em&gt;?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My current options all suck:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email attachments&lt;/strong&gt; - They live forever on multiple servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discord/WhatsApp&lt;/strong&gt; - University projects with sensitive keys exposed in group chats&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pastebin&lt;/strong&gt; - Public by default, retention unclear&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Drive/WeTransfer&lt;/strong&gt; - Third-party servers storing my data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-built solutions&lt;/strong&gt; - Time-consuming, over-engineered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Just last week, I needed to share a Google Gemini API key with a batchmate for our machine learning project.&lt;/strong&gt; I spent 15 minutes debating the "least bad" option before settling on splitting the key across multiple messages. There has to be a better way.&lt;/p&gt;

&lt;p&gt;Think about it: &lt;strong&gt;API keys, configuration files with database credentials, project secrets, authentication tokens&lt;/strong&gt; - we're sharing these daily through completely insecure channels.&lt;/p&gt;
&lt;h2&gt;
  
  
  💡 The Vision: OneTimeShare
&lt;/h2&gt;

&lt;p&gt;Imagine this workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You upload a file or paste text (like that Gemini API key)&lt;/li&gt;
&lt;li&gt;You get a unique, unguessable link&lt;/li&gt;
&lt;li&gt;You share that link with one person&lt;/li&gt;
&lt;li&gt;They view/download the content &lt;strong&gt;once&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The data is &lt;strong&gt;permanently deleted&lt;/strong&gt; from the server&lt;/li&gt;
&lt;li&gt;The link becomes invalid forever&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No accounts. No tracking. No permanent storage. Just secure, ephemeral sharing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sharing API keys with teammates&lt;/li&gt;
&lt;li&gt;Sending configuration files for projects&lt;/li&gt;
&lt;li&gt;Temporary password sharing&lt;/li&gt;
&lt;li&gt;Code snippets with sensitive data&lt;/li&gt;
&lt;li&gt;Project credentials for group assignments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🗓️ The 30-Day Challenge Timeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start Date:&lt;/strong&gt; December 26, 2025&lt;br&gt;&lt;br&gt;
&lt;strong&gt;End Date:&lt;/strong&gt; January 24, 2026&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Duration:&lt;/strong&gt; 30 days of daily progress&lt;/p&gt;
&lt;h3&gt;
  
  
  Weekly Breakdown:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Week 1: Foundation &amp;amp; Planning&lt;/strong&gt; (Dec 26 - Jan 1)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Flask application setup&lt;/li&gt;
&lt;li&gt;File upload system&lt;/li&gt;
&lt;li&gt;Text snippet handling&lt;/li&gt;
&lt;li&gt;Unique URL generation&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Week 2: Core Features&lt;/strong&gt; (Jan 2 - Jan 8)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;One-time view implementation&lt;/li&gt;
&lt;li&gt;Timer-based expiration&lt;/li&gt;
&lt;li&gt;Password protection&lt;/li&gt;
&lt;li&gt;API development&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Week 3: Security &amp;amp; Polish&lt;/strong&gt; (Jan 9 - Jan 15)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Advanced security measures&lt;/li&gt;
&lt;li&gt;Rate limiting and abuse prevention&lt;/li&gt;
&lt;li&gt;Docker optimization&lt;/li&gt;
&lt;li&gt;Testing suite&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Week 4: Advanced Features &amp;amp; Launch&lt;/strong&gt; (Jan 16 - Jan 24)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Performance optimization&lt;/li&gt;
&lt;li&gt;CI/CD pipeline&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Public launch&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🛠️ Technology Stack Decisions
&lt;/h2&gt;

&lt;p&gt;After much deliberation (and several cups of coffee), here's what I'm going with:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend Framework&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flask&lt;/td&gt;
&lt;td&gt;Lightweight, easy to prototype, Python ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Containerization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Reproducible environments, easy deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ephemeral Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;Built-in TTL, fast in-memory operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bootstrap 5&lt;/td&gt;
&lt;td&gt;Responsive, minimal CSS, rapid UI development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQLite (for metadata)&lt;/td&gt;
&lt;td&gt;Simple, file-based, no setup required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hosting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DigitalOcean/Railway&lt;/td&gt;
&lt;td&gt;Affordable, developer-friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;td&gt;Free, integrated with repository&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  📁 Day 0: What I've Built Today
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. GitHub Repository Setup
&lt;/h3&gt;

&lt;p&gt;The foundation is live: &lt;a href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;github.com/Aayushbankar/onetimeshare&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detailed README&lt;/strong&gt; with 30-day roadmap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MIT License&lt;/strong&gt; for open source distribution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project structure&lt;/strong&gt; skeleton&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issue templates&lt;/strong&gt; for community feedback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow diagram&lt;/strong&gt; of the planned architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Initial Workflow Design
&lt;/h3&gt;

&lt;p&gt;I've mapped out the core user journey:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Student/Developer Uploads API Key/Config
        ↓
Generate Unique ID (UUID + timestamp)
        ↓
Encrypt Data (AES-256)
        ↓
Store in Redis with TTL (5 min - 24 hr)
        ↓
Return Unique URL to User
        ↓
Teammate Accesses URL
        ↓
Decrypt &amp;amp; Serve Data
        ↓
DELETE from Redis Immediately
        ↓
Invalidate URL Forever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 30-Day Daily Breakdown
&lt;/h3&gt;

&lt;p&gt;Each day has specific, achievable goals. No vague "work on backend" tasks. For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 1 (Tomorrow):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flask "Hello World" application&lt;/li&gt;
&lt;li&gt;Basic file upload endpoint&lt;/li&gt;
&lt;li&gt;Docker container setup&lt;/li&gt;
&lt;li&gt;HTML template with Bootstrap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 8:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One-time view implementation&lt;/li&gt;
&lt;li&gt;Database flags for "viewed" status&lt;/li&gt;
&lt;li&gt;Atomic operations to prevent race conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤔 Why Build in Public?
&lt;/h2&gt;

&lt;p&gt;This isn't my first project, but it's my first &lt;strong&gt;public build challenge&lt;/strong&gt;. Here's why I'm doing it:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Accountability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you tell the internet you're going to do something, you're more likely to actually do it. No more abandoned side projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Community Wisdom&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I don't know everything. By sharing my process, I'll get feedback from people who've solved similar problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Learning Acceleration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Mistakes made in public are lessons learned faster. If I architect something poorly, someone will (hopefully kindly) point it out.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Portfolio Building&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A 30-day public build with documented challenges and solutions is better than any resume bullet point.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Helping Others&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If one person looks at this and thinks "I could do that too," it's worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Success Metrics
&lt;/h2&gt;

&lt;p&gt;By Day 30, I aim to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Working MVP&lt;/strong&gt; with all core features&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;100+ GitHub stars&lt;/strong&gt; (showing community interest)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Security audit&lt;/strong&gt; completed (or at least started)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Production deployment&lt;/strong&gt; live and working&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Comprehensive documentation&lt;/strong&gt; for users and developers&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;10+ community contributions&lt;/strong&gt; (issues, PRs, feedback)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  👥 How You Can Participate
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Level 1: The Observer&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Follow &lt;a href="https://twitter.com/hashtag/OneTimeShare30" rel="noopener noreferrer"&gt;#OneTimeShare30&lt;/a&gt; on Twitter&lt;/li&gt;
&lt;li&gt;Read these weekly Dev.to updates&lt;/li&gt;
&lt;li&gt;Watch the GitHub repository&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Level 2: The Supporter&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Star the GitHub repository&lt;/li&gt;
&lt;li&gt;Share updates with batchmates or colleagues who might find it useful&lt;/li&gt;
&lt;li&gt;Give thumbs up on social media posts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Level 3: The Contributor&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open issues for feature requests or bugs&lt;/li&gt;
&lt;li&gt;Test early versions and provide feedback&lt;/li&gt;
&lt;li&gt;Share your expertise in the comments&lt;/li&gt;
&lt;li&gt;Submit PRs for improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Level 4: The Co-Builder&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build your own version alongside me&lt;/li&gt;
&lt;li&gt;Create complementary tools (CLI, browser extension)&lt;/li&gt;
&lt;li&gt;Document your learnings from following along&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 What's Next?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tomorrow (December 26, Day 1):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Flask application skeleton&lt;/li&gt;
&lt;li&gt;Basic file upload endpoint (even if it just prints to console)&lt;/li&gt;
&lt;li&gt;Docker container that runs the app&lt;/li&gt;
&lt;li&gt;First commit to the repository&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll be posting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Twitter:&lt;/strong&gt; Daily progress threads with code snippets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; Commit-by-commit development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dev.to:&lt;/strong&gt; Weekly retrospective articles like this one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn:&lt;/strong&gt; Technical deep-dives on specific challenges&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❓ Questions for You
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;As a student/developer, how do you currently share API keys or config files with teammates?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which security feature should I prioritize first?&lt;/strong&gt; (Encryption, rate limiting, file validation, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Have you ever accidentally committed an API key to GitHub?&lt;/strong&gt; (I have! 🫣)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What would make this tool genuinely useful for your projects or assignments?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔗 Quick Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Aayushbankar/onetimeshare" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/hashtag/OneTimeShare30" rel="noopener noreferrer"&gt;Twitter Hashtag #OneTimeShare30&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/enthusiadev" rel="noopener noreferrer"&gt;My Twitter @enthusiadev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎄 Final Thoughts on Christmas Eve
&lt;/h2&gt;

&lt;p&gt;It's almost midnight on Christmas Eve. My family is asleep, the house is quiet, and I'm excited.&lt;/p&gt;

&lt;p&gt;Excited to build something useful.&lt;br&gt;
Excited to learn in public.&lt;br&gt;
Excited to see where this 30-day journey takes me.&lt;/p&gt;

&lt;p&gt;If you're reading this, thank you. Whether you're a fellow student working on group projects, a developer tired of insecure file sharing, or just someone curious about building in public - you're part of this journey.&lt;/p&gt;

&lt;p&gt;Here's to 30 days of building, learning, and sharing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See you tomorrow for Day 1.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Merry Christmas, and happy building! 🎄👨💻&lt;/p&gt;




</description>
      <category>github</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>devchallenge</category>
    </item>
  </channel>
</rss>
