Back to blog

Client-Side AES-256-GCM in Bitburner: Encryption in Your Browser 🔒

Published October 6, 2025
Updated October 6, 2025
7 min read

A practical guide to how Bitburner encrypts your message in the browser with AES-256-GCM, including keys, IVs, auth tags, and common pitfalls.

If you are curious how Bitburner keeps your message safe before it ever leaves your browser, this post is for you. We use client-side AES-256-GCM encryption with the Web Crypto API. It sounds heavy, but the idea is simple: encrypt in the browser, send only ciphertext. You can try the app here: bitburner.vberkoz.com.

This article focuses only on encryption in the browser. I will not repeat the one-time link logic or the “key in the URL” topic, because those are covered in other posts. Here we go deep into AES-256-GCM, what it gives you, and what mistakes you should avoid.

Why client-side encryption matters in Bitburner 🔐

Client-side encryption means the plaintext never reaches the server. Your browser takes the message, encrypts it, and sends only encrypted bytes. The server stores ciphertext, not readable text.

The value is trust reduction:

  • the server cannot read the message,
  • logs are safer,
  • database leaks do not expose plaintext.

This is a big step above “encrypt at rest” where the server still has the decryption keys.

Why AES-256-GCM is used ⚙️

AES is a standard block cipher. “256” is the key size in bits. “GCM” is a mode that gives two things at once:

  • confidentiality (nobody can read the message),
  • integrity (nobody can modify the ciphertext without detection).

GCM includes an authentication tag. If someone changes even one byte, decryption fails. This is important for secure sharing because it prevents silent tampering.

AES-256-GCM is fast on modern devices and built directly into the Web Crypto API, which makes it reliable and safe to use in browsers.

The Web Crypto API is the right tool 🧠

Browsers provide the Web Crypto API so you can do real cryptography without custom JavaScript implementations. This is important, because crypto code is easy to mess up.

With Web Crypto:

  • keys are generated securely by the browser,
  • encryption is implemented in native code,
  • the API is tested and standardized.

This is why Bitburner uses Web Crypto instead of third-party crypto libraries for the core encryption.

The encryption flow in the browser 🔁

At a high level, the flow looks like this:

  1. Generate a random 256-bit key.
  2. Generate a random IV (nonce).
  3. Encrypt the message with AES-GCM.
  4. Store ciphertext + IV together.
  5. Send ciphertext + IV to the server.

Let’s break these pieces down.

Step 1: key generation 🔑

You should never create your own key from a password with simple hashing. Instead, the browser can generate a secure random key for AES-GCM.

This is a strong random key:

  • 256 bits (32 bytes),
  • cryptographically secure,
  • not guessable.

The key is what makes the message readable. Without it, ciphertext is useless noise.

Step 2: IV (nonce) generation 🎲

AES-GCM requires a random IV (initialization vector). This is not a secret, but it must be unique for each encryption with the same key.

If you reuse an IV with the same key, you break security. This is a common mistake in home-made crypto.

Bitburner generates a fresh random IV for every message. The IV is sent along with the ciphertext, because it is needed for decryption.

Step 3: encrypting the message 🔒

Now the browser encrypts:

  • input: plaintext string
  • output: ciphertext bytes + auth tag

In AES-GCM, the auth tag is part of the output. It proves the ciphertext was not modified.

If the ciphertext is changed, decryption will fail with an error. This protects your message from tampering.

Step 4: encoding for transport 📦

Encryption outputs raw bytes. But servers and APIs often prefer JSON strings, not binary data.

So Bitburner converts:

  • ciphertext bytes -> base64 string
  • IV bytes -> base64 string

Then it sends JSON like:

{
  "ciphertext": "...",
  "iv": "..."
}

This is safe. Base64 is not encryption, it is just a transport format.

Step 5: decryption on the receiver side 🔓

When the receiver opens the link, the browser does the opposite:

  • decode base64 to bytes,
  • use IV + key to decrypt,
  • verify auth tag,
  • show plaintext.

If any part is wrong (wrong key, wrong IV, modified ciphertext), decryption fails. This is expected and it is good.

What “AES-256-GCM” gives you in practice ✅

For real users, the benefits are:

  • the server never sees plaintext,
  • encrypted data is useless without the key,
  • modifications are detected automatically.

This is why AES-GCM is used for modern secure messaging and storage. It is both safe and fast.

Common mistakes to avoid ❌

Even with a good algorithm, small mistakes can break security. These are the main ones:

  • Reusing IVs with the same key.
  • Using weak random sources.
  • Storing keys on the server.
  • Logging plaintext before encryption.
  • Using custom crypto libraries with unknown quality.

Bitburner avoids these by using browser primitives and strict flow: generate key, generate IV, encrypt, then send.

Performance in the browser is very good ⚡

AES-GCM is fast. Even on mobile devices, encrypting a short text is instant.

This makes client-side encryption user friendly. Users do not see delays. They just press “Create link” and it works.

The main performance costs are not from crypto but from network and UI rendering.

Why we do not use passwords as keys 🧩

Some tools allow users to enter a password and use that as the encryption key. This is risky because human passwords are weak.

If you want a user-supplied password, you must derive a key with a slow KDF like PBKDF2, scrypt, or Argon2. That adds complexity.

Bitburner keeps it simple: it uses a strong random key and stores it in the link. This makes the crypto strong by default. If you want a password layer, you can add it separately, but it should never replace the random key.

Integrity matters as much as secrecy 🧪

Many people think encryption is only about hiding the message. But integrity is just as important.

Imagine someone intercepts the ciphertext and changes it. With AES-GCM, decryption fails. So you never see a tampered message. This is a big safety feature.

Without integrity, you could show corrupted or malicious content without knowing.

Handling text and encoding correctly 🧵

Encryption works on bytes, not strings. So the browser needs to:

  • convert text -> UTF-8 bytes before encrypting,
  • convert bytes -> text after decrypting.

If you mess this up, you get broken messages or weird characters. Bitburner uses standard UTF-8 conversion so your message is stable and readable.

Client-side crypto is not a magic shield 🧯

It is strong, but not magic. It does not protect against:

  • malware on the device,
  • compromised browser extensions,
  • someone taking a screenshot of your message.

So client-side AES-256-GCM is about protecting the server and storage layer, not about endpoint security. This is an important honest limitation.

SEO-friendly summary for quick readers 📌

Bitburner encrypts your message in the browser using AES-256-GCM with the Web Crypto API. A random 256-bit key and a random IV are generated, then the message is encrypted and sent as ciphertext to the server. The server stores only encrypted data, so it cannot read the message. Decryption happens locally in the receiver’s browser using the key from the link. AES-GCM also adds integrity, so tampering is detected.

Final thoughts ✅

Client-side AES-256-GCM is the core reason Bitburner can promise “we do not read your message.” It is not marketing; it is a technical design. The encryption happens before the message leaves your device, and the server stores only ciphertext.

If you care about keeping secrets out of server logs and databases, browser encryption is the right approach. It is fast, standardized, and safe when used correctly.