<?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: Zola Gonano</title>
    <description>The latest articles on DEV Community by Zola Gonano (@zolagonano).</description>
    <link>https://dev.to/zolagonano</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%2F1217963%2Ff2bf04fe-5c94-4a1b-8a69-24cd20efcd21.jpeg</url>
      <title>DEV Community: Zola Gonano</title>
      <link>https://dev.to/zolagonano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zolagonano"/>
    <language>en</language>
    <item>
      <title>A Technical Look at Iran’s Internet Shutdowns</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/a-technical-look-at-irans-internet-shutdowns-2d27</link>
      <guid>https://dev.to/zolagonano/a-technical-look-at-irans-internet-shutdowns-2d27</guid>
      <description>&lt;p&gt;Every time mass protests erupt in Iran, a familiar pattern follows: the flow of information stops. The internet slows to a crawl or disappears entirely.&lt;/p&gt;

&lt;p&gt;But how does a modern country survive cutting itself off from the internet? Wouldn’t that break everything?&lt;/p&gt;

&lt;p&gt;Not quite, because the Islamic Republic has spent the last decade building an internet within the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The National Information Network (NIN): Isolation by Design
&lt;/h2&gt;

&lt;p&gt;Iran’s &lt;strong&gt;National Information Network (NIN)&lt;/strong&gt; is a state-controlled intranet designed to keep domestic services running even when international connectivity is cut off. Think of it as a national sandbox: websites, banking portals, messaging apps, and e-government services that function entirely within Iran’s borders.&lt;/p&gt;

&lt;p&gt;This setup serves two primary functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It &lt;strong&gt;enables selective blackouts&lt;/strong&gt; : the state can block international platforms (like WhatsApp, Instagram, or news sites) while keeping local services (like state media, banking apps) fully operational.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It &lt;strong&gt;forces ISPs to route traffic through government-controlled gateways&lt;/strong&gt; , making it easier to monitor, filter, or shut down parts of the network on demand.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layered on top of this is the &lt;strong&gt;IRGFW&lt;/strong&gt; —the Iranian Great Firewall. Modeled after China’s Great Firewall (GFW), but with stricter enforcement and more centralized control, it filters, blocks, and surveils traffic across the country. On paper, it seems solid and impenetrable.&lt;/p&gt;

&lt;p&gt;But there’s always a hole. Always.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can Be Done in This Situation?
&lt;/h2&gt;

&lt;p&gt;The Iranian internet blockade is aggressive but it’s not perfect. Like any large-scale filtering system, it relies on outdated metadata, and static blocklists. And that’s where cracks begin to form.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Known Flaw: IPs Are Rented, Not Owned
&lt;/h3&gt;

&lt;p&gt;IPv4 addresses are limited and constantly reallocated. Most are rented and passed between hosting providers, resold between datacenters, or migrated across regions. The Iranian filtering system uses &lt;strong&gt;GeoIP databases and BGP information&lt;/strong&gt; to decide which IP ranges to trust and which to block. But those records lag behind the changes.&lt;/p&gt;

&lt;p&gt;An IP that once belonged to a local Iranian provider may now be assigned to a server in Amsterdam, but unless the IRGFW updates its filters in real time (which it doesn’t), that IP might still be allowed through.&lt;/p&gt;

&lt;p&gt;This opens up a small but real opportunity: &lt;strong&gt;scanning IP space&lt;/strong&gt; for reachable proxies, VPNs, or relays that haven’t yet been added to blocklists.&lt;/p&gt;

&lt;p&gt;Yes, it’s mostly brute-force. But when everything else is down, even a single working IP can be a tunnel into the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pingtunnel: Slow, but Better Than Nothing
&lt;/h3&gt;

&lt;p&gt;To prevent scanning or circumvention, the IRGFW has tried to block most outbound protocols. But one thing they haven’t (yet) blocked completely is &lt;strong&gt;ICMP&lt;/strong&gt; which is the protocol behind &lt;code&gt;ping&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ICMP packets are typically used for diagnostics (checking whether a server is alive), and blocking them outright would break a lot of legitimate network functionality. So they’re still allowed, even under heavy shutdown conditions.&lt;/p&gt;

&lt;p&gt;That’s where tools like &lt;strong&gt;Pingtunnel&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;Pingtunnel allows you to &lt;strong&gt;smuggle data inside ICMP packets&lt;/strong&gt; , essentially tunneling TCP traffic over a stream of pings. It’s really slow and It’s prone to packet loss. But it works, especially for text-based communication, command-line access, or sending small files.&lt;/p&gt;

&lt;p&gt;It’s not secure against DPI or timing analysis. But in a shutdown scenario, &lt;strong&gt;“slow but working” is better than nothing&lt;/strong&gt;. Even a shell session or basic messaging tool can be a critical line to the outside world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starlinks Behind NATs: Iranians Bypass Censorship Despite Criminalization
&lt;/h2&gt;

&lt;p&gt;Despite Iran’s very aggressive criminalization of Starlink receivers, many Iranians still manage to get their hands on one of them. Starlink connections can be securely shared with others by routing traffic through NAT-enabled local routers using encrypted tunnels like WireGuard.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does “Behind NAT” Means?
&lt;/h3&gt;

&lt;p&gt;Starlink provides an independent internet connection via satellite, bypassing local ISP infrastructure entirely. However, because Starlink devices receive &lt;strong&gt;dynamic, often private IPv4/IPv6 addresses&lt;/strong&gt; and operate outside traditional ISP infrastructure, they are typically &lt;strong&gt;behind NATs&lt;/strong&gt; when connected to local Iranian networks or user devices.&lt;/p&gt;

&lt;p&gt;Here’s what this looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Starlink terminal&lt;/strong&gt; (user terminal + router) connects to the satellite network and obtains an IP address from Starlink’s global network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Meanwhile, the user’s devices in Iran are connected to the &lt;strong&gt;local ISP’s network&lt;/strong&gt; , which uses its own IP addressing and NAT systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user sets up a &lt;strong&gt;local router or gateway inside Iran&lt;/strong&gt; that bridges these two networks, routing local traffic through the Starlink link.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How This Setup Bypasses Censorship
&lt;/h3&gt;

&lt;p&gt;The key is that &lt;strong&gt;Iranian ISPs and firewalls cannot effectively block Starlink traffic without physically confiscating or disabling the terminals&lt;/strong&gt; , because Starlink’s satellites communicate directly with user terminals over encrypted, proprietary protocols.&lt;/p&gt;

&lt;p&gt;To share this Starlink connection with friends and family inside Iran, users employ &lt;strong&gt;WireGuard VPN tunnels&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WireGuard Server Setup:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The user sets up a &lt;strong&gt;WireGuard server on a local Iranian ISP router&lt;/strong&gt; that acts as the gateway. This router has two interfaces:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic Routing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Incoming VPN connections from trusted friends or family connect to the WireGuard server on the Iranian ISP router (over the local Iranian network). The router then &lt;strong&gt;routes this decrypted traffic outbound via the Starlink interface&lt;/strong&gt; , effectively using Starlink as the internet exit point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NAT and IP Translation:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because the Iranian ISP router is behind the ISP’s NAT and firewall, it &lt;strong&gt;performs NAT translation&lt;/strong&gt; on the incoming WireGuard traffic and routes it over the Starlink network, which has its own IP addressing scheme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WireGuard Configuration Sharing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The WireGuard config files containing public keys, endpoint addresses, allowed IPs, and ports are shared securely with trusted users. This allows them to establish encrypted tunnels into the Starlink-connected router from their own devices within Iran.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why This Setup Is Resilient
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Starlink traffic is encrypted and satellite-based&lt;/strong&gt; , making it extremely difficult for IRGFW to inspect or block without physical interference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WireGuard uses UDP and a small handshake footprint&lt;/strong&gt; , making detection and blocking via DPI harder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NAT hides the underlying IP structure&lt;/strong&gt; , so Iranian firewalls see only standard encrypted traffic to the local router — they can’t easily distinguish if that traffic is then routed over Starlink.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This also &lt;strong&gt;allows multiple users to share a single Starlink terminal&lt;/strong&gt; , maximizing scarce and expensive hardware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Survive Inside the NIN?
&lt;/h2&gt;

&lt;p&gt;Sometimes, when the National Information Network (NIN) is up but Iran’s connection to the global internet is completely cut off, you simply &lt;em&gt;can’t&lt;/em&gt; reach friends and family outside the country. Even communicating inside Iran becomes a challenge.&lt;/p&gt;

&lt;p&gt;So what are your options?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SMS?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
SMS in Iran is unencrypted. The government can—and does—intercept, read, and store messages at will. Plus, SMS is slow, costly, and unreliable for anything beyond short texts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phone calls?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Calls use GSM networks, which are fully controlled by the state. Voice calls can be intercepted, recorded, and monitored without any user consent. Privacy here is nonexistent.&lt;/p&gt;




&lt;h3&gt;
  
  
  Exploiting the Local Network: Self-Hosted Encrypted Services
&lt;/h3&gt;

&lt;p&gt;But here’s the catch: the NIN &lt;em&gt;does&lt;/em&gt; allow traffic inside Iran’s local network. This means you can run services completely inside Iran, avoiding the censored global internet but still enabling communication.&lt;/p&gt;

&lt;p&gt;One powerful option is setting up your own &lt;strong&gt;end-to-end encrypted messaging and calling service&lt;/strong&gt;. like a &lt;strong&gt;Matrix Synapse server&lt;/strong&gt; which can be fully hosted on a VPS inside an Iranian ISP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Matrix?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Matrix is an open-source protocol that supports secure, E2E-encrypted messaging, voice, and video calls. It’s decentralized, so anyone can run their own server. If your server is inside Iran, and your contacts connect locally, you avoid international censorship and heavy filtering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you need?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A VPS hosted by an Iranian ISP, so the server is reachable inside the NIN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A domain name pointing to that VPS, ideally registered with an Iranian registrar or configured to resolve within the NIN’s DNS system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Matrix Synapse server software installed and configured on the VPS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How does it help?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Since the traffic never leaves the country’s internal network, it’s harder for the government to block without cutting off the NIN entirely. And because Matrix uses strong encryption, even if the government inspects packets, the content remains private.&lt;/p&gt;




&lt;p&gt;Surviving inside the NIN means adapting to its limitations and exploiting its architecture. Running your own encrypted local communication service allows Iranians to stay connected securely, even when the global internet is a no-go.&lt;/p&gt;

&lt;p&gt;It’s not perfect. there are risks, and setting up these services requires some technical knowledge. but it’s a crucial lifeline in a digital environment designed to isolate and surveil.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Digital Autonomism: Personal Autonomy through Technology</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/digital-autonomism-personal-autonomy-through-technology-5d64</link>
      <guid>https://dev.to/zolagonano/digital-autonomism-personal-autonomy-through-technology-5d64</guid>
      <description>&lt;p&gt;Freedom starts from within, once we break through the external controls and take control over our own lives and decisions.&lt;/p&gt;

&lt;p&gt;Although avoiding external controls might not sound feasible at the moment, just like avoiding cholera was not feasible a hundred years ago, the history of humanity is full of impossibilities that now just seem stupid to us.&lt;/p&gt;

&lt;p&gt;Just like how absurd it sounds that people died from cholera because they didn’t separate sewers from drinking water, our situation will sound absurd a hundred years later—that we didn’t have control over our own lives, our own finances, our own privacy, our own data, our own minds even.&lt;/p&gt;

&lt;p&gt;Bitcoin and cryptocurrencies broke a mental barrier for us, we suddenly realized things can work better without corruption looking over them, but that barrier can be pushed even further. We can control more than our finances, the Internet allows it, cryptography allows it, decentralized systems allow it.&lt;/p&gt;

&lt;p&gt;We can have free markets, free media, free finances, free information, free expressions, free privacy, free thoughts and beliefs, all through technology, by controlling the matters ourselves rather than authoritarian entities, by putting the trust into ourselves, and the systems we will build on top of cryptographic methods. We will put our trust in math rather than humans because math won’t get corrupt when given power—math is the power.&lt;/p&gt;

&lt;p&gt;We can have markets that people are free to trade on, markets that would be permissionless and trustless in every sense possible.&lt;/p&gt;

&lt;p&gt;We can have media that are run by us, the humans—not the algorithms, not the companies profiting off of them. We would profit off of our own content, we would get paid for hosting the content.&lt;/p&gt;

&lt;p&gt;We can have freedom of expression, information, and thoughts without censorship. We can have a place where no one’s voice can be suppressed.&lt;/p&gt;

&lt;p&gt;We can have free privacy—an Internet where privacy is built into it, not something that would take our conscious effort and time and a lot of sketchy things to get into it.&lt;/p&gt;

&lt;p&gt;For now, we have free finances, digital money that would be like gold in your safe, with the difference that crypto is safer. We have loans without banks, we have digital cash like Monero without federal reserves, we have borderless international money worth more than any currency on Earth.&lt;/p&gt;

&lt;p&gt;We can eventually replace the Internet we know today with something that is truly decentralized—from the network infrastructure to the protocols, to everything running on it. An Internet where it is a basic right to have control over yourself, your data, and your decisions.&lt;/p&gt;

&lt;p&gt;The world will move, the tools will be built, the knowledge will spread, and the barriers will fall. All that will remain will be for us to take back control, to build, to adopt, to be free.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Don't use Telegram, but if you have to, at least use Partisan Telegram</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Sat, 22 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/dont-use-telegram-but-if-you-have-to-at-least-use-partisan-telegram-2f50</link>
      <guid>https://dev.to/zolagonano/dont-use-telegram-but-if-you-have-to-at-least-use-partisan-telegram-2f50</guid>
      <description>&lt;p&gt;Telegram is really close to the worst when it comes to privacy, security, and anonymity, which highly matters if you are an activist, a protester, a journalist, or even a normal paranoid human being.&lt;/p&gt;

&lt;p&gt;Telegram is a platform that keeps on animating its emoji reactions in every update and milking users for money by giving them a “premium” subscription that essentially provides nothing “premium” in exchange. I have had Telegram since it came out on Android, and that’s about 10 years ago, but apparently, that wasn’t enough time for Telegram to add E2EE to their platform.&lt;/p&gt;

&lt;p&gt;Of course, it provides so-called “Secret Chats,” but what is the use of it if it is only available on mobile clients and its encryption is self-rolled, provoking one of the most important laws in cryptography, which states explicitly: “DO NOT ROLL YOUR OWN CRYPTO.”&lt;/p&gt;

&lt;p&gt;But besides its lack of proper E2EE, you might have to use it. I have to use it. Just because everyone I know uses it. And that’s a huge reason, believe it or not—you cannot go live on your own island forever. I have tried, and I have failed.&lt;/p&gt;

&lt;p&gt;With all this hate speech I did on Telegram, it is time to introduce a client called “Partisan Telegram” that not only fixes the issues with E2EE but also provides some other kind of security to it.&lt;/p&gt;

&lt;p&gt;Partisan Telegram brings operational security to Telegram, and by using it, you are still trusting Telegram with your data, which is not something you should do, honestly. Do not trust anyone with your data, especially if they can profit off your data or be pressured to hand out your data (be realistic—no one would shut down their platform in a country for you, let alone go to jail for you).&lt;/p&gt;

&lt;p&gt;Partisan Telegram adds some privacy and security features that can be life-saving for protesters and activists in some parts of the world where freedom is far from a luxury, in places where expressing it is considered a crime and punished severely.&lt;/p&gt;

&lt;p&gt;I like to keep this post short, so I will just explain how it works and what it offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Partisan Telegram tries its best to obfuscate its existence so it wouldn’t put you into more trouble if you’re caught with it. So everything feels and looks like vanilla Telegram.&lt;/p&gt;

&lt;p&gt;It uses the lock feature of Telegram, where you put a 4-digit passcode to access your Telegram. By using Partisan Telegram, you can set multiple passcodes, which can then be programmed to do certain things when entered. This is its main functionality.&lt;/p&gt;

&lt;p&gt;For example, you can set the passcode “1234” to show only one account that you have nothing on. Or you can program it to send an alert message to your contacts when activated or to log off your accounts on all devices. And you will have a main passcode that will give you full access to your Telegram.&lt;/p&gt;

&lt;p&gt;But how would this be useful? Imagine you’re caught mid-protest and someone is investigating your phone. You can just give them the fake passcode that you have programmed to log out your accounts and remove any evidence from the device without them noticing while alerting your friends who might have been involved. The scenarios can be endless.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Offers
&lt;/h2&gt;

&lt;p&gt;Partisan Telegram’s main focus is your OPSEC, as it cannot add E2EE to Telegram without breaking its backward compatibility with other versions of Telegram. And it is relatively good at it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurability
&lt;/h3&gt;

&lt;p&gt;Partisan Telegram has great configurability. You can set endless fake passcodes and configure each to do a certain thing for a specific situation.&lt;/p&gt;

&lt;p&gt;You can set a timer to go off or set a number of failed attempts to trigger a fake passcode, which will then trigger other events you have programmed it to do.&lt;/p&gt;

&lt;p&gt;It can also take pictures when entering a wrong or fake passcode, which you can later check to see if someone has attempted to unlock your Telegram or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Triggering Killswitch by Receiving a Message
&lt;/h3&gt;

&lt;p&gt;One main feature it provides is that the fake passcode actions or killswitch can be triggered if you receive a specific message.&lt;/p&gt;

&lt;p&gt;This can be very useful if you lost your phone, or it got stolen or taken from you. You can remotely delete all your accounts from that phone and send an SOS message to your key contacts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Providing Additional Security Measures
&lt;/h3&gt;

&lt;p&gt;It also provides some other security measures, like brute-force protection for the passcodes, which Telegram itself doesn’t. With brute-force protection, the time between login attempts will increase every time.&lt;/p&gt;

&lt;p&gt;It can also be set to delete cache and drafts on exit, which the original Telegram doesn’t offer.&lt;/p&gt;

&lt;p&gt;It can prevent accidental clicks by double-checking with you when you accidentally touch the subscribe button or send a reaction to a message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete After Read
&lt;/h3&gt;

&lt;p&gt;It provides automatic delete-after-read for specific messages. You can send a message with a timer, and it will be deleted after the timer has passed. It is not like Telegram’s auto-delete, which deletes all messages from both sides after a period of time and is also visible when enabled or disabled, which can be more suspicious in some cases.&lt;/p&gt;

&lt;p&gt;Other than that, Partisan Telegram also provides auto-delete to delete all of your messages in a group chat automatically. This can come in handy if you need to delete your messages and leave. Although all group chat events, like deleting or editing messages, will be visible to the admins of the group chat for 72 hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  File Protection
&lt;/h3&gt;

&lt;p&gt;Partisan Telegram can prevent information extraction from your phone by encrypting the data stored on the phone, including messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypted Group Chats
&lt;/h3&gt;

&lt;p&gt;Partisan Telegram recently introduced an experimental feature for having an encrypted chat with a group of people, which can be useful for organizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Perks
&lt;/h2&gt;

&lt;p&gt;It can also bypass some of the annoying paywalls that Telegram has recently put up. For example, it will allow you to add more than three accounts without subscribing to Telegram Premium.&lt;/p&gt;

&lt;p&gt;It can provide additional badges to certain accounts, helping you detect suspicious accounts and scammers before you interact with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Precautions
&lt;/h2&gt;

&lt;p&gt;You should research before using anything, especially when it doesn’t have audits and a well-known, reputed developer team. But Partisan Telegram is fully open-source and can be compared against the original Telegram codebase to see exactly what has been modified. You can compile your own version instead of trusting their binaries.&lt;/p&gt;

&lt;p&gt;You can find Partisan Telegram at &lt;a href="https://github.com/wrwrabbit/Partisan-Telegram-Android" rel="noopener noreferrer"&gt;https://github.com/wrwrabbit/Partisan-Telegram-Android&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a good project for a good purpose, but if you can avoid Telegram and use something like Signal (which includes E2EE and is built with privacy in mind), do it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How Monero Fulfilled Satoshi's Promise</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Fri, 07 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/how-monero-fulfilled-satoshis-promise-4g0p</link>
      <guid>https://dev.to/zolagonano/how-monero-fulfilled-satoshis-promise-4g0p</guid>
      <description>&lt;p&gt;Since Trump’s election and even before that, news kept coming out about how crypto was going to change the world, how the US was going to become the crypto capital of the world, and how they wanted to build strategic reserves of Bitcoin, Ethereum, Solana, Ripple, and others. At the same time, however, they de-listed Monero from major exchanges like Binance and even criminalized this cryptocurrency.&lt;/p&gt;

&lt;p&gt;But if we take a closer look at Monero, we can see that it was the true crypto—it was what Satoshi wanted to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  But why is it hated so much by the authorities?
&lt;/h2&gt;

&lt;p&gt;Governments first thought Bitcoin and early cryptocurrencies were anonymous too, as we did. But soon it became obvious that this anonymity shatters as soon as you spend your money in the real world.&lt;/p&gt;

&lt;p&gt;Imagine you get some Bitcoin somehow, and you try to buy a car with it. Everyone can trace that transaction, get to the person who sold you the car, and identify you. With the help of AI, this can be further simplified and made easier to track.&lt;/p&gt;

&lt;p&gt;But Monero is different. Monero is untraceable, meaning they don’t know who spends money. They cannot collect taxes, and they hate it when they cannot figure out what everyone in society is doing.&lt;/p&gt;

&lt;p&gt;But despite all the efforts to criminalize Monero and delist it from exchanges, it has kept its value, continuing to increase over time because, like cash, it is actually used in transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is cash and what was Satoshi’s promise?
&lt;/h2&gt;

&lt;p&gt;Satoshi’s whitepaper introduced Bitcoin as &lt;strong&gt;“Bitcoin: A Peer-to-Peer Electronic Cash System”&lt;/strong&gt; , but Bitcoin never became electronic cash. Not even Bitcoin Cash managed to be electronic cash.&lt;/p&gt;

&lt;p&gt;But what is cash? Cash is a form of money that allows for direct &lt;strong&gt;peer-to-peer transactions&lt;/strong&gt; without intermediaries. When you pay for something with cash, you don’t know where the cash originally came from. You just know you got it, and you will give it to someone else in exchange. No matter how many times these green papers circulate among people, they won’t be linked to anyone. When you hand over cash, the transaction is &lt;strong&gt;irreversible&lt;/strong&gt; and requires no third-party verification.&lt;/p&gt;

&lt;p&gt;Cash is &lt;strong&gt;Permissionless&lt;/strong&gt; , meaning no approval is needed to use it. Bitcoin and other public ledger cryptos are that to some extent.&lt;/p&gt;

&lt;p&gt;Cash is &lt;strong&gt;Censorship-Resistant&lt;/strong&gt; , meaning it cannot be blocked by banks or governments. Bitcoin is that as well to some extent, but there can be censorship when exchanging on centralized exchanges (CEX).&lt;/p&gt;

&lt;p&gt;Cash is &lt;strong&gt;Untraceable&lt;/strong&gt; , meaning transactions are not publicly recorded. Bitcoin and most cryptos are not that; they’re exactly the opposite.&lt;/p&gt;

&lt;p&gt;Cash has &lt;strong&gt;No Counterparty Risk&lt;/strong&gt; , meaning unlike digital bank balances, which depend on a central authority, cash does not. Neither Bitcoin nor most cryptos do.&lt;/p&gt;

&lt;p&gt;Self-Custodial: When you have cash, it’s in your wallet. You’re holding it. Bitcoin and other cryptos are like that as well.&lt;/p&gt;

&lt;p&gt;Based on all these points, Bitcoin and other public ledger cryptocurrencies have most of the characteristics of cash except one thing: &lt;strong&gt;Untraceability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monero found the missing piece of the puzzle
&lt;/h2&gt;

&lt;p&gt;Monero introduced a new way that fixed the only missing piece of the “Electronic Cash” system that Satoshi wanted to build. Monero made a &lt;strong&gt;untraceable cryptocurrency&lt;/strong&gt; while keeping all of cash’s characteristics.&lt;/p&gt;

&lt;p&gt;To achieve this, Monero introduced a few new technologies to the crypto space:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Ring Signatures: Sender Anonymity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Monero transactions do not directly reveal the sender. Instead, they use &lt;strong&gt;ring signatures&lt;/strong&gt; , which mix a real transaction input with decoys.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;ring signature&lt;/strong&gt; allows a signer to create a signature that proves ownership of a private key &lt;strong&gt;without revealing which key in the set was used&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In a ring signature, the user is given a &lt;strong&gt;set of public keys&lt;/strong&gt; $P1, P2, …, Pn$. The signer has the private key $sk$ corresponding to one of these.&lt;/p&gt;

&lt;p&gt;The signature is constructed so that an observer cannot determine which private key was used, only that one of the keys in the ring signed the message.&lt;/p&gt;

&lt;p&gt;Monero used to use &lt;strong&gt;Linkable Spontaneous Anonymous Group (LSAG) Signatures&lt;/strong&gt; for ring signatures, in which:&lt;/p&gt;

&lt;p&gt;Each &lt;strong&gt;participant’s public key&lt;/strong&gt; contributes to a &lt;strong&gt;key image&lt;/strong&gt; $I$, which is derived as: I=xH(P)I=xH(P) where $x$ is the private key, and $H(P)$ is a cryptographic hash of the public key.&lt;/p&gt;

&lt;p&gt;Then, the signer constructs a ring $(P1, P2, …, Pn)$ such that: $σ=(I,c1,r1,…,rn)σ=(I,c1, r1, …, rn)$&lt;/p&gt;

&lt;p&gt;where $c1$ is a random challenge, and $r_i$ are random values that make the signature verifiable without revealing the real signer.&lt;/p&gt;

&lt;p&gt;A verifier can check that the &lt;strong&gt;key image $I$&lt;/strong&gt; hasn’t been used before, preventing double spending.&lt;/p&gt;

&lt;p&gt;In 2020, Monero introduced &lt;strong&gt;&lt;a href="https://eprint.iacr.org/2019/654.pdf" rel="noopener noreferrer"&gt;Concise Linkable Spontaneous Anonymous Group Signatures (CLSAG)&lt;/a&gt;&lt;/strong&gt;, which does this much more efficiently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With CLSAG, users see a 20% improvement in signature verification, and at least a 10% overall improvement for typical transactions. For example, a typical Monero transaction (2 inputs and 2 outputs) that usually weighs 2.5kB now takes only 1.9kB of blockchain space with CLSAG, a ~25% improvement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. RingCT: Amount Privacy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bitcoin transactions openly show input and output amounts. Monero hides these with &lt;strong&gt;RingCT&lt;/strong&gt; (Ring Confidential Transactions).&lt;/p&gt;

&lt;p&gt;RingCT is based on &lt;strong&gt;Pedersen Commitments&lt;/strong&gt; , which allow a sender to commit to a value without revealing it.&lt;/p&gt;

&lt;p&gt;A commitment to a value $v$ is:&lt;/p&gt;

&lt;p&gt;$C=vG+rHC=vG+rH$&lt;/p&gt;

&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$G, H$ are generator points on an elliptic curve.&lt;/li&gt;
&lt;li&gt;$r$ is a random blinding factor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Each input and output amount is committed&lt;/strong&gt; using Pedersen Commitments. &lt;strong&gt;Bulletproofs&lt;/strong&gt; are used to prove that the committed values &lt;strong&gt;sum to zero&lt;/strong&gt; (to ensure no coins are created out of thin air) without revealing them. &lt;strong&gt;Decoy amounts&lt;/strong&gt; are included to make it impossible to determine the real transaction amounts.&lt;/p&gt;

&lt;p&gt;Additionally, a Bulletproofs+ upgrade in 2022 &lt;strong&gt;reduced transaction size&lt;/strong&gt; by 5-7x compared to original Bulletproofs, making Monero even faster.&lt;/p&gt;

&lt;p&gt;Later on, cryptos like ZCash came along that use Zero-Knowledge Proofs (ZKPs) like ZK-Snarks to do this exact thing, and they are superior. But the problem with ZCash is that it is not the default; in Monero, all transactions are private, whereas in ZCash, some transactions can be private.&lt;/p&gt;

&lt;p&gt;In ZKPs, someone can prove that they possess information (in the case of crypto, the amount of money they want to transfer) without revealing anything about the information itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Stealth Addresses: Receiver Privacy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Bitcoin addresses are static, meaning you can see all transactions going to a given address. Monero uses &lt;strong&gt;one-time stealth addresses&lt;/strong&gt; that unlink the receiver from the transaction.&lt;/p&gt;

&lt;p&gt;Each Monero wallet has a &lt;strong&gt;public view key $v$ and a public spend key $s$&lt;/strong&gt;. When sending a transaction, the sender generates a &lt;strong&gt;one-time public key $P$&lt;/strong&gt; as follows:&lt;/p&gt;

&lt;p&gt;$P=H(rV)G+SP=H(rV)G+S$&lt;/p&gt;

&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$r$ is a random scalar chosen by the sender.&lt;/li&gt;
&lt;li&gt;$V$ is the recipient’s &lt;strong&gt;public view key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;$S$ is the recipient’s &lt;strong&gt;public spend key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;$G$ is the elliptic curve generator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The recipient can compute the corresponding &lt;strong&gt;private key&lt;/strong&gt; to spend the funds:&lt;/p&gt;

&lt;p&gt;$P′=H(rv)G+sP′=H(rv)G+s$&lt;/p&gt;

&lt;p&gt;This ensures that &lt;strong&gt;only the recipient can identify and spend the transaction&lt;/strong&gt; , but an outsider cannot link it to a wallet.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Dandelion++: Network-Level Privacy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Even if transactions are private on-chain, Bitcoin and other cryptocurrencies &lt;strong&gt;leak metadata&lt;/strong&gt; through the P2P network when broadcasting transactions. Monero mitigates this with &lt;strong&gt;Dandelion++&lt;/strong&gt; , which obfuscates transaction propagation.&lt;/p&gt;

&lt;p&gt;In Dandelion++, a node first &lt;strong&gt;selects a “stem” path&lt;/strong&gt; (a small subset of nodes) to pass the transaction privately. Then, at a random step, the transaction &lt;strong&gt;“fluffs”&lt;/strong&gt; (broadcasts) to the entire network. This makes it difficult to determine the &lt;strong&gt;original source&lt;/strong&gt; of the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monero makes a more decentralized cryptocurrency than Bitcoin
&lt;/h2&gt;

&lt;p&gt;As mining becomes more competitive, larger entities with access to specialized hardware (ASICs) and cheap electricity can dominate the mining process. This leads to centralization, where a few large mining pools control the majority of the network’s hash power, potentially threatening decentralization and security.&lt;/p&gt;

&lt;p&gt;Monero introduces a new PoW algorithm called RandomX to be ASIC-resistant by making the PoW memory-hard, meaning it requires RAM to compute hashes, which cannot be specialized like SHA hashes. RAM is expensive to obtain.&lt;/p&gt;

&lt;p&gt;Also, unlike Bitcoin’s &lt;strong&gt;1 MB limit&lt;/strong&gt; , Monero has an &lt;strong&gt;adaptive block size&lt;/strong&gt; to prevent congestion. And unlike Ethereum and Solana, Monero has &lt;strong&gt;no pre-mined coins, no corporate backing, and no central leadership&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;With all that being said, we all love Bitcoin, Ethereum, and Solana. They’re great technologies, and even the worst of them is still superior to the best of banking systems.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Very Technical Look at BitMessage: Learning From a Dead Project</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Sun, 25 Aug 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/a-very-technical-look-at-bitmessage-learning-from-a-dead-project-1j6o</link>
      <guid>https://dev.to/zolagonano/a-very-technical-look-at-bitmessage-learning-from-a-dead-project-1j6o</guid>
      <description>&lt;p&gt;There are a lot of cool projects that unfortunately have been abandoned or unmaintained for years, but that doesn’t mean they added no value. Studying what they’ve done, taking their unique ways of doing certain things and their problems can lead us to build something better. Bitmessage is one of those projects; it is an email-like service but fully peer-to-peer and decentralized, built upon the same principles. It used innovations of other projects like Bitcoin to build a new thing.&lt;/p&gt;

&lt;p&gt;But sadly, Bitmessage didn’t seem to make it. Though it was a cool project, it never got independently audited and its latest release was in 2018. There aren’t many peers left on the network and its client has some known and critical vulnerabilities like remote code execution, but none of this means it served no good. There have been freedom-loving and privacy-caring people behind it, dedicating their time, money, and energy to build something valuable.&lt;/p&gt;

&lt;p&gt;In this post, I wanted to take a technical look at this network, on how it worked in depth (like the &lt;a href="//./a-very-technical-look-at-zeronet"&gt;post I did on Zeronet&lt;/a&gt;) in a very simple and easy-to-understand way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did Bitmessage do
&lt;/h2&gt;

&lt;p&gt;Bitmessage was supposed to be like a truly &lt;a href="https://en.wikipedia.org/wiki/Peer-to-peer" rel="noopener noreferrer"&gt;P2P&lt;/a&gt; email system. You would send a message on the network, it would have been encrypted for the receiver and spread across the peers until the receiver got it. Everyone would get the message, but only the receiver would open it. That causes some issues, though. We’re relying too much on the encryption scheme and its implementation. If a flaw in the scheme was found, the whole network would become insecure until a new version was released, and then it would break compatibility with older versions. Here, a bad actor could log all messages flowing on the network and wait for the day that a vulnerability in encryption was found, then they would open all messages. Networks like &lt;a href="https://en.wikipedia.org/wiki/Jami_(software)" rel="noopener noreferrer"&gt;Jami&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Tox_(protocol)" rel="noopener noreferrer"&gt;Tox&lt;/a&gt; do this differently; they find the receiver and then directly communicate with them, which fixes that problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mailing Lists
&lt;/h3&gt;

&lt;p&gt;One of the interesting features of Bitmessage was its mailing list feature, which is a broadcast address that, when someone sends a message to it, a copy of the message gets sent to everyone in the subscription list of this address.&lt;/p&gt;

&lt;p&gt;But the downside is that everyone can send a message to a mailing list in Bitmessage without even being a member of it, and that is the recipe for spam.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscriptions
&lt;/h3&gt;

&lt;p&gt;Subscriptions in Bitmessage allow users to receive encrypted broadcasts from a subscribed address. The way that this encryption happens is not very secure. A broadcast message is encrypted with a key, which can be derived from the sender’s address. Once a broadcast is decrypted, the sender’s address is known, and after that, every broadcast ever sent and every broadcast that will be sent in the future can be decrypted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Private Messages
&lt;/h3&gt;

&lt;p&gt;Private messages in Bitmessage are those messages that have only one recipient. All private messages are encrypted using the receiver’s public key (and the receiver’s public key is the receiver’s address), and when the receiver successfully decrypts the sender’s message, they send an ACK message telling the sender that the message has been successfully received and decrypted. If the ACK message isn’t received within 2.5 days, the message expires and the sender will have to do the Proof-of-Work again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Explain the Proof of Work and how it works in Bitmessage here&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  BitMessage’s Encryption
&lt;/h2&gt;

&lt;p&gt;Bitmessage used an &lt;a href="https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme" rel="noopener noreferrer"&gt;ECIES (Elliptic Curve Integrated Encryption Scheme)&lt;/a&gt; to encrypt the payloads of the messages and broadcast objects.&lt;/p&gt;

&lt;p&gt;This scheme uses &lt;a href="https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman" rel="noopener noreferrer"&gt;ECDH (Elliptic Curve Diffie-Hellman)&lt;/a&gt; to generate a shared secret, which is then used to encrypt the data using AES-256 (Advanced Encryption Standard) in CBC mode.&lt;/p&gt;

&lt;p&gt;This scheme, by today’s standards, isn’t that secure. The CBC mode adds a lot of complications and insecurities because it doesn’t have authentication of messages, and self-implementation of them leaves room for many errors and mistakes. A better scheme by today’s standards would use X25519 to exchange the keys and generate the shared secrets. &lt;a href="https://en.wikipedia.org/wiki/Curve25519" rel="noopener noreferrer"&gt;X25519&lt;/a&gt; is based on Curve25519, which is faster and more secure than ECDH.&lt;/p&gt;

&lt;p&gt;Also, there are other new methods for exchanging keys besides elliptic curves and &lt;a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)" rel="noopener noreferrer"&gt;RSA&lt;/a&gt;, like &lt;a href="https://en.wikipedia.org/wiki/Key_encapsulation_mechanism" rel="noopener noreferrer"&gt;Key Encapsulation Mechanisms (KEMs)&lt;/a&gt;, which are supposed to reduce the complexity of the key exchange methods.&lt;/p&gt;

&lt;p&gt;The encryption process in Bitmessage is as follows (taken from Bitmessage’s wiki):&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;The destination public key is called K.&lt;/li&gt;
&lt;li&gt;Generate 16 random bytes using a secure random number generator. Call them IV.&lt;/li&gt;
&lt;li&gt;Generate a new random EC key pair with the private key called r and the public key called R.&lt;/li&gt;
&lt;li&gt;Do an EC point multiply with public key K and private key r. This gives you public key P.&lt;/li&gt;
&lt;li&gt;Use the X component of public key P and calculate the SHA512 hash H.&lt;/li&gt;
&lt;li&gt;The first 32 bytes of H are called key_e and the last 32 bytes are called key_m.&lt;/li&gt;
&lt;li&gt;Pad the input text to a multiple of 16 bytes, in accordance with PKCS7.&lt;/li&gt;
&lt;li&gt;Encrypt the data with AES-256-CBC, using IV as the initialization vector, key_e as the encryption key, and the padded input text as the payload. Call the output ciphertext.&lt;/li&gt;
&lt;li&gt;Calculate a 32-byte MAC with HMAC-SHA256, using key_m as salt and IV + R + ciphertext as data. Call the output MAC.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The resulting data is: IV + R + ciphertext + MAC&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This could be improved in many ways, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a safe KDF like HKDF to derive the keys instead of using a hash like SHA512.&lt;/li&gt;
&lt;li&gt;Using an &lt;a href="https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD)" rel="noopener noreferrer"&gt;AEAD&lt;/a&gt; to ensure the integrity of the encrypted message instead of calculating the MAC separately and increasing the risk of implementation errors.&lt;/li&gt;
&lt;li&gt;Using a KEM to exchange the keys would simplify the exchange process while increasing security by reducing the risk of key interception or leakage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Plausible Deniability
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Plausible_deniability" rel="noopener noreferrer"&gt;Plausible deniability&lt;/a&gt; is when someone can say they didn’t know about something bad that happened, and there is no clear proof to show they did.&lt;/p&gt;

&lt;p&gt;Plausible deniability is a big part of Bitmessage. In Bitmessage, the messages are not only encrypted but also signed with the sender’s address to prevent strangers from claiming to be a specific person. However, this also causes problems: if a message is decrypted and the signature is verified, the content of the message can be used against the sender. But these actions can be taken for plausible deniability in Bitmessage:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deleting: Address blocks can be deleted from keys.dat so they are no longer used to send or receive messages.&lt;/li&gt;
&lt;li&gt;Publication: Another thing that can be done is to publicly share the address block in a crowded mailing list. This way, users can pretend that they never used that address at all, and there will be no proof that they actually did, or someone else who had access to that address block. But this comes with some consequences: 

&lt;ol&gt;
&lt;li&gt;Everyone can claim that they’re the true owner of the address, impersonating the address.&lt;/li&gt;
&lt;li&gt;Every message that was sent using or to the public address can be decrypted by everyone. While the messages delete after 2.5 days, there might always be a backup copy of the messages.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  BitMessage’s Proof of Work
&lt;/h2&gt;

&lt;p&gt;To prevent or at least reduce the spam on the network, Bitmessage used proof of work to address this problem.&lt;/p&gt;

&lt;p&gt;Proof of work is a costly task for a computer to perform, for example, a calculation that requires time and effort (for a computer) to do, and it is verifiable by other people that this calculation or work is done correctly and there is no cheating involved.&lt;/p&gt;

&lt;p&gt;Bitmessage uses a double round of &lt;a href="http://en.wikipedia.org/wiki/SHA-2" rel="noopener noreferrer"&gt;SHA-512&lt;/a&gt; for its proof of work, meaning it hashes a message twice with SHA-512. It is not very costly by modern standards, and in my opinion, it doesn’t prevent spam that much. It could have been improved by using a hash algorithm that requires memory to perform the hashing, usually a &lt;a href="https://en.wikipedia.org/wiki/Key_derivation_function" rel="noopener noreferrer"&gt;key derivation function (KDF)&lt;/a&gt; like &lt;a href="https://en.wikipedia.org/wiki/Argon2" rel="noopener noreferrer"&gt;Argon2id&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Scrypt" rel="noopener noreferrer"&gt;scrypt&lt;/a&gt;. These algorithms not only require CPU/GPU power but also take up RAM, and RAM is much more expensive than CPU power.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043 (first round of SHA-512)
0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff1423c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200 (second round of SHA-512)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BitMessage’s Addresses
&lt;/h2&gt;

&lt;p&gt;In Bitmessage, all addresses are Base58 encoded hashes of the public key. The hash algorithm for address generation is different from its PoW algorithm; for addresses, Bitmessage uses &lt;a href="http://en.wikipedia.org/wiki/RIPEMD" rel="noopener noreferrer"&gt;RIPEMD-160&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;For example, a Bitmessage address looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BM-BcbRqcFFSQUUmXFKsPJgVQPSiFA3Xash

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All Bitmessage addresses start with the characters “BM-“ to indicate they are part of the protocol. This is a good idea because when a network applies such a separator in the addresses, it becomes easier to identify newer versions of addresses. For example, if in a new version of Bitmessage they wanted to use a different hash or public key algorithm, they could have changed the address prefix to &lt;code&gt;BMV2-&lt;/code&gt;, indicating it is version 2 of the address. This would let users know if they need a newer client and would prevent sending messages from unsupported clients to newer versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  BitMessage’s Protocol
&lt;/h2&gt;

&lt;h3&gt;
  
  
  BitMessage’s Message Encoding
&lt;/h3&gt;

&lt;p&gt;BitMessage’s protocol uses a custom encoding system for its messages that are sent over the network. It consists of several parts:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Message Header&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Magic (4 bytes)&lt;/strong&gt;: Identifies the network. It helps the protocol to recognize the beginning of a message. Known magic values include &lt;code&gt;0xE9BEB4D9&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command (12 bytes)&lt;/strong&gt;: ASCII string identifying the type of message. It’s padded with NULL bytes (&lt;code&gt;\x00&lt;/code&gt;) to ensure a length of 12 bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Length (4 bytes)&lt;/strong&gt;: Specifies the length of the payload. It’s an unsigned 32-bit integer, meaning it can describe a payload up to &lt;code&gt;4,294,967,295&lt;/code&gt; bytes, though restrictions limit it to 1,600,003 bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checksum (4 bytes)&lt;/strong&gt;: First 4 bytes of the SHA-512 hash of the payload to ensure data integrity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Payload (variable)&lt;/strong&gt;: The actual data being transmitted, which could vary based on the message type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Variable Length Integer (VarInt)&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1 byte&lt;/strong&gt; : For values less than &lt;code&gt;0xFD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3 bytes&lt;/strong&gt; : Starts with &lt;code&gt;0xFD&lt;/code&gt; followed by a &lt;code&gt;uint16_t&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 bytes&lt;/strong&gt; : Starts with &lt;code&gt;0xFE&lt;/code&gt; followed by a &lt;code&gt;uint32_t&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9 bytes&lt;/strong&gt; : Starts with &lt;code&gt;0xFF&lt;/code&gt; followed by a &lt;code&gt;uint64_t&lt;/code&gt; value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Variable Length String&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Prefixed with a VarInt indicating the length of the string, followed by the string itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Variable Length List of Integers&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Starts with a VarInt specifying the number of integers, followed by the integers themselves, each encoded as VarInts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Network Address Structure&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time (8 bytes)&lt;/strong&gt;: Timestamp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream (4 bytes)&lt;/strong&gt;: Stream number for the node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services (8 bytes)&lt;/strong&gt;: Node services bitfield.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv6/4 (16 bytes)&lt;/strong&gt;: IPv6 address (or IPv4 mapped into IPv6).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port (2 bytes)&lt;/strong&gt;: Network port.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. &lt;strong&gt;Inventory Vectors&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Used to announce or request objects within the network. Each entry includes a 32-byte hash representing the object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. &lt;strong&gt;Encrypted Payload&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IV (16 bytes)&lt;/strong&gt;: Initialization vector for AES-256-CBC encryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curve Type (2 bytes)&lt;/strong&gt;: Identifies the elliptic curve used (e.g., 0x02CA for secp256k1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public Key Components (X and Y)&lt;/strong&gt;: Lengths and values of the X and Y coordinates of the elliptic curve public key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ciphertext&lt;/strong&gt; : The actual encrypted data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MAC (32 bytes)&lt;/strong&gt;: Message Authentication Code using HMAC-SHA256.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  8. &lt;strong&gt;Unencrypted Message Data&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Various fields including version, address version, stream number, public keys, and a bitfield indicating node behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce Trials per Byte and Extra Bytes&lt;/strong&gt; : Difficulty settings for Proof of Work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RIPE Hash (20 bytes)&lt;/strong&gt;: Represents the receiver’s public key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Encoding&lt;/strong&gt; : Specifies how the message is formatted (e.g., UTF-8).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt; : ECDSA signature covering specific parts of the message.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  9. &lt;strong&gt;Message Types&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version Message&lt;/strong&gt; : Announces a node’s protocol version and capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verack Message&lt;/strong&gt; : Acknowledges the reception of a version message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Addr Message&lt;/strong&gt; : Provides information about known nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inv and Getdata Messages&lt;/strong&gt; : Handle the exchange of object information and requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Message&lt;/strong&gt; : Carries content that propagates across the network, such as public keys, messages, or broadcasts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  10. &lt;strong&gt;Pubkey and Broadcast Structures&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pubkey&lt;/strong&gt; : Contains public keys for signing and encryption, behavior bitfields, and optionally encrypted data (in version 4 and above).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broadcast&lt;/strong&gt; : Used for sending messages to subscribers, with version 4 and 5 utilizing tags and encryption for additional security.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There could be some improvement to this encoding format. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The protocol uses a variable-length encoding that allows smaller numbers to be represented with fewer bytes. However, the current scheme (e.g., using 0xFD, 0xFE, and 0xFF prefixes) might be wasteful for certain number ranges. A more efficient variable-length encoding scheme, such as &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/LEB128" rel="noopener noreferrer"&gt;LEB128 (Little Endian Base 128)&lt;/a&gt;&lt;/strong&gt;, which is widely used in formats like WebAssembly, encodes integers using a variable number of bytes, with no need for extra prefix bytes, making it more space-efficient for both small and large numbers.&lt;/li&gt;
&lt;li&gt;The protocol stores full 128-bit IPv6 addresses, which can be wasteful, especially for addresses with long sequences of zeros. It could use &lt;strong&gt;address compression&lt;/strong&gt; techniques, similar to how IPv6 addresses are represented textually (e.g., using &lt;code&gt;::&lt;/code&gt; to replace sequences of zeros). Alternatively, apply &lt;strong&gt;prefix compression&lt;/strong&gt; if many addresses share a common prefix.&lt;/li&gt;
&lt;li&gt;Commands are encoded as fixed-length, 12-byte ASCII strings, which is simple but inefficient and inflexible. Using a &lt;strong&gt;variable-length encoding&lt;/strong&gt; for commands, storing the command length as a prefix, followed by the command string, would reduce the size of the message when the command is shorter than 12 bytes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  BitMessage’s Message Types
&lt;/h3&gt;

&lt;p&gt;Message types refer to the different kinds of messages that nodes (computers) can send and receive in a peer-to-peer network. These messages are used for various purposes, including establishing connections, sharing information about nodes, requesting and receiving data, and managing the objects (like messages or keys) in the network.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : When two nodes first connect, they need to agree on the version of the protocol they are using.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version&lt;/strong&gt; : Tells which version of the protocol the node is using (should be version 3).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services&lt;/strong&gt; : Lists the features the node supports (like network connectivity or security options).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt; : The current time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Addresses&lt;/strong&gt; : The network addresses of the node sending and receiving the message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt; : A random number used to check if the connection is with itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Agent&lt;/strong&gt; : Information about the software being used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream Numbers&lt;/strong&gt; : The streams of messages the node is interested in.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Verack&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : A simple acknowledgment message sent in reply to the &lt;code&gt;version&lt;/code&gt; message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : Just a header with the command “verack” (short for “version acknowledgment”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt; : Signals that the connection setup is complete and both nodes are ready to communicate. After this, they can start a secure connection if both support &lt;a href="https://dev.toSSL/TLS"&gt;SSL/TLS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Addr&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : A message that provides information about other nodes in the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Count&lt;/strong&gt; : The number of addresses being shared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Address List&lt;/strong&gt; : The addresses of other nodes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Inv&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : A message used to announce that a node knows about certain objects (like messages or public keys).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Count&lt;/strong&gt; : The number of objects being announced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory&lt;/strong&gt; : Details of each object.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Getdata&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : A request to get the actual data of specific objects after they have been announced by &lt;code&gt;inv&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Count&lt;/strong&gt; : The number of objects being requested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory&lt;/strong&gt; : Details of each object requested.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Object&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What It Is&lt;/strong&gt; : This is the actual data message that gets shared across the network. It’s the primary way to send information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What It Contains&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt; : A random number used to ensure the message has been properly processed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expires Time&lt;/strong&gt; : When the object will no longer be valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Type&lt;/strong&gt; : Tells what kind of message it is (like a request for a public key, a public key, a message, or a broadcast).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version&lt;/strong&gt; : The version of the object format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream Number&lt;/strong&gt; : The stream the object is related to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Payload&lt;/strong&gt; : The actual content of the message, which varies depending on the type of object.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The message types could have been improved by implementing these methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A more detailed protocol negotiation mechanism to handle different versions and backward compatibility better.&lt;/li&gt;
&lt;li&gt;Including additional metadata about the node’s capabilities or preferences (e.g., supported encryption algorithms or message types) to optimize the interactions.&lt;/li&gt;
&lt;li&gt;Ensuring SSL/TLS handshakes are mandatory and verified before proceeding with further messages.&lt;/li&gt;
&lt;li&gt;Implementing mechanisms to dynamically update and validate node addresses to ensure that outdated or invalid addresses are removed from the list.&lt;/li&gt;
&lt;li&gt;Using methods to anonymize node addresses or using temporary addresses that change periodically to increase privacy.&lt;/li&gt;
&lt;li&gt;Supporting batch requests to retrieve multiple objects in a single &lt;code&gt;getdata&lt;/code&gt; message, reducing overhead and improving efficiency.&lt;/li&gt;
&lt;li&gt;Implementing priority mechanisms to request the most critical data first and supporting caching to avoid redundant requests for the same data.&lt;/li&gt;
&lt;li&gt;Using compression algorithms to reduce the size of &lt;code&gt;object&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;messages, especially for large payloads.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implementing version control within &lt;code&gt;object&lt;/code&gt; messages to handle changes in the object structure or content format over time.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  BitMessage’s Object Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Object types&lt;/strong&gt; are specific data structures used to perform various operations within the network. Each object type serves a particular purpose, such as requesting a public key, sending messages, broadcasting information to multiple recipients, or transmitting a public key. These objects are the building blocks of the protocol, enabling nodes (participants in the network) to communicate, authenticate, and exchange information securely and efficiently.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;&lt;code&gt;getpubkey&lt;/code&gt; Object&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt; : This object is used by a node to request a public key from another node when it has the hash of the public key (from an address) but not the key itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fields&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ripe&lt;/code&gt; (20 bytes)&lt;/strong&gt;: This is the RIPEMD-160 hash of the public key. It is included only when the address version is 3 or below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tag&lt;/code&gt; (32 bytes)&lt;/strong&gt;: This is derived from the address version, stream number, and ripe hash. It’s included when the address version is 4 or above, ensuring that the requesting node can correctly identify the public key.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;&lt;code&gt;pubkey&lt;/code&gt; Object&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt; : The &lt;code&gt;pubkey&lt;/code&gt; object contains the public key information used for cryptographic operations like signing and encryption. The format of this object evolves across different protocol versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version 2&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;behavior bitfield&lt;/code&gt; (4 bytes)&lt;/strong&gt;: Indicates the behaviors and features supported by the node. This is a set of flags that tell other nodes what to expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;public signing key&lt;/code&gt; (64 bytes)&lt;/strong&gt;: The ECC public key used for signing messages, provided in an uncompressed format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;public encryption key&lt;/code&gt; (64 bytes)&lt;/strong&gt;: The ECC public key used for encrypting messages, also in an uncompressed format.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Version 3&lt;/strong&gt; : Builds upon version 2 by adding: 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nonce_trials_per_byte&lt;/code&gt; (variable length)&lt;/strong&gt;: Defines how hard the Proof of Work (PoW) needs to be for messages accepted by the node. A higher value increases the difficulty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;extra_bytes&lt;/code&gt; (variable length)&lt;/strong&gt;: Adds to the message length to increase the difficulty of sending small messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;sig_length&lt;/code&gt; (variable length)&lt;/strong&gt;: Length of the signature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;signature&lt;/code&gt; (variable length)&lt;/strong&gt;: The ECDSA signature that covers the object header and data.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Version 4&lt;/strong&gt; : In version 4, most of the pubkey data is encrypted: 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tag&lt;/code&gt; (32 bytes)&lt;/strong&gt;: Helps in identifying the correct pubkey for decryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;encrypted&lt;/code&gt; (variable length)&lt;/strong&gt;: Contains encrypted data, which includes fields like the behavior bitfield, public signing key, and public encryption key. This encryption is intended to prevent spam or abuse of the public key.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;&lt;code&gt;msg&lt;/code&gt; Object&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt; : The &lt;code&gt;msg&lt;/code&gt; object is used for sending person-to-person messages within the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fields&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;encrypted&lt;/code&gt; (variable length)&lt;/strong&gt;: The message data is encrypted to ensure confidentiality. The details of this encryption are handled similarly to how pubkeys are encrypted, ensuring only the intended recipient can read the message.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;&lt;code&gt;broadcast&lt;/code&gt; Object&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt; : The &lt;code&gt;broadcast&lt;/code&gt; object allows a user to send messages to all subscribers of an address. This is typically used for announcements or public messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fields&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tag&lt;/code&gt; (32 bytes)&lt;/strong&gt;: Similar to the &lt;code&gt;pubkey&lt;/code&gt; object, it helps identify the broadcast messages that are relevant to a particular address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;encrypted&lt;/code&gt; (variable length)&lt;/strong&gt;: Contains the encrypted broadcast data. Like in the &lt;code&gt;msg&lt;/code&gt; object, the encryption ensures that only the intended recipients can decrypt and view the broadcast.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Encryption Mechanism&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For Version 4+ Objects&lt;/strong&gt; : 

&lt;ul&gt;
&lt;li&gt;The encryption is done using a key derived from the double SHA-512 hash of the address version, stream number, and the ripe hash of the address. This ensures that only nodes that know the address can decrypt the pubkey or broadcast message, adding a layer of privacy and security.&lt;/li&gt;
&lt;li&gt;The process involves creating a public and private key pair from the first 32 bytes of the hash, which is then used for encrypting the pubkey data.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Understanding Specific Fields&lt;/strong&gt; :
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;behavior bitfield&lt;/code&gt;&lt;/strong&gt; : This is a bitmask that specifies what behaviors the node supports. Each bit in the 32-bit field might represent a different capability or feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;public signing key&lt;/code&gt; and &lt;code&gt;public encryption key&lt;/code&gt;&lt;/strong&gt; : These are standard ECC (Elliptic Curve Cryptography) keys used in the cryptographic processes of signing messages to verify authenticity and encrypting messages to ensure privacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nonce_trials_per_byte&lt;/code&gt; and &lt;code&gt;extra_bytes&lt;/code&gt;&lt;/strong&gt; : These are parameters related to the Proof of Work mechanism, which is used to prevent spam by making it computationally expensive to send messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tag&lt;/code&gt;&lt;/strong&gt; : This is a unique identifier derived from the address data, allowing nodes to quickly determine whether a particular piece of data is relevant to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Object types also have some issues that could have been addressed and improved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instead of requesting public keys using a hash, using a more direct method to find and retrieve keys quickly.&lt;/li&gt;
&lt;li&gt;Allowing the &lt;code&gt;behavior bitfield&lt;/code&gt; and other metadata to be dynamically updated rather than fixed, so nodes can negotiate features dynamically.&lt;/li&gt;
&lt;li&gt;Implementing data compression to reduce the size of encrypted messages and improve transmission efficiency.&lt;/li&gt;
&lt;li&gt;Improving the tagging mechanism to handle larger and more complex broadcasts efficiently. For instance, using hierarchical tagging to manage different types of broadcasts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  BitMessage’s Files
&lt;/h2&gt;

&lt;p&gt;BitMessage uses several &lt;code&gt;.dat&lt;/code&gt; files to store crucial data for the client to work:&lt;/p&gt;

&lt;h3&gt;
  
  
  Knownnodes.dat
&lt;/h3&gt;

&lt;p&gt;BitMessage uses a file named &lt;code&gt;knownnodes.dat&lt;/code&gt; to store the IP addresses and ports of the nodes that run BitMessage. These nodes help bootstrap the connection to the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keys.dat
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;keys.dat&lt;/code&gt;&lt;/strong&gt; is a file used by BitMessage to store important settings and address information.&lt;/p&gt;

&lt;p&gt;This file is the most important file in BitMessage as it contains all your keys; if you lose this file, you lose your BitMessage identity (which is your private/public keys).&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration Sections
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[DEFAULT] and [bitmessagesettings]&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Address Sections&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  messages.dat
&lt;/h4&gt;

&lt;p&gt;All messages in BitMessage are stored in a &lt;a href="https://en.wikipedia.org/wiki/SQLite" rel="noopener noreferrer"&gt;SQLite&lt;/a&gt; database named &lt;code&gt;messages.dat&lt;/code&gt;, along with &lt;code&gt;keys.dat&lt;/code&gt; and &lt;code&gt;knownnodes.dat&lt;/code&gt; in the same directory.&lt;/p&gt;

&lt;p&gt;This database uses different tables for different messages, for example, messages that were retrieved and decrypted, sent messages, and also some app configurations:&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;inbox&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table contains messages that were retrieved and were successfully decrypted. It also stores trash messages as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE inbox (
    msgid blob,
    toaddress text,
    fromaddress text,
    subject text,
    received text,
    message text,
    folder text,
    encodingtype int,
    read bool,
UNIQUE(msgid) ON CONFLICT REPLACE)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;sent&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;Similar to the &lt;code&gt;inbox&lt;/code&gt; table, it contains only the sent messages, including the trashed sent messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE sent (
    msgid blob,
    toaddress text,
    toripe blob,
    fromaddress text,
    subject text,
    message text,
    ackdata blob,
    lastactiontime integer,
    status text,
    pubkeyretrynumber integer,
    msgretrynumber integer,
    folder text,
    encodingtype int
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;subscription&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table contains all the addresses that the user has subscribed to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE subscriptions (
    label text,
    address text,
    enabled bool
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;addressbook&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table contains all of the addresses that a user has communicated with in the past, like a phonebook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE addressbook (
    label text,
    address text
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;blacklist&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;As the name suggests, any address that a user blocks will be stored in this table to prevent future communications with these addresses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE blacklist (
    label text,
    address text,
    enabled bool
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;whitelist&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table, similar to the &lt;code&gt;blacklist&lt;/code&gt; table, contains addresses that are whitelisted. If the field &lt;code&gt;enabled&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;, the user can only communicate with the addresses in this table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE whitelist (
    label text,
    address text,
    enabled bool
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;knownnodes&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table was created for future use and to replace the &lt;code&gt;knownnodes.dat&lt;/code&gt; file, which never happened as the project’s development halted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE knownnodes (
    timelastseen int,
    stream int,
    services blob,
    host blob,
    port blob,
UNIQUE(host, stream, port) ON CONFLICT REPLACE)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;settings&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table, like the &lt;code&gt;knownnodes&lt;/code&gt; table, is not implemented and was set to replace the &lt;code&gt;keys.dat&lt;/code&gt; file configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE settings (
    key blob,
    value blob,
UNIQUE(key) ON CONFLICT REPLACE)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;pubkeys&lt;/code&gt; Table:
&lt;/h5&gt;

&lt;p&gt;This table contains public keys created by the user and the time they were last transmitted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE pubkeys (
    hash blob,
    transmitdata blob,
    time int,
    usedpersonally text,
UNIQUE(hash) ON CONFLICT REPLACE)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;This approach has some obvious flaws that could have been addressed relatively easily:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There is no need for storing sent and retrieved messages in separate tables; it could have been done by adding a field to a table called &lt;code&gt;messages&lt;/code&gt; to determine whether it is sent or received. This would reduce a table in the database, making it smaller, especially as it is a file-based database.&lt;/li&gt;
&lt;li&gt;Whitelists and blacklists could have been implemented into the &lt;code&gt;addressbook&lt;/code&gt; table by adding a field to determine whether the address is whitelisted or blacklisted.&lt;/li&gt;
&lt;li&gt;Using a file-based database for storing messages is not a good idea as they will get huge and will slow down as they grow more and more with usage.&lt;/li&gt;
&lt;li&gt;Configurations such as &lt;code&gt;knownnodes&lt;/code&gt; aren’t related to the messages and should have a separate database, perhaps named &lt;code&gt;configs.dat&lt;/code&gt;, to store all configurations and settings.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  BitMessage’s Stream
&lt;/h2&gt;

&lt;p&gt;In BitMessage, a stream is like a separate channel or group where nodes can communicate. Streams in BitMessage help organize and manage communication between nodes. They allow for more efficient data handling and keep the network organized.&lt;/p&gt;

&lt;p&gt;This feature was never fully implemented to have multiple streams, and all addresses use stream 1 in BitMessage. When you create a new address, you usually set it up with a stream number, which is stream 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stream 1&lt;/strong&gt; is the main or “master” stream. It’s the primary stream and, at the moment, the only one.&lt;/p&gt;

&lt;p&gt;If you have addresses in different streams, your BitMessage client will connect to other clients in those specific streams only. This helps manage and reduce the amount of data your client handles. Your client will also connect to streams of addresses you are subscribed to.&lt;/p&gt;

&lt;p&gt;Clients occasionally connect to Stream 1 to let other clients know that they exist. This helps clients find out which stream a particular address is using.&lt;/p&gt;

&lt;p&gt;If there are too many messages in a stream, clients can create new streams (child streams) to manage the load. This helps keep the traffic and messages more manageable.&lt;/p&gt;

&lt;p&gt;When someone wants to send you a private message, they need to find your stream and send it there. You then need to connect back to their stream to acknowledge receipt of the message.&lt;/p&gt;

&lt;p&gt;Broadcasts are sent to the stream associated with the sending address. If you want to receive broadcasts from another stream, you have to connect to that stream and check for messages manually. For example, if you’re in Stream 5 and want updates from Stream 1, you need to connect to Stream 1 to get those updates.&lt;/p&gt;

&lt;p&gt;This feature, if implemented fully, could benefit a searching system where users could look up different stream numbers and connect to those. It could also allow users to prioritize streams based on their preferences. This way, important streams receive more attention and resources, while less critical ones are managed with lower priority.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good BitMessage’s Proposals
&lt;/h2&gt;

&lt;p&gt;BitMessage had some good proposals to implement. If development had continued, it could have made a solid network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalability through Prefix Filtering
&lt;/h3&gt;

&lt;p&gt;This proposal was to make BitMessage more scalable. The proposal is still a work in progress, and some details are yet to be finalized. It suggests a new system to handle how messages are routed through the network to manage increasing traffic efficiently.&lt;/p&gt;

&lt;p&gt;In this proposal, every BitMessage address and network node will have a ‘prefix’ and a ‘prefix length.’ These determine how messages are routed and how much traffic each node handles.&lt;/p&gt;

&lt;p&gt;Nodes will be grouped into overlapping ‘streams’ based on these prefixes. As the network grows or shrinks, both addresses and nodes will move between streams to balance traffic and privacy.&lt;/p&gt;

&lt;p&gt;Each message or object has a ‘prefix nonce’ that determines which streams it will travel through. Objects are processed in their stream and all higher streams in the same branch.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stream Structure
&lt;/h4&gt;

&lt;p&gt;The diagram below shows the proposed structure of streams in BitMessage:&lt;/p&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnfy92702x6e1dv5jsgf.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnfy92702x6e1dv5jsgf.png" alt="Prefix Filter Streams Hierarchy.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the diagram above, the small, light blue circles represent groups of nodes, and the large colored circles represent streams.&lt;/p&gt;

&lt;h4&gt;
  
  
  Node Connections
&lt;/h4&gt;

&lt;p&gt;The diagram below shows the connections between nodes and clients under the proposed system:&lt;/p&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya707h0y2if70kswmgfe.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya707h0y2if70kswmgfe.png" alt="Node Connections Diagram.png" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nodes and clients are labeled with a stream number, which corresponds to the stream numbers in the stream structure diagram above.&lt;/p&gt;

&lt;h4&gt;
  
  
  Proposed Changes
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prefixes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Prefixes route messages through the network. Instead of creating or deleting streams, this proposal uses a vast number of possible prefix values to manage traffic and privacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node and Address Management:&lt;/strong&gt; Nodes and addresses are assigned a prefix and prefix length to control their traffic handling and balance anonymity with efficiency.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Address and Object Structure:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Address Prefix:&lt;/strong&gt; The prefix is part of the address and does not change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix Length:&lt;/strong&gt; Determines the address’s stream. Changing the prefix length adjusts the stream assignment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Structure:&lt;/strong&gt; Messages (objects) include a ‘prefix nonce’ to dictate their propagation path.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream Hierarchy:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The proposed system involves a multi-level hierarchy of streams. Each stream level handles different traffic volumes and maintains connections accordingly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How Objects Travel and Nodes Connect
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Node Connections:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Nodes connect to multiple nodes in their stream and nearby streams. They also connect directly to other streams as needed.&lt;/li&gt;
&lt;li&gt;Higher-capacity nodes maintain more connections.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Propagation:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Nodes process messages in their stream and all higher streams within the same branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Client Procedures
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Creating an Address:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The client requests information on current traffic levels, sets a prefix length for the address, and generates a pubkey with this prefix length.&lt;/li&gt;
&lt;li&gt;The client then sends the pubkey to the appropriate nodes based on the stream.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieving a Pubkey:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The client queries nodes in the stream to get the pubkey for an address, matching the address’s prefix value.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sending a Message:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The client sets the prefix nonce of the message to match the destination address’s prefix and sends it to the relevant stream.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieving Messages:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The client connects to nodes in the address’s stream or higher streams to request and process messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broadcasts:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Broadcasts are sent to all nodes in the destination address’s stream. Clients need to periodically check these streams for new broadcasts from subscribed addresses.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Argothas Architecture
&lt;/h3&gt;

&lt;p&gt;The goal of this proposal is to make it more scalable and user-friendly while preserving privacy. It is worth mentioning that this system sacrifices some aspects of complete anonymity and the ability to check for new messages instantly.&lt;/p&gt;

&lt;p&gt;The new system involves several types of servers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Server (DS):&lt;/strong&gt; Stores actual messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introduction Server (IS):&lt;/strong&gt; Handles notification messages that inform users about new messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directory Server (DIR):&lt;/strong&gt; Keeps track of all available servers so clients can find them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;New Address Process&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create Address:&lt;/strong&gt; The user creates a new BitMessage address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find Servers:&lt;/strong&gt; The user connects to a DIR to get a list of available ISs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select ISs:&lt;/strong&gt; The user chooses some ISs to use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request Access:&lt;/strong&gt; The user contacts the chosen ISs to request access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store Details:&lt;/strong&gt; If accepted, the IS’s details are stored with the user’s address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Multiple ISs?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy:&lt;/strong&gt; If one IS is down, the user can still receive messages through others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; Using multiple ISs prevents any single IS from seeing all messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New Message Process&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create Message:&lt;/strong&gt; The sender prepares the message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose DS:&lt;/strong&gt; The sender picks a Data Server to store the message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store Message:&lt;/strong&gt; The DS responds with a minimum proof-of-work value (security measure).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send Message:&lt;/strong&gt; The sender uploads the message to the DS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare Notification:&lt;/strong&gt; The sender creates a notification message (NMESSAGE) with instructions for the recipient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send Notification:&lt;/strong&gt; The sender sends the NMESSAGE to the chosen ISs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Receiving Messages&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check ISs:&lt;/strong&gt; The recipient periodically connects to their ISs to check for new notifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve Messages:&lt;/strong&gt; The recipient decrypts the notification and then fetches the actual messages from the Data Servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Onion Routing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Onion routing (like TOR) hides users’ IP addresses to prevent tracking and linking of messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Question:&lt;/strong&gt; Should BitMessage clients use TOR, or should the BitMessage network create its own onion routing system?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This proposal suggests a more scalable and private architecture for BitMessage. It involves using multiple servers to handle different types of data, distributing trust among them, and incorporating onion routing for enhanced privacy.&lt;/p&gt;




&lt;p&gt;Bitmessage was a great project aiming to create a fully decentralized and private messaging system. Even though it’s no longer maintained and has some serious issues, it was an appreciable effort in its time.&lt;/p&gt;

&lt;p&gt;By studying Bitmessage and other similar projects, we can learn valuable lessons from their innovations and challenges. These lessons help us understand what worked, what didn’t, and how we can build even better systems in the future.&lt;/p&gt;

&lt;p&gt;The dedication of the people behind Bitmessage, who worked hard to create something meaningful, is a testament to their commitment to privacy and freedom. Their work, despite its limitations, has paved the way for new ideas and improvements in the world of decentralized communication.&lt;/p&gt;

&lt;p&gt;While Bitmessage may be a project of the past, its impact continues to guide future developments in privacy-focused and decentralized technologies.&lt;/p&gt;

&lt;p&gt;As always, this post is freely available on my &lt;a href="https://github.com/zolagonano" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you see any problems or have any suggestions, please make a pull request or open an issue.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating a Muti-Algorithm simple Proof-Of-Work library in Rust</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Thu, 09 May 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/creating-a-muti-algorithm-simple-proof-of-work-library-in-rust-35a4</link>
      <guid>https://dev.to/zolagonano/creating-a-muti-algorithm-simple-proof-of-work-library-in-rust-35a4</guid>
      <description>&lt;p&gt;I had an idea for a project that required Proof of Work as a part of it, but I couldn’t find any Rust libraries that would have Argon2id or Scrypt algorithms and were meant to provide proof of work functionality without being tied to a specific blockchain. So, I decided to develop my own. When I was doing so, I wanted to show how Rust’s data types can make such things easy and clean.&lt;/p&gt;

&lt;p&gt;Okay, but what is PoW? Proof of Work is like solving a puzzle – an expensive task for a computer. It’s proof that your computer has done something difficult. It’s mostly used in cryptocurrency blockchains during mining, proving that the miner has completed the puzzle (equivalent to going to a mine and digging with a pickaxe for gold and silver). However, it’s not necessarily meant only for mining. Another common example of its use is for preventing spam on a network, which was the reason I needed to use it. For example, Bitmessage, which was an old (now defunct) P2P email network, used it to prevent spam on the network.&lt;/p&gt;

&lt;p&gt;The idea is pretty straightforward. I wanted a library that is expandable, meaning multiple algorithms can be added to it without breaking everything. Secondly, I needed it to be general-purpose. I didn’t want it to be meant for one specific blockchain; I wanted it to handle any data and verify any data using it.&lt;/p&gt;

&lt;p&gt;To start, I created a &lt;code&gt;PoWAlgorithm&lt;/code&gt; enum, which would be expanded to include algorithms that the library is going to support. For now, I’ve used SHA2_256 for testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub enum PoWAlgorithm {
    Sha2_256,
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I implemented calculate functions for it, which compute the hash of given data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;impl PoWAlgorithm {
    pub fn calculate_sha2_256(data: &amp;amp;[u8], nonce: usize) -&amp;gt; Vec&amp;lt;u8&amp;gt; {
        let mut hasher = Sha256::new();
        hasher.update(data);

        hasher.update(nonce.to_le_bytes());

        let final_hash = hasher.finalize();

        final_hash.to_vec()
    }

    pub fn calculate(&amp;amp;self, data: &amp;amp;[u8], nonce: usize) -&amp;gt; Vec&amp;lt;u8&amp;gt; {
        match self {
            Self::Sha2_256 =&amp;gt; Self::calculate_sha2_256(data, nonce),
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of structure also allows using a trait for algorithms later, reducing some of the code and making the project cleaner as it grows.&lt;/p&gt;

&lt;p&gt;Then I created the &lt;code&gt;PoW&lt;/code&gt; library, meant to calculate and verify the proof of work based on the given data, difficulty, and the algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub struct PoW {
    data: Vec&amp;lt;u8&amp;gt;,
    difficulty: usize,
    algorithm: PoWAlgorithm,
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the data, I decided to accept all types that implement serde’s Serialize trait and convert the data to JSON. This way, anyone could provide their own structs and data types to the PoW.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;impl PoW {
    pub fn new(
        data: impl Serialize,
        difficulty: usize,
        algorithm: PoWAlgorithm,
    ) -&amp;gt; Result&amp;lt;Self, String&amp;gt; {
        Ok(PoW {
            data: serde_json::to_vec(&amp;amp;data).unwrap(),
            difficulty,
            algorithm,
        })
    }

    pub fn calculate_pow(&amp;amp;self, target: &amp;amp;[u8]) -&amp;gt; (Vec&amp;lt;u8&amp;gt;, usize) {
        let mut nonce = 0;

        loop {
            let hash = self.algorithm.calculate(&amp;amp;self.data, nonce);

            if &amp;amp;hash[..target.len()] == target {
                return (hash, nonce);
            }
            nonce += 1;
        }
    }

    pub fn verify_pow(&amp;amp;self, target: &amp;amp;[u8], pow_result: (Vec&amp;lt;u8&amp;gt;, usize)) -&amp;gt; bool {
        let (hash, nonce) = pow_result;

        let calculated_hash = self.algorithm.calculate(&amp;amp;self.data, nonce);

        if &amp;amp;calculated_hash[..target.len()] == target &amp;amp;&amp;amp; calculated_hash == hash {
            return true;
        }
        false
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the actual proof of work calculation, I followed what most cryptocurrencies do. I defined target bytes, which are the bytes that the hash should match with at the beginning. The nonce is then incremented until the hash meets this target.&lt;/p&gt;




&lt;p&gt;My blog and all of its content are available under the &lt;code&gt;CC by SA 4.0&lt;/code&gt; License on my &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you notice any problems or have any improvements for the blog or its content, you’re always welcome to open a pull request.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hosting Multiple Censorship Circumvention Tools on a VPS</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Wed, 01 May 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/hosting-multiple-censorship-circumvention-tools-on-a-vps-4b7g</link>
      <guid>https://dev.to/zolagonano/hosting-multiple-censorship-circumvention-tools-on-a-vps-4b7g</guid>
      <description>&lt;p&gt;This is a guide for those who live under heavy internet censorship and restrictions and want to host their own censorship circumvention tools and services to bypass the firewalls and access the free internet. To understand how these censorship systems and firewalls work, you can check out my previous post by &lt;a href="//./how-governments-detect-and-block-your-internet-traffic"&gt;clicking here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To host your own VPN and Proxy services, you will need a VPS with unrestricted internet access (and in some extreme cases a VPS inside your country to communicate with that VPS with unrestricted access, which I’ll explain why and how later in this post).&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Sing-box to create our proxy servers
&lt;/h2&gt;

&lt;p&gt;Sing-box is a fast universal proxy platform with straightforward configuration. It can be used to run many services like Trojan, VMess, VLess, Shadowsocks, Hysteria, TUIC, and other censorship circumvention tools.&lt;/p&gt;

&lt;p&gt;For this post, I’ll be creating a Shadowsocks server and a Trojan server using Sing-box. However, you can check &lt;a href="https://sing-box.sagernet.org/configuration/" rel="noopener noreferrer"&gt;Sing-box’s configuration guide&lt;/a&gt; and choose the protocol that works best for you.&lt;/p&gt;

&lt;p&gt;For the Trojan server, we will need a domain name with a certificate. If the domain name is not available, we can generate a self-signed certificate instead.&lt;/p&gt;

&lt;p&gt;To create the self-signed certificates, run these &lt;code&gt;openssl&lt;/code&gt; commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openssl genrsa -out privkey.pem 2048
openssl req -new -key privkey.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey privkey.pem -out fullchain.pem

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should generate two files, &lt;code&gt;privkey.pem&lt;/code&gt; and &lt;code&gt;fullchain.pem&lt;/code&gt;, which we will use for TLS encryption in Sing-box.&lt;/p&gt;

&lt;p&gt;Now, let’s create the Sing-box config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "inbounds": [
    {
      "type": "trojan",
      "listen": "127.0.0.1",
      "listen_port": 4431,
      "users": [
        {
          "name": "example",
          "password": "password"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "example.org",
        "key_path": "privkey.pem",
        "certificate_path": "fullchain.pem"
      }
    },
    {
      "type": "shadowsocks",
      "listen": "127.0.0.1",
      "listen_port": 4432,
      "network": "tcp",
      "method": "2022-blake3-aes-128-gcm",
      "password": "&amp;lt;server_password&amp;gt;",
      "users": [
        {
          "name": "username",
          "password": "&amp;lt;user_password&amp;gt;"
        }
      ]
    }
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our config file is ready. It will run a Shadowsocks server for us on &lt;code&gt;127.0.0.1:4432&lt;/code&gt; and a Trojan server on &lt;code&gt;127.0.0.1:4431&lt;/code&gt;, which we will redirect traffic to using HAProxy.&lt;/p&gt;

&lt;p&gt;To run our Sing-box server, we need to execute the Sing-box command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sing-box run -c config.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optionally, you can create a systemd service for it as well to make it automatically run on boot:&lt;/p&gt;

&lt;p&gt;To set up the systemd service, create and open a file at &lt;code&gt;/etc/systemd/system/sing-box.service&lt;/code&gt; and add the following configuration (change the paths according to where your config file and Sing-box executable are located):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Sing-box Service
After=network.target

[Service]
Type=simple
ExecStart=/path/to/sing-box run -c /path/to/config.json
WorkingDirectory=/path/to/sing-box
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, reload the systemd services and enable and start the Sing-box service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl enable sing-box.service --now

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting-Up HAProxy to host multiple services on one Port
&lt;/h2&gt;

&lt;p&gt;Most of the time, you can only use common ports like 443 (which is for TLS and it’s not suspicious to have encrypted communications over this port). So, we might need to run all of our services on this port. HAProxy can help us achieve that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.haproxy.org/" rel="noopener noreferrer"&gt;HAProxy&lt;/a&gt; is a high-performance TCP/HTTP load balancer. It can spread requests across multiple servers and separate requests based on things like SNI and headers.&lt;/p&gt;

&lt;p&gt;Here is the config file for HAProxy, which takes requests from port 443 and reroutes them based on the SNI of the request to our Trojan or Shadowsocks server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend https
    bind &amp;lt;server_ip&amp;gt;:443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    use_backend trojan_server if { req_ssl_sni -i example.org }
    default_backend shadowsocks_server

backend trojan_server
    mode tcp
    server trojan_server 127.0.0.1:4431

backend shadowsocks_server
    mode tcp
    server shadowsocks_server 127.0.0.1:4432

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to add this to the end of your HAProxy config file located at &lt;code&gt;/etc/haproxy/haproxy.cfg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, you can start and enable HAProxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl enable --now haproxy

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now your proxies should be ready to use
&lt;/h2&gt;

&lt;p&gt;After setting up Sing-box and HAProxy, you can now access your proxies on the same port and hopefully bypass censorship. Additionally, you can add more services like obfs4 and OpenVPN (to be used with Stunnel or obfs4 if it’s blocked) and other stuff on the same port and the same VPS using HAProxy.&lt;/p&gt;




&lt;p&gt;My blog and all of its content are available under the &lt;code&gt;CC by SA 4.0&lt;/code&gt; License on my &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you notice any problems or have any improvements for the blog or its content, you’re always welcome to open a pull request.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How Governments Detect and Block your Internet traffic</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Thu, 25 Apr 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/how-governments-detect-and-block-your-internet-traffic-468k</link>
      <guid>https://dev.to/zolagonano/how-governments-detect-and-block-your-internet-traffic-468k</guid>
      <description>&lt;p&gt;If you have ever lived in a country with advanced internet censorship, such as China or Iran, you would know how challenging it is to bypass these restrictions. In this post, I want to discuss the methods by which these firewalls block and detect your traffic, as well as the circumvention tools and methods available for each of them.&lt;/p&gt;

&lt;p&gt;An advanced censorship system can employ a combination of these methods based on multiple factors, such as the geolocation of the destination server or its data center, as well as packet fingerprinting and throttling of suspicious traffic, among others.&lt;/p&gt;

&lt;h2&gt;
  
  
  IP Blocking
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/IP_address_blocking" rel="noopener noreferrer"&gt;Ip blocking&lt;/a&gt; is the simplest and easiest method for firewalls to implement. It involves checking the destination address of traffic, and if it matches a certain IP or IP range, the firewall will either block the traffic or route it to another IP.&lt;/p&gt;

&lt;p&gt;Because of its simplicity, it’s quite easy to bypass as well. All you have to do is route the traffic through another server whose IP is not on a block list using a &lt;a href="https://en.wikipedia.org/wiki/Proxy_server" rel="noopener noreferrer"&gt;proxy server&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Spoofing
&lt;/h2&gt;

&lt;p&gt;Most of the time, an IP can be used for multiple services. For example, YouTube and other Google services might share the same IP addresses. This would make IP blocking quite expensive for a government because they might inadvertently block some services they didn’t intend to block.&lt;/p&gt;

&lt;p&gt;In this situation, the easiest thing that can be done to block specific websites and services would be &lt;a href="https://en.wikipedia.org/wiki/DNS_spoofing" rel="noopener noreferrer"&gt;spoofing the user’s DNS traffic&lt;/a&gt; (as DNS lacks encryption and can be read along the way). If the destination domain matches a specific domain, it would return an invalid address or not respond to the user at all.&lt;/p&gt;

&lt;p&gt;The fix for this would be relatively straightforward as well. All we have to do is encrypt the DNS traffic using protocols such as &lt;a href="https://www.cloudflare.com/learning/dns/dns-over-tls/" rel="noopener noreferrer"&gt;DNS-Over-TLS&lt;/a&gt; or &lt;a href="https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-tls/" rel="noopener noreferrer"&gt;DNS-Over-HTTPS&lt;/a&gt;, &lt;a href="https://www.cloudflare.com/dns/dnssec/how-dnssec-works/" rel="noopener noreferrer"&gt;DNSSEC&lt;/a&gt;, or &lt;a href="https://www.dnscrypt.org/" rel="noopener noreferrer"&gt;DNSCrypt&lt;/a&gt;. Because the firewall wouldn’t see what domain name we’re asking for, it can’t determine whether we’re trying to access a blocked website or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protocol Blocking
&lt;/h2&gt;

&lt;p&gt;In some extreme cases, a firewall might fully block a protocol, mostly those used for VPNs such as PPTP and L2TP.&lt;/p&gt;

&lt;p&gt;This method is usually applied to protocols that wouldn’t incur significant costs. For example, if they were to block HTTPS or TLS, it would disrupt most websites regardless of whether they are blocked or not, and that can be quite expensive.&lt;/p&gt;

&lt;p&gt;To overcome this type of blocking, some protocols have been created to make proxied traffic appear as normal web or TLS traffic as much as possible. Protocols such as &lt;a href="https://github.com/XTLS/REALITY" rel="noopener noreferrer"&gt;REALITY&lt;/a&gt; and &lt;a href="https://trojan-gfw.github.io/trojan/" rel="noopener noreferrer"&gt;Trojan&lt;/a&gt; are designed for this purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packet Filtering
&lt;/h2&gt;

&lt;p&gt;A firewall might filter packets and block or throttle them based on factors such as their protocol (whether they’re TCP or UDP), size and length, destination port, and headers.&lt;/p&gt;

&lt;p&gt;For example, in extreme cases, they might fully block UDP traffic and only allow TCP connections to certain ports, such as 443 and 22, which are common ports for TLS and SSH.&lt;/p&gt;

&lt;p&gt;Bypassing this type of restriction is not difficult, but it will come with speed and bandwidth sacrifices, as you might be limited to using TCP connections, which are typically slower than UDP ones, especially for streaming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Packet Inseption (DPI)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Deep_packet_inspection" rel="noopener noreferrer"&gt;DPI (Deep Packet Inspection)&lt;/a&gt; is a method used to inspect and filter traffic in real-time, meaning that the firewall will open your packets, analyze their content, and decide whether to block them or allow them to pass through.&lt;/p&gt;

&lt;p&gt;DPI can even detect and block fully encrypted traffic through methods like fingerprinting, allowing it to determine whether the traffic is VPN or proxy traffic or normal traffic.&lt;/p&gt;

&lt;p&gt;Bypassing DPI is actually challenging, as DPI systems are constantly evolving and becoming more advanced at detecting encrypted traffic. However, so are the protocols for bypassing them.&lt;/p&gt;

&lt;p&gt;The most promising and well-tested protocol for bypassing DPI is obfuscating protocols, such as &lt;a href="https://gitlab.com/yawning/obfs4" rel="noopener noreferrer"&gt;obfs4&lt;/a&gt;, which are designed to make the traffic appear as noise or normal traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Active Probing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ensa.fi/active-probing/" rel="noopener noreferrer"&gt;Active probing&lt;/a&gt;, unlike other methods of censorship, isn’t passive; it involves automated servers sending requests to other servers to check if they’re being used for bypassing censorship or not.&lt;/p&gt;

&lt;p&gt;These servers might act as obfs4 clients and send requests to your server to examine its response.&lt;/p&gt;

&lt;p&gt;Preventing these probes is a challenging task, but there are measures that can be taken, such as only allowing connections from specific IP addresses or blocking any suspicious attempts on the server.”&lt;/p&gt;




&lt;p&gt;My blog and all of its content are available under the &lt;code&gt;CC by SA 4.0&lt;/code&gt; License on my &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you notice any problems or have any improvements for the blog or its content, you’re always welcome to open a pull request.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating an Encrypted Portable Container for ZeroNet</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/creating-an-encrypted-portable-container-for-zeronet-19ck</link>
      <guid>https://dev.to/zolagonano/creating-an-encrypted-portable-container-for-zeronet-19ck</guid>
      <description>&lt;p&gt;I have two Linux machines that I constantly switch between, and I had a problem syncing my &lt;a href="https://zeronet.dev/" rel="noopener noreferrer"&gt;ZeroNet&lt;/a&gt;&lt;sup id="fnref:1"&gt;1&lt;/sup&gt; data between my machines. Additionally, I didn’t want to share my data with a third-party server. So, I decided to make a portable USB stick for my ZeroNet that could not only be used with my devices but also with any other device running Linux. This approach also solved another problem I had with ZeroNet, which was its lack of encryption. Now, I could encrypt my USB stick and my ZeroNet data inside it without any complications.&lt;/p&gt;

&lt;p&gt;And I thought that sharing the process of doing so would save a lot of time for someone experiencing the same problem. So here’s how I set up my portable container:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Wiping the USB Stick
&lt;/h2&gt;

&lt;p&gt;Always before encrypting any devices, you should securely wipe the device so that the previous data on it becomes unrecoverable in case you lose the device or it gets stolen. To wipe this USB stick, all I did was fill it with zeros until there was no space left on it:&lt;/p&gt;

&lt;p&gt;To do so, you first need to identify the device that you want to wipe:&lt;/p&gt;

&lt;p&gt;For that, you can run the &lt;code&gt;lsblk&lt;/code&gt; command which will show all your devices and their names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lsblk -p
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
...
/dev/sdc 8:32 1 29.3G 0 disk 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output shows me that the USB stick that I’m going to use is located at &lt;code&gt;/dev/sdc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, use the &lt;code&gt;dd&lt;/code&gt; command to read from &lt;code&gt;/dev/zero&lt;/code&gt; or &lt;code&gt;/dev/urandom&lt;/code&gt; into it until it’s filled with zeros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dd if=/dev/zero of=/dev/sdc status=progress bs=128M

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You should replace &lt;code&gt;/dev/sdc&lt;/code&gt; with your own device.&lt;/p&gt;

&lt;p&gt;I recommend reading from &lt;code&gt;/dev/urandom&lt;/code&gt; as most modern Flash Memory devices use compression features, which can compress a pattern of zeros and prevent the device from getting fully and securely wiped. However, with &lt;code&gt;/dev/urandom&lt;/code&gt;, you’ll get fairly fast-generated pseudo-random data that cannot be compressed, making it the safer approach.&lt;/p&gt;

&lt;p&gt;You should wait until you get the “No space left on device” message from the &lt;code&gt;dd&lt;/code&gt; command. Then, you can proceed to encrypt the device.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Encrypting the USB Stick
&lt;/h2&gt;

&lt;p&gt;To encrypt the device, I used &lt;a href="https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup" rel="noopener noreferrer"&gt;LUKS&lt;/a&gt;&lt;sup id="fnref:2"&gt;2&lt;/sup&gt; as I only have Linux machines and I don’t need my USB stick to be readable on Windows machines. However, if you want to make it cross-platform, you can use &lt;a href="https://veracrypt.de/en/Beginner%27s%20Tutorial.html" rel="noopener noreferrer"&gt;VeraCrypt&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;**Note: ** To encrypt the device using the LUKS format, you’ll need to install the &lt;code&gt;cryptsetup&lt;/code&gt; package (usually it is already installed in most Linux distributions).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cryptsetup -y -v --type luks2 luksFormat /dev/sdc

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By running the command above, you’ll be prompted to accept the risks of overwriting data on your device. Then, you’ll be asked for a passphrase, which will be used to decrypt and unlock the USB stick.&lt;/p&gt;

&lt;p&gt;After you set up encryption, you need to open the device using &lt;code&gt;luksOpen&lt;/code&gt; and create a file system on it. For the file system, I’ve used BTRFS, which is a modern and stable enough filesystem for my purpose. You can use EXT4 as well if you want something older and more stable, but the journaling of EXT4 can cause some additional wear and tear on your device.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cryptsetup luksOpen /dev/sdc DeviceName

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you open and decrypt the device, it will be available at &lt;code&gt;/dev/mapper/DeviceName&lt;/code&gt;, and you can use this path to create a file system on the device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkfs.btrfs /dev/mapper/DeviceName -L WhateverLabelYouWant -f

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can mount your encrypted device and put the ZeroNet on it (it will mount your device on &lt;code&gt;/mnt/zeronet_container&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir /mnt/zeronet_container
sudo mount /dev/mapper/DeviceName /mnt/zeronet_container

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Setting-Up ZeroNet Bundle
&lt;/h2&gt;

&lt;p&gt;Next, you want to download the ZeroNet Bundle, which includes all the executables inside it and doesn’t need any additional packages to work. For that, I’ve downloaded the ZeroNetX Bundle, which is an actively maintained fork of ZeroNet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd /mnt/zeronet_container
wget https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-linux.zip
unzip ZeroNet-linux.zip
cd ZeroNet-linux

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a &lt;code&gt;zeronet.conf&lt;/code&gt; file in the &lt;code&gt;Zeronet-linux&lt;/code&gt; directory to enable TOR support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;force_encryption = True
tor_proxy = 127.0.0.1:9150
tor_controller = 127.0.0.1:9151
tor = always

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The ports &lt;code&gt;9150&lt;/code&gt; and &lt;code&gt;9151&lt;/code&gt; are default ports for the TOR Browser, which we will include in our container. This way, when you open your Tor Browser to access the ZeroNet, the ZeroNet will use the browser’s controller port to communicate with Tor, minimizing the need for setting up Tor and granting access to ZeroNet to use its controller port.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Setting-Up a Portable TOR Browser
&lt;/h2&gt;

&lt;p&gt;Making a portable Tor Browser is fairly easy. You only need to download the Tor Browser onto your USB stick and extract it there. Every time you want to use it, run it from there.&lt;/p&gt;

&lt;p&gt;To download the Tor Browser for Linux, you should go to &lt;a href="https://www.torproject.org/download/" rel="noopener noreferrer"&gt;https://www.torproject.org/download/&lt;/a&gt; and after downloading it, extract it into your USB stick.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Now your Portable ZeroNet is Ready to Use
&lt;/h2&gt;

&lt;p&gt;After you set everything up, you can just plug your USB stick into your machine, open it up, and run the Tor Browser and ZeroNet from there.&lt;/p&gt;

&lt;p&gt;Additionally, you can run your ZeroNet with &lt;code&gt;FireJail&lt;/code&gt; to isolate it from the rest of your system and provide some sandboxing for it.&lt;/p&gt;

&lt;p&gt;Another method, if you want to use your ZeroNet on untrusted machines portably, is through using Tails OS. You can download and boot the Tails OS on your USB stick and enable Persisted Encrypted Storage on it. Then, put your ZeroNet Bundle on the Persisted storage inside Tails and boot the device on any machine to use your ZeroNet without leaving any trace on the machine or having to trust the machine (to some extent).&lt;/p&gt;




&lt;p&gt;My blog and all of its content are available under the &lt;code&gt;CC by SA 4.0&lt;/code&gt; License on my GitHub. If you notice any problems or have any improvements for the blog or its content, you’re always welcome to open a pull request.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;ZeroNet is a peer-to-peer web-like network, which I have &lt;a href="https://dev.to/blog/posts/a-very-technical-look-at-zeronet"&gt;covered in detail in my blog&lt;/a&gt;. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LUKS (Linux Unified Key Setup) is a disk encryption specification that provides an easy-to-use, platform-independent method for securing data on storage devices. It allows users to encrypt entire partitions or storage devices, ensuring that data remains protected even if the device is lost or stolen ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Hacking a CTF: Do not use ECB mode for encryption</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Wed, 03 Jan 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/hacking-a-ctf-do-not-use-ecb-mode-for-encryption-1895</link>
      <guid>https://dev.to/zolagonano/hacking-a-ctf-do-not-use-ecb-mode-for-encryption-1895</guid>
      <description>&lt;p&gt;I recently started doing CTF challenges. A few days ago, I was working on a challenge from &lt;a href="https://247CTF.com" rel="noopener noreferrer"&gt;247CTF.com.&lt;/a&gt; I found a challenge that, in my opinion, shows why using &lt;a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation" rel="noopener noreferrer"&gt;ECB(Electronic Codebook) mode&lt;/a&gt; for encrypting with &lt;a href="https://en.wikipedia.org/wiki/Block_cipher" rel="noopener noreferrer"&gt;block ciphers&lt;/a&gt; like AES or Twofish isn’t a good idea. So, I decided to write a series of blog posts where I solve these challenges and explain how to prevent these kinds of attacks.&lt;/p&gt;

&lt;p&gt;The challenge was quite simple. It was a website with two parts: &lt;code&gt;/encrypt&lt;/code&gt; and &lt;code&gt;/get_flag&lt;/code&gt;. Both parts needed a hex-encoded message called &lt;code&gt;user&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Source Code
&lt;/h2&gt;

&lt;p&gt;This challenge provided the source code for us, making it quite easy to reverse engineer and understand how it works:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;Crypto.Cipher&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aes_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_key&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&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="n"&gt;secret_key&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DEBUG&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="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;flag_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;impossible_flag_user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AESCipher&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aes_key&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;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_ECB&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;pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&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;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&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;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;block_size&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;unpad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])]&lt;/span&gt;

    &lt;span class="k"&gt;def&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;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plaintext&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;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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hex&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decrypt&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;encrypted&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="nf"&gt;unpad&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;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&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;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hex&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;

%s

&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&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;__file__&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/encrypt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hex&lt;/span&gt;&lt;span class="sh"&gt;'&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;user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;flag_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No cheating!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AESCipher&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Something went wrong!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/get_flag&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_flag&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nc"&gt;AESCipher&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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;user&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="n"&gt;flag_user&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;flag&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Invalid user!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Something went wrong!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just by looking at the code, it’s obvious that we need to encrypt the &lt;code&gt;impossible_flag_user&lt;/code&gt; using the &lt;code&gt;AESCipher&lt;/code&gt; class defined in the code. The class employs a straightforward algorithm for padding and utilizes AES with ECB mode for encryption. The secret key is imported from another Python file, which we don’t have access to. This means we can’t simply rewrite the &lt;code&gt;AESCipher&lt;/code&gt; class and encrypt whatever we want.&lt;/p&gt;

&lt;p&gt;On the other hand, the &lt;code&gt;/encrypt&lt;/code&gt; route takes a hex-encoded payload named &lt;code&gt;user&lt;/code&gt; and decodes it. If the decoded value is equal to &lt;code&gt;impossible_flag_user&lt;/code&gt;, it returns a ‘No cheating!’ message. However, to obtain the flag, we need to provide the &lt;code&gt;/get_flag&lt;/code&gt; route with a hex-encoded payload named &lt;code&gt;user&lt;/code&gt; that, when decrypted, equals &lt;code&gt;impossible_flag_user&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/encrypt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hex&lt;/span&gt;&lt;span class="sh"&gt;'&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;user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;flag_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No cheating!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AESCipher&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Something went wrong!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what we can do is attack the implementation of the encryption scheme, which is the &lt;code&gt;AESCipher&lt;/code&gt; class. The two main issues that come to mind when looking at it are the self-rolled padding algorithm and the use of ECB mode.&lt;/p&gt;

&lt;p&gt;But what is ECB mode and how can it help us bypass that restriction? Well, ECB mode is the simplest way of encrypting blocks in block cipher algorithms. It works by breaking down the plaintext data into blocks of a fixed size and encrypting each block with the key. This process is repeated for each chunk until it reaches the last block. The final block is then padded to match the block size of the block cipher, and all the blocks are arranged in series to form the ciphertext: &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fznano.eu.org%2Fassets%2Fpics%2Fecb_encryption_mode.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%2Fznano.eu.org%2Fassets%2Fpics%2Fecb_encryption_mode.png" alt="img" width="601" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what’s the problem? ECB mode lacks &lt;a href="https://en.wikipedia.org/wiki/Confusion_and_diffusion" rel="noopener noreferrer"&gt;diffusion&lt;/a&gt;, meaning it doesn’t obscure the correlation between the plaintext and the ciphertext. This weakness is what we will leverage to our advantage when encrypting the &lt;code&gt;impossible_flag_user&lt;/code&gt; with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performing the Attack
&lt;/h2&gt;

&lt;p&gt;The first thing that came to my mind was that I could encrypt the &lt;code&gt;impossible_flag_user&lt;/code&gt; partially to obtain some encrypted segments. To achieve this, I replaced the &lt;code&gt;user&lt;/code&gt; in the plaintext with &lt;code&gt;0000&lt;/code&gt; to maintain the same length. Here are the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;939454b054b7379b0709a270b894025c1c3b822d1217b7af1516eccddb9349fc

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I encrypted only the &lt;code&gt;user&lt;/code&gt; and obtained the following result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;707ece4f0913868ec5df07d131b0822d

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all I had to do was replace one block size length (16 bytes in this case) from the first encrypted plaintext with the corresponding portion from the second encrypted plaintext:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;939454b054b7379b0709a270b894025c707ece4f0913868ec5df07d131b0822d

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, by sending this modified ciphertext to the &lt;code&gt;/get_flag&lt;/code&gt; route, we obtain the flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;247CTF{ddd01e396dc1965c3fcf943f3968aa39}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason this happened is that the &lt;code&gt;user&lt;/code&gt; was our last chunk, and because there was no random initializing vector, no matter how many times we encrypt that last chunk, we’d get the same result. Essentially, we encrypted the initial chunks and then appended the last chunk to bypass the restriction and obtain the flag.&lt;/p&gt;

&lt;p&gt;This attack could have been easily prevented by using a cipher mode that provides diffusion and &lt;a href="https://en.wikipedia.org/wiki/Authenticated_encryption" rel="noopener noreferrer"&gt;authentication&lt;/a&gt;, such as GCM_SIV. This mode eliminates the need for padding, and the ciphertext can be authenticated later.&lt;/p&gt;




&lt;p&gt;This blog is available on my &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and if you find the content interesting, you can give it a star or consider making a donation &lt;a href="https://znano.eu.org/#donate" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Guide to Security, Privacy, and Anonymity on ZeroNet</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Tue, 08 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/a-guide-to-security-privacy-and-anonymity-on-zeronet-5ep4</link>
      <guid>https://dev.to/zolagonano/a-guide-to-security-privacy-and-anonymity-on-zeronet-5ep4</guid>
      <description>&lt;p&gt;In my previous post, I took &lt;a href="https://dev.to/blog/posts/a-very-technical-look-at-zeronet"&gt;a technical look at ZeroNet&lt;/a&gt;, explaining how it works and the technologies it uses to create a peer-to-peer web-like network. In this post, I want to discuss how you can maintain privacy and security in this network, explore the potential threats, and provide some techniques to enhance your privacy and security.&lt;/p&gt;

&lt;p&gt;I will divide this guide into three main sections: “Security,” “Privacy,” and “Anonymity.” In each section, I will explain what you can do to enhance each aspect.&lt;/p&gt;

&lt;p&gt;These sections are interconnected, and as a result, there will be a lot of overlap. For example, you will need security to ensure your privacy, and you will need privacy to stay anonymous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;This section covers what is needed to protect assets, information, or prevent harm, damage, unauthorized access, or exploitation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensure Browser Security
&lt;/h3&gt;

&lt;p&gt;In the &lt;a href="https://zeronet.dev" rel="noopener noreferrer"&gt;ZeroNet&lt;/a&gt; network, no servers are hosting the sites, which means everything is executed on the client-side. Every site you visit will run JavaScript or &lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;WASM&lt;/a&gt; code in your browser. This makes browser sandboxing critically important because you cannot simply block every script and expect things to function properly. Therefore, the most important thing to stay secure in such a network is the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a well-known browser
&lt;/h3&gt;

&lt;p&gt;Use a browser that has been around for a while, as it will have had the chance to be audited and tested, and most of its vulnerabilities are likely to be fixed. Browsers like Firefox or Chromium are good options, as they have sandboxing features and vulnerabilities are detected and fixed quickly. However, the best choice would be the &lt;a href="https://www.torproject.org/download/" rel="noopener noreferrer"&gt;Tor Browser&lt;/a&gt;, which is a modified version of Firefox provided by &lt;a href="https://torproject.org" rel="noopener noreferrer"&gt;the Tor Project&lt;/a&gt;. It is designed to reduce fingerprinting and enhances security by enabling some sandboxing features of Firefox that are not enabled by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep your browser up-to-date
&lt;/h3&gt;

&lt;p&gt;Usually, most attacks come from already known and fixed vulnerabilities, and it is very unlikely to be attacked by a zero-day vulnerability. That’s why you should always keep your browser and all your software up-to-date. It prevents attacks through known and fixed vulnerabilities and reduces your attack surface area significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypt All ZeroNet Traffic
&lt;/h3&gt;

&lt;p&gt;By default, traffic encryption is not enforced for all requests and clients in ZeroNet. However, you can enforce it by adding &lt;code&gt;force_encryption = True&lt;/code&gt; to the &lt;code&gt;[global]&lt;/code&gt; section in the &lt;code&gt;zeronet.conf&lt;/code&gt; file. Alternatively, you can run your ZeroNet with the &lt;code&gt;--force_encryption&lt;/code&gt; flag, but you may accidentally forget to do so, so it’s safer to put it in the config file.&lt;/p&gt;

&lt;p&gt;By doing so, all your traffic will be secured using &lt;a href="https://en.wikipedia.org/wiki/Transport_Layer_Security" rel="noopener noreferrer"&gt;TLS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add an Additional Layer of Encryption
&lt;/h3&gt;

&lt;p&gt;You can also provide an additional layer of encryption by using a &lt;a href="https://en.wikipedia.org/wiki/Virtual_private_network" rel="noopener noreferrer"&gt;VPN(Virtual Private Network)&lt;/a&gt; or by tunneling your whole system through TOR. This will prevent your &lt;a href="https://en.wikipedia.org/wiki/Internet_service_provider" rel="noopener noreferrer"&gt;ISP(Internet Service Provider)&lt;/a&gt; from knowing you’re connecting to ZeroNet nodes.&lt;/p&gt;

&lt;p&gt;But note that using a VPN means you’re putting your trust in your VPN provider instead of your Internet Service Provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypt Your ZeroNet Data
&lt;/h3&gt;

&lt;p&gt;ZeroNet data, such as site files, even your private keys, etc., are stored in plain text inside a directory named &lt;code&gt;data&lt;/code&gt;, and ZeroNet itself doesn’t provide encryption for those files yet. However, there are several tricks to implement encryption for these files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use ZeroNet inside an encrypted virtual machine
&lt;/h3&gt;

&lt;p&gt;If you want to take it to the next level and increase the security and privacy of your ZeroNet client at the same time, you can install a fully encrypted OS inside a &lt;a href="https://en.wikipedia.org/wiki/Virtual_machine" rel="noopener noreferrer"&gt;virtual machine&lt;/a&gt; and run your ZeroNet inside it. This approach provides strong sandboxing and security for your ZeroNet data. An OS recommended for such purposes is &lt;a href="https://www.whonix.org/" rel="noopener noreferrer"&gt;Whonix OS&lt;/a&gt;, and they have a &lt;a href="https://www.whonix.org/wiki/ZeroNet" rel="noopener noreferrer"&gt;guide&lt;/a&gt; on how to use ZeroNet inside Whonix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Store your ZeroNet files in an encrypted container
&lt;/h3&gt;

&lt;p&gt;This method is simpler and offers added benefits, such as portability. You can encrypt a USB stick and store your entire ZeroNet bundle there, enabling you to use it on any machine you desire.&lt;/p&gt;

&lt;p&gt;For enhanced portability, I highly recommend using &lt;a href="https://tails.net" rel="noopener noreferrer"&gt;Tails OS&lt;/a&gt;, which routes all traffic through Tor and includes an &lt;a href="https://tails.net/doc/persistent_storage/index.en.html" rel="noopener noreferrer"&gt;Encrypted Persistent Storage&lt;/a&gt; feature. This allows you to store files like your ZeroNet bundle securely without having them deleted when you restart the Tails Os.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not log in when using a ZeroNet instance (public proxy)
&lt;/h3&gt;

&lt;p&gt;Everyone who runs a ZeroNet public proxy can see your private key and potentially steal your identity. Therefore, never use your identity or perform actions like creating an ID or site using a public proxy, as the proxy manager will have access to that site and ID just as you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;This section covers what you can do to control what information about you is shared or accessed when using ZeroNet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always use Tor
&lt;/h3&gt;

&lt;p&gt;Setting Tor mode to &lt;code&gt;Always&lt;/code&gt; will ensure that your IP address is not exposed when connecting and seeding a site in ZeroNet. Instead of IP addresses, other ZeroNet nodes will communicate with you through your &lt;a href="https://tb-manual.torproject.org/onion-services/" rel="noopener noreferrer"&gt;onion address&lt;/a&gt;, and you have multiple of them (10 by default) to reduce the fingerprinting of an onion address.&lt;/p&gt;

&lt;p&gt;To do so, you need to open a Tor controller port and allow ZeroNet to have access to the cookie authentication file.&lt;/p&gt;

&lt;p&gt;Here are the changes you will need to make in the &lt;code&gt;torrc&lt;/code&gt; file to achieve this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uncomment or add this line to open the controller port:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ControlPort 9151

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add these lines to make the cookie authentication file readable for ZeroNet:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CookieAuthFile /var/lib/tor/control_auth_cookie
DataDirectoryGroupReadable 1
CacheDirectoryGroupReadable 1
CookieAuthentication 1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add your user or the user that runs ZeroNet to the Tor group:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown -R your_user:tor /var/lib/tor/control_auth_cookie

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you’ve made these changes, you can add the following lines to the &lt;code&gt;[global]&lt;/code&gt; section in your &lt;code&gt;zeronet.conf&lt;/code&gt; file to enforce ZeroNet to use Tor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tor_proxy = 127.0.0.1:9050
tor_controller = 127.0.0.1:9151
tor = always

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these configurations, your ZeroNet instance will route its traffic through Tor, providing increased privacy and anonymity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Tor Browser or Disconnect Your Browser from the Internet
&lt;/h3&gt;

&lt;p&gt;Even if you have set Tor to ‘Always’ mode, the sites can still send a request from your browser to the clearnet and expose your real IP address. The best practice here would be to always use ZeroNet inside the Tor browser to ensure that your real IP address never leaks to the clearnet through your browser. Optionally, you can set a non-working proxy or use your browser in offline mode when using ZeroNet, as ZeroNet doesn’t require your browser to have access to the internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protect your Identity
&lt;/h3&gt;

&lt;p&gt;In ZeroNet, all identities are represented by &lt;a href="https://en.wikipedia.org/wiki/Public-key_cryptography" rel="noopener noreferrer"&gt;private keys and certificates&lt;/a&gt;, which are stored in the &lt;code&gt;users.json&lt;/code&gt; file. Therefore, it is essential to regularly back up this file if you want to ensure you don’t lose your identity on ZeroNet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use ZeroID if possible
&lt;/h3&gt;

&lt;p&gt;ID providers like CryptoID or KaffieID are considered “decentralized,” but this decentralization comes at the cost of lacking uniqueness and regulation on IDs. As a result, anyone could generate the same ID that you have and potentially use your identity. On the other hand, ZeroID follows a different approach with a centralized server that ensures usernames and IDs are unique. However, it is worth noting that using ZeroID inside the Tor Browser should help maintain privacy despite the data being sent to the clearnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anonymity
&lt;/h2&gt;

&lt;p&gt;This section covers what you can do to seperate your real identity from the identity that you have on ZeroNet.&lt;/p&gt;

&lt;h3&gt;
  
  
  You need almost everything from the Security and Privacy sections
&lt;/h3&gt;

&lt;p&gt;There’s a lot of overlap between security, privacy, and anonymity, and you should have those to achieve anonymity.&lt;/p&gt;

&lt;h3&gt;
  
  
  You need good OPSEC
&lt;/h3&gt;

&lt;p&gt;“&lt;a href="https://en.wikipedia.org/wiki/Operations_security" rel="noopener noreferrer"&gt;OPSEC&lt;/a&gt;” stands for Operational Security. It involves using specific practices and strategies to protect sensitive information. When you have applied most of the security and privacy practices, it’s mostly about OPSEC. You are the one who chooses what to share, where to share, and with whom.&lt;/p&gt;




&lt;p&gt;Privacy is a human right, and digital privacy is necessary for people living in dictatorships, journalists, or activists to stay safe in the real world. If there’s anything else that can be added, I’d be more than happy to know. This entire blog is available on &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and you can contribute to it or simply give it a star.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>zeronet</category>
      <category>privacy</category>
      <category>security</category>
    </item>
    <item>
      <title>A Very Technical Look at ZeroNet</title>
      <dc:creator>Zola Gonano</dc:creator>
      <pubDate>Mon, 17 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zolagonano/a-very-technical-look-at-zeronet-3obp</link>
      <guid>https://dev.to/zolagonano/a-very-technical-look-at-zeronet-3obp</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ZeroNet" rel="noopener noreferrer"&gt;ZeroNet&lt;/a&gt; has always been a project that I’m very passionate about, and I enjoy contributing to it. It is a Peer-to-Peer Web-Like Network that cannot be censored or taken down, thanks to its decentralized nature. When I first started exploring ZeroNet, I struggled to find comprehensive documents or blog posts that provided a clear understanding of the network. Therefore, I decided to write this blog post to make it easier for newcomers to learn more about the network and contribute to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/HelloZeroNet/ZeroNet" rel="noopener noreferrer"&gt;ZeroNet&lt;/a&gt; was created in 2015 by Tamas Kocsis as a decentralized and peer-to-peer network. It utilizes technologies such as Bitcoin’s cryptography, &lt;a href="https://en.wikipedia.org/wiki/BitTorrent" rel="noopener noreferrer"&gt;BitTorrent&lt;/a&gt; trackers, and &lt;a href="https://en.wikipedia.org/wiki/Namecoin" rel="noopener noreferrer"&gt;NameCoin&lt;/a&gt;’s domain name system. These technologies enable ZeroNet to function as a fully dynamic web-like network, in contrast to &lt;a href="https://ipfs.tech" rel="noopener noreferrer"&gt;IPFS&lt;/a&gt; which is limited to serving static files and websites. One of the key strengths of ZeroNet is its high resistance to censorship, as it operates without relying on a single central server. It also provides anonymity for users by enabling them to use the &lt;a href="https://torproject.org" rel="noopener noreferrer"&gt;TOR&lt;/a&gt; network and hide their IP address while using ZeroNet. In ZeroNet, every site has an address that is represented by a Bitcoin public key. Peers for the sites are discovered through various methods, including the use of BitTorrent trackers. However, it’s worth noting that this is the only instance where a central server comes into play. To eliminate the reliance on a central server, ZeroNet provides an internal plugin called BootStrapper, which allows peers to function as trackers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How exactly do we find other peers?
&lt;/h2&gt;

&lt;p&gt;As mentioned before the main method for finding the peers that are hosting the site on the ZeroNet is BitTorrent Trackers, BitTorrent trackers are an essential part of the BitTorrent protocol as they hold the information that what peer holds what piece of data, and ZeroNet uses them for the same purpose. When your ZeroNet client tries to access a site it asks the trackers for the peers that are hosting the website and when your client gets the peers list it starts downloading the site’s content and it becomes a peer itself and the next time someone comes to that site they might download a piece of it from you.&lt;/p&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%2Fznano.eu.org%2Fassets%2Fpics%2Fbittorrent_tracker.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%2Fznano.eu.org%2Fassets%2Fpics%2Fbittorrent_tracker.png" alt="How BitTorrent Trackers work illustration" width="602" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But BitTorrent trackers are not the only option for discovering peers of a site. ZeroNet offers a plugin called &lt;code&gt;AnnounceZero&lt;/code&gt; that utilizes the ZeroNet Protocol to find peers. This plugin is particularly useful for locating peers on the TOR network, as BitTorrent trackers are not capable of performing this function.&lt;/p&gt;

&lt;p&gt;The BitTorrent Tracker works through a plugin named &lt;code&gt;AnnounceBitTorrent&lt;/code&gt; which operates as follows: It collects all the trackers that start with &lt;code&gt;http://&lt;/code&gt;, &lt;code&gt;https://&lt;/code&gt;, and &lt;code&gt;udp://&lt;/code&gt;, and sends them a request with the following parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "info_hash": "SHA1_HASH_OF_SITE_ADDRESS",
  "peer_id": "YOUR_PEER_ID",
  "port": "YOUR_FILESERVER_PORT",
  "uploaded": 0,
  "downloaded": 0,
  "left": 431102370,
  "compact": 1,
  "numwant": NUMBER_OF_PEERS_NEEDED,
  "event": "started"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the tracker has any peers associated with that &lt;code&gt;info_hash&lt;/code&gt;, it will return them in a BenCode, which is a binary serialization format commonly used in BitTorrent. Here’s a Python code snippet that demonstrates the process behind the scenes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import hashlib, bencode, requests, urllib

tracker_url = "https://some_tracker:443/announce"
peer_id = "-UT3530-some_id"
peer_port = 15441
number_wanted = 2
site_sha1 = hashlib.sha1(b"1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d").digest()

params = {
 "info_hash": site_sha1,
 "peer_id": peer_id,
 "port": peer_port,
 "uploaded": 0, "downloaded": 0, "left": 431102370,
 "compact": 1,
 "numwant": number_wanted,
 "event": "started"
 }

response = requests.get(tracker_url+"?"+urllib.parse.urlencode(params)).content
print(bencode.decode(response))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we execute this code, we would obtain our peers. However, please note that the peer information would be in binary encoding and would need to be decoded in order to establish connections with them. In this blog post, we won’t cover the decoding process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 b'complete': 0,
 b'incomplete': 15,
 b'interval': 1800,
 b'min interval': 300,
 b'peers': b'\xbc\xe2D\xf3\x00\x01PuW\xb3\x00\x01'
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;AnnounceZero&lt;/code&gt; plugin functions in a similar manner, but the request it sends to trackers starting with &lt;code&gt;zero://&lt;/code&gt; has slightly different parameters. Here is an example of the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "hashes": ["SITE_ADDRESS_HASHES"],
  "onions": ["YOUR_ONION_ADDRESSES"],
  "port": YOUR_FILESERVER_PORT,
  "need_types": ["PEERS_TYPES"],
  "need_num": NUMBER_OF_PEERS_NEEDED,
  "add": ["TYPE_OF_ADDRESSES_TO_REACH_YOU"]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this request, the &lt;code&gt;need_types&lt;/code&gt; parameter specifies the type of peers you want to receive, which can be either &lt;code&gt;onion&lt;/code&gt; or &lt;code&gt;ipv4&lt;/code&gt;. The &lt;code&gt;onions&lt;/code&gt; field contains your own onion addresses for communication, and the &lt;code&gt;add&lt;/code&gt; field indicates the type of addresses (ipv4 or onion) through which others can reach you. If you have set Tor mode to &lt;code&gt;Always&lt;/code&gt;, the value for &lt;code&gt;add&lt;/code&gt; will always be &lt;code&gt;onion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are several other plugins designed for the same purpose. For example, the &lt;code&gt;AnnounceLocal&lt;/code&gt; plugin enables peer discovery on a Local Area Network (LAN) through UDP broadcasting. The &lt;code&gt;AnnounceShare&lt;/code&gt; plugin allows peers to share discovered trackers with each other. Additionally, there is a plugin called &lt;code&gt;Bootstrapper&lt;/code&gt; that is disabled by default to prioritize user privacy. The &lt;code&gt;Bootstrapper&lt;/code&gt; plugin functions as a BitTorrent Tracker server running on the user’s client, facilitating peer discovery within the ZeroNet network.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we validate the content?
&lt;/h2&gt;

&lt;p&gt;In ZeroNet, the data and content of a site are hosted by its visitors. However, to prevent corruption of the data, ZeroNet utilizes &lt;a href="https://en.wikipedia.org/wiki/Hash_function" rel="noopener noreferrer"&gt;hash functions&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Checksum" rel="noopener noreferrer"&gt;checksums&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Digital_signature" rel="noopener noreferrer"&gt;cryptographic signatures&lt;/a&gt;. As mentioned earlier, ZeroNet site addresses are Bitcoin public keys, and the user creating the site possesses the private key.&lt;/p&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%2Fznano.eu.org%2Fassets%2Fpics%2Fchecksum.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%2Fznano.eu.org%2Fassets%2Fpics%2Fchecksum.png" alt="Illustration of how checksums work" width="483" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When downloading a ZeroNet site, the first file retrieved is the &lt;code&gt;content.json&lt;/code&gt; file. This file contains the SHA512 checksum for each available file within the site. Additionally, it includes a &lt;code&gt;sign&lt;/code&gt; field that ensures the integrity of the content.json file itself. By verifying the signature, we can confirm that the content.json file is valid and has been signed by the owner of the site.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code&gt;content.json&lt;/code&gt; file for an empty site that I just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "address": "17u6wJX7fCd9BZwLX8JyhVKTwxb1uEhzcH",
 "address_index": 5655359,
 "background-color": "#FFF",
 "clone_root": "template-new",
 "cloned_from": "1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d",
 "description": "",
 "files": {
  "index.html": {
   "sha512": "542f7724432a22ceb8821b4241af4d36cfd81e101b72d425c6c59e148856537e",
   "size": 1114
  },
  "js/ZeroFrame.js": {
   "sha512": "76a24d167e8a4c45f7d1b315efe31e4b4ccb19efef011c080994c94045ff4c93",
   "size": 5088
  }
 },
 "ignore": "",
 "inner_path": "content.json",
 "modified": 1689603718,
 "postmessage_nonce_security": true,
 "signers_sign": "HMGXIah7OTimruksGGqAhzC821bWemxkmS9MG6DlrIJDGpHuIb2MYGO0UpAzxd0nfUzF4x0xxSal1rfbBD0sok4=",
 "signs": {"17u6wJX7fCd9BZwLX8JyhVKTwxb1uEhzcH": "G3jkxsTv+acg0Bzm7+EJZxBznaXdMhrKD3YKSdlMRGsNYUSCzbZ0cSag+VUIkMuPhH2ApveJOglAZcytJik59Lc="},
 "signs_required": 1,
 "title": "my new site",
 "translate": ["js/all.js"],
 "zeronet_version": "0.7.6-internal 2"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the &lt;code&gt;content.json&lt;/code&gt; file is retrieved, ZeroNet looks for the &lt;code&gt;files&lt;/code&gt; field and downloads the files listed in it. It verifies the integrity of each file by comparing the hash in the &lt;code&gt;content.json&lt;/code&gt; file with the hash of the downloaded file. If the hashes match, it means that the file has not been changed or lost during the downloading process.&lt;/p&gt;

&lt;p&gt;The signatures in ZeroNet are based on the same &lt;a href="https://en.wikipedia.org/wiki/EdDSA" rel="noopener noreferrer"&gt;cryptographic techniques used in Bitcoin’s signatures&lt;/a&gt;, which have undergone audits and have been established as secure over a long period of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How sites are created?
&lt;/h2&gt;

&lt;p&gt;ZeroNet’s data and settings are stored in the &lt;code&gt;data&lt;/code&gt; directory. Within this directory, there is a file called &lt;code&gt;users.json&lt;/code&gt; that contains the private keys for sites, certificates for ID systems, and a &lt;code&gt;master_seed&lt;/code&gt; field from which site keys are derived.&lt;/p&gt;

&lt;p&gt;Here is an example of the &lt;code&gt;users.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "1NupA7xwj4qiQzh58Zu4oKn6c3zQUYGdbt": {
    "certs": {},
    "master_seed": "14cacb9f9321b&amp;lt;CENSORED&amp;gt;70a61a9dda362",
    "settings": {
      "theme": "light",
      "use_system_theme": true
    },
    "sites": {
      "17u6wJX7fCd9BZwLX8JyhVKTwxb1uEhzcH": {
        "auth_address": "18Vijw97tkMp7sYYiuX5pvoewpKybCfxZ2",
        "auth_privatekey": "5JgiXeSAPJ1tF&amp;lt;CENSORED&amp;gt;cx6QSSdXhuxtS",
        "privatekey": "5KNmLu2S6&amp;lt;CENSORED&amp;gt;T1hu1Lthdp2SRr"
      }
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you create a site in ZeroNet, a random HD Keypair (&lt;a href="https://www.w3.org/2016/04/blockchain-workshop/interest/robles.html" rel="noopener noreferrer"&gt;hierarchical deterministic keys&lt;/a&gt;) will be derived from your &lt;a href="http://bip32.org/" rel="noopener noreferrer"&gt;BIP32&lt;/a&gt; encoded &lt;code&gt;master_seed&lt;/code&gt;, and it will be written to your &lt;code&gt;users.json&lt;/code&gt; file. This allows you to restore all your site’s private keys by having your master seed.&lt;/p&gt;

&lt;p&gt;The process involves generating an index, which is a random number between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;29639936&lt;/code&gt;. This index is used to derive the private key from your master seed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index = (a random index between 0 and 29639936)
private_key = HDPrivateKey(master_seed, index)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it’s also possible to use normal Bitcoin keypairs that are not associated with your master seed. In fact, you can even generate a custom public key using tools like VanityGen.&lt;/p&gt;

&lt;p&gt;You might notice that there is another keypair named &lt;code&gt;auth_address&lt;/code&gt; and &lt;code&gt;auth_privatekey&lt;/code&gt; in the &lt;code&gt;users.json&lt;/code&gt; file. These two addresses act as your identity on the site, and their primary use case is for identity systems like ZeroID. These keypairs are separate from the site’s private keys and serve to authenticate and identify you on the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Identities work in ZeroNet?
&lt;/h2&gt;

&lt;p&gt;Identities in ZeroNet are provided by an ID provider such as &lt;a href="https://github.com/HelloZeroNet/ZeroID" rel="noopener noreferrer"&gt;ZeroID&lt;/a&gt;, (which acts as a centralized system to ensure uniqueness of the IDs). When a user requests an ID, the provider signs them a Certificate, which is a cryptographic signature of their public address and the username they requested. The validity of this Certificate is later verified by matching it with the provider’s public key, ensuring the authenticity and integrity of the identity.&lt;/p&gt;

&lt;p&gt;The Cert is generated using the following process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cert = Base64(BitcoinSign(PROVIDER_PRIVATE_KEY, (USER_AUTH_ADDRESS + "#METHOD_OF_CREATION/") + USERNAME))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if a user with the address &lt;code&gt;18Vijw97tkMp7sYYiuX5pvoewpKybCfxZ2&lt;/code&gt; wants the username &lt;code&gt;zeronet_user&lt;/code&gt; and uses the web interface, the message that would be signed is constructed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cert = Base64(BitcoinSign(PROVIDER_PRIVATE_KEY, "18Vijw97tkMp7sYYiuX5pvoewpKybCfxZ2#web/zeronet_user"))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s an example of accepted ID providers in a site’s &lt;code&gt;data/users/content.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"cert_signers": {
  "cryptoid.bit": ["18143WPue3rQykNaopx5KJKzYmaYhCjqhv"],
  "zeroid.bit": ["1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz"]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Domain Name System in ZeroNet
&lt;/h2&gt;

&lt;p&gt;Domain names are provided using NameCoin’s IDs to help users remember the site’s addresses. The way it works is that a server transfers all the NameCoin domains that have the &lt;code&gt;zeronet&lt;/code&gt; key in them to a ZeroNet site named ZeroName.&lt;/p&gt;

&lt;p&gt;Example domain registered for ZeroNet in NameCoin’s blockchain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": {
    "formatted": "ZeroNet project"
  },
  "bitcoin": {
    "address": "1QDhxQ6PraUZa21ET5fYUCPgdrwBomnFgX"
  },
  "zeronet": {
    "": "1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr",
    "blog": "1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8",
    "talk": "1TaLk3zM7ZRskJvrh3ZNCDVGXvkJusPKQ"
  },
  "ns": [
    "ns1.domaincoin.net",
    "ns2.domaincoin.net"
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when a user looks for a site with the domain name &lt;code&gt;zeronetwork.bit&lt;/code&gt;, it looks it up from the ZeroName site and redirects the user to the public key associated with that domain name.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Databases work in ZeroNet?
&lt;/h2&gt;

&lt;p&gt;ZeroNet also provides decentralized databases, making it a dynamic network. The structure of the database is defined in a file named &lt;code&gt;dbschema.json&lt;/code&gt;, where tables, fields, and types are specified. ZeroNet offers APIs for site developers to interact with the database and modify the data. The data is stored in the site’s data directory, and when it changes, it is automatically updated for other peers, ensuring synchronization.&lt;/p&gt;

&lt;p&gt;Here’s a simplified example of a dbschema for a forum-like site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "database": "ZeroTalk",
  "tables": {
    "topic": {
      "cols": [
        ["topic_id", "INTEGER"],
        ["title", "TEXT"],
        ["body", "TEXT"],
        ["added", "DATETIME"]
      ]
    },
    "comment": {
      "cols": [
        ["comment_id", "INTEGER"],
        ["body", "TEXT"],
        ["added", "DATETIME"],
        ["topic_id", "INTEGER REFERENCES topic (topic_id)"]
      ]
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the corresponding &lt;code&gt;data.json&lt;/code&gt; would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "topics": [
    {
      "topic_id": 1,
      "title": "First Topic",
      "body": "This is the first topic.",
      "added": "2022-01-01 10:00:00"
    },
    {
      "topic_id": 2,
      "title": "Second Topic",
      "body": "This is the second topic.",
      "added": "2022-02-01 12:00:00"
    }
  ],
  "comments": [
    {
      "comment_id": 1,
      "body": "Comment 1",
      "added": "2022-01-01 11:00:00",
      "topic_id": 1
    },
    {
      "comment_id": 2,
      "body": "Comment 2",
      "added": "2022-02-01 13:00:00",
      "topic_id": 2
    }
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example showcases a simple database structure for a forum-like site with two tables: &lt;code&gt;topic&lt;/code&gt; and &lt;code&gt;comment&lt;/code&gt;. The &lt;code&gt;topic&lt;/code&gt; table contains columns for the topic ID, title, body, and timestamp. Similarly, the &lt;code&gt;comment&lt;/code&gt; table includes columns for the comment ID, body, timestamp, and a foreign key referencing the topic ID in the &lt;code&gt;topic&lt;/code&gt; table. The accompanying &lt;code&gt;data.json&lt;/code&gt; file presents sample data entries for topics and comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get started with ZeroNet?
&lt;/h2&gt;

&lt;p&gt;While the official development of ZeroNet has not been active since 2020, there are several forks that continue to work on the project. Some of these forks are even reimplementing ZeroNet in other languages such as Rust, which would eventually increase its security and performance. Here are some links to these forks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ZeroNetX - &lt;a href="https://github.com/ZeroNetX/ZeroNet" rel="noopener noreferrer"&gt;https://github.com/ZeroNetX/ZeroNet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ZeroNet-rs (Rust Implementation) - &lt;a href="https://github.com/ZeroNetX/zeronet-rs" rel="noopener noreferrer"&gt;https://github.com/ZeroNetX/zeronet-rs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;zeronet-conservancy - &lt;a href="https://github.com/zeronet-conservancy/zeronet-conservancy" rel="noopener noreferrer"&gt;https://github.com/zeronet-conservancy/zeronet-conservancy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, if you’re interested in using ZeroNet but don’t know where to start, I have created a curated list on my GitHub called “awesome-zeronet”. This list provides resources and links to new sites on ZeroNet, and you can also contribute by adding sites that are not yet listed. You can find the list at &lt;a href="https://github.com/zolagonano/awesome-zeronet" rel="noopener noreferrer"&gt;https://github.com/zolagonano/awesome-zeronet&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts on ZeroNet
&lt;/h2&gt;

&lt;p&gt;ZeroNet might be a great approach towards achieving a decentralized web, but it is far from perfect. It lacks encryption for data and still depends on central servers to operate properly, such as BitTorrent Trackers and ZeroID. However, it can be improved. If you are interested, you can start contributing to make it better.&lt;/p&gt;




&lt;p&gt;As always, the entire blog is available on my &lt;a href="https://github.com/zolagonano/zolagonano.github.io" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and I would greatly appreciate it if you could point out any inaccuracies, grammatical errors, technical mistakes, or simply give it a star. Your contributions means a lot to me.&lt;/p&gt;

&lt;p&gt;Here are some of the resources used in this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/ZeroNet" rel="noopener noreferrer"&gt;en.wikipedia.org/wiki/ZeroNet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zeronet.io/docs/site_development/getting_started/" rel="noopener noreferrer"&gt;zeronet.io/docs/site_development//&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/HelloZeroNet/ZeroID" rel="noopener noreferrer"&gt;github.com/HelloZeroNet/ZeroID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/HelloZeroNet/ZeroNet" rel="noopener noreferrer"&gt;github.com/HelloZeroNet/ZeroNet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>web3</category>
      <category>zeronet</category>
      <category>decentralized</category>
      <category>anonymity</category>
    </item>
  </channel>
</rss>
