Beating the Rubber Hose Cryptanalysis

The Ultimate Guide to Deniable Encryption

·

14 min read

Alright folks, gather around because I’m about to take you on a journey that starts in the mundane world of everyday coding and ends in the deep, thrilling abyss of deniable encryption. This isn’t just a story about code – it’s about paranoia, privacy, and the lengths we go to protect our secrets. Trust me, by the end of this, you’ll be locking your journal in a safe and wondering if your phone is eavesdropping on you.

The Spark of an Idea

It all started on a rainy Tuesday afternoon. I was in my favorite coffee shop, sipping on an overpriced latte, and banging my head against the wall – metaphorically, of course. I was working on a project that involved basic encryption. Nothing fancy, just your run-of-the-mill "keep-the-nosey-neighbor-out-of-my-business" kind of stuff. But then, I stumbled upon a blog article by Oren Eini, aka Ayende Rahien, the CEO of RavenDB. He had written an intriguing piece on deniable encryption. The article was both fascinating and horrifying. The thought that someone could be compelled to give up their secrets, no matter how well-protected, stuck with me.

In his article, Ayende described a concept where you could provide a key that reveals a different, benign message when forced to decrypt. This way, if someone pressures you for your decryption key, you can reveal a decoy password, keeping your real secrets hidden. This was my "Eureka!" moment. I realised that there was a way to enhance privacy even under duress.

Ayende's explanation was clear and concise. He detailed the technical feasibility of implementing such a system, even including code snippets to illustrate the concept. However, his implementation was in C#. While C# is a powerful language, I wanted to make this technology accessible to as many people as possible. That meant creating a web-based solution using JavaScript, a language that runs in any modern web browser. This would lower the barrier to entry and allow anyone, regardless of their technical background, to benefit from deniable encryption.

Rubber Hose Cryptanalysis

But before we dive deeper, let’s talk about something equally fascinating and terrifying: rubber hose cryptanalysis. This term refers to extracting cryptographic secrets (like encryption keys) through coercion or torture. It’s a blunt, brutal method where all your sophisticated algorithms and encryption techniques become useless. If someone threatens you with violence, chances are, you’ll give up your password. And this is precisely where deniable encryption comes into play. It offers a way to protect sensitive data even when you’re forced to reveal a password.

The concept of rubber hose cryptanalysis highlights a fundamental flaw in traditional encryption methods. No matter how secure your encryption is, it becomes useless if someone can coerce you into revealing your password. This is not a hypothetical scenario. Journalists, activists, and dissidents around the world face this threat regularly. Governments and other powerful entities have no qualms about using force to access sensitive information.

Deniable encryption is designed to mitigate this risk. By allowing users to provide a decoy key under duress, it offers a layer of protection that traditional encryption methods cannot. Even if you're forced to reveal a password, the real secrets remain hidden. This concept intrigued me. It was like adding a secret compartment to a safe – a way to hide the most valuable items in plain sight.

Deniable Encryption

Encryption, at its core, is about converting data into a format that can only be read by someone with the correct key. But traditional encryption has a flaw – if you’re forced to reveal your key, all your secrets are laid bare. Enter deniable encryption, the James Bond of cryptographic techniques.

Here’s the lowdown: Deniable encryption allows you to encrypt data in such a way that you can plausibly deny the existence of certain information. Imagine you have a safe with two compartments. One compartment is for the fake documents you’re okay with showing, and the other holds your real secrets. When someone demands the key, you give them the one to the fake compartment. They think they’ve got everything, but your real secrets remain hidden.

The beauty of deniable encryption lies in its simplicity and effectiveness. By using two different keys for the same encrypted data, it creates two plausible scenarios. The decoy key reveals a harmless message, while the real key reveals the sensitive information. The attacker has no way of knowing that a second key exists, and therefore cannot compel you to reveal it. This dual-layer protection is what makes deniable encryption so powerful.

Deniable encryption is not a new concept, but its implementation has often been limited to academic research and theoretical discussions. Bringing it into the realm of practical, everyday use was the challenge I set for myself. I wanted to create a tool that anyone could use to protect their privacy, regardless of their technical expertise. This meant building an application that was not only secure but also user-friendly and accessible.

Why Deniable Encryption is a Game-Changer

Before we dive into the nitty-gritty, let’s talk about why deniable encryption is a big deal.

  1. Protection Under Duress: In scenarios where revealing a password is unavoidable (think journalists, activists, or even corporate whistleblowers), deniable encryption provides a way to protect the most sensitive information. By offering a decoy message, it creates a plausible alternative that can be revealed without compromising the real data. This can be a lifesaver in situations where the stakes are high, and the consequences of revealing sensitive information are severe.

  2. Plausible Deniability: If someone demands your encrypted data and forces you to decrypt it, you can show them the decoy data. They have no way of knowing there's more hidden behind another key. This layer of plausible deniability is what makes deniable encryption so effective. It’s like having a secret compartment in your safe – even if someone gets access, they don’t know what they’re missing.

  3. Enhanced Privacy: For the average person, deniable encryption can add an extra layer of privacy. Whether it’s personal diaries, financial records, or sensitive documents, your secrets remain yours alone. In a world where data breaches and privacy violations are becoming increasingly common, having an extra layer of protection can provide peace of mind.

  4. Versatile Use Cases: This technology can be applied in various scenarios, from safeguarding personal communications to protecting corporate secrets. It's a versatile tool that can adapt to different needs. Whether you’re a journalist protecting your sources, a whistleblower revealing corporate corruption, or just someone who values their privacy, deniable encryption has something to offer.

Implementation

With the seed of an idea firmly planted in my mind, I decided to embark on the journey of creating a proof of concept (PoC) for deniable encryption. The goal was simple: develop a system that allows a user to encrypt data in such a way that they could reveal a decoy message if pressured while keeping their true secrets hidden. Little did I know, this journey would take me deep into the realms of cryptography and data security.

The Initial Challenges

The first challenge was understanding the core principles behind deniable encryption. How could I create a system that effectively hides the true message while presenting a plausible decoy? This required a solid grasp of cryptographic techniques and the ability to think like both an attacker and a defender.

I started by researching existing encryption algorithms and techniques. AES-GCM (Advanced Encryption Standard - Galois/Counter Mode) stood out as a robust option for encryption due to its speed and security features. Additionally, I needed a method to derive cryptographic keys from passwords securely, which led me to PBKDF2 (Password-Based Key Derivation Function 2). This function takes a password and a salt (a random string added for extra security) and stretches it into a more complex, secure key.

Understanding these cryptographic primitives was crucial. AES-GCM provides both encryption and authentication, ensuring that the data is not only confidential but also tamper-proof. PBKDF2, on the other hand, helps to derive strong cryptographic keys from passwords, making brute-force attacks more difficult. These two technologies formed the backbone of my deniable encryption system.

Crafting the Encryption Logic

With the foundational knowledge in place, it was time to start coding. The first step was generating the key: one key that could decrypt either the decoy message or the real message, depending on the password used. This involved using PBKDF2 to derive keys from passwords.

In his article, Ayende had written the code in C#. While his implementation was brilliant, I wanted to make this technology readily available to a broader audience. So, I decided to implement it in JavaScript, ensuring it could run in any modern web browser without the need for additional software installations.

Here’s how I did it:

const SALT_SIZE = 16;
const AES_KEY_SIZE = 256;
const AES_NONCE_SIZE = 12;
const MAX_USER_ITEMS = 2;

async function getPasswordKey(password) {
    const encoder = new TextEncoder();
    return window.crypto.subtle.importKey("raw", encoder.encode(password), { name: "PBKDF2" }, false, ["deriveKey"]);
}

async function deriveKey(keyMaterial, salt) {
    return window.crypto.subtle.deriveKey(
        { name: "PBKDF2", salt: salt, iterations: 1000000, hash: "SHA-256" },
        keyMaterial,
        { name: "AES-GCM", length: AES_KEY_SIZE },
        false,
        ["encrypt", "decrypt"]
    );
}

Next, I needed to encrypt the messages using AES-GCM. This algorithm not only encrypts the data but also provides an integrity check, ensuring that the data has not been tampered with. Both the decoy and real messages would be encrypted into a single cipher that can be decrypted using different keys.

async function encrypt(items) {
    if (Object.keys(items).length > MAX_USER_ITEMS) {
        throw new Error("Too many items");
    }
    const salt = window.crypto.getRandomValues(new Uint8Array(SALT_SIZE));
    let buffer = new Uint8Array([...salt]);

    for (let [password, message] of Object.entries(items)) {
        const keyMaterial = await getPasswordKey(password);
        const key = await deriveKey(keyMaterial, salt);
        const nonce = window.crypto.getRandomValues(new Uint8Array(AES_NONCE_SIZE));
        const encoder = new TextEncoder();
        const encodedMessage = encoder.encode(message);
        const encryptedData = await window.crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, key, encodedMessage);

        let dataToAppend = new Uint8Array(4 + AES_NONCE_SIZE + encryptedData.byteLength);
        new DataView(dataToAppend.buffer).setUint32(0, encryptedData.byteLength, true);
        dataToAppend.set(nonce, 4);
        dataToAppend.set(new Uint8Array(encryptedData), 4 + AES_NONCE_SIZE);

        buffer = concatTypedArrays(buffer, dataToAppend);
    }
    return bufferToHex(buffer);
}

function bufferToHex(buffer) {
    return Array.from(buffer).map((b) => b.toString(16).padStart(2, "0")).join("");
}

function concatTypedArrays(a, b) {
    let c = new Uint8Array(a.length + b.length);
    c.set(a, 0);
    c.set(b, a.length);
    return c;
}

The Decryption Logic

Decrypting the data required the correct password to derive the appropriate key. If the decoy password was used, the decoy message would be revealed. If the real password was used, the real message would be decrypted.

Here’s the code for the decryption logic:

async function decrypt(password, encryptedHex) {
    const encryptedData = hexToBuffer(encryptedHex);
    const salt = encryptedData.slice(0, SALT_SIZE);
    const keyMaterial = await getPasswordKey(password);
    const key = await deriveKey(keyMaterial, salt);
    let offset = SALT_SIZE;

    while (offset < encryptedData.length) {
        if (offset + 4 > encryptedData.length) break;

        const ciphertextLength = new DataView(encryptedData.buffer, encryptedData.byteOffset + offset, 4).getUint32(0, true);
        offset += 4;

        if (offset + AES_NONCE_SIZE + ciphertextLength > encryptedData.length) break;

        const nonce = encryptedData.slice(offset, offset + AES_NONCE_SIZE);
        offset += AES_NONCE_SIZE;
        const ciphertext = encryptedData.slice(offset, offset + ciphertextLength);
        offset += ciphertextLength;

        try {
            const decryptedData = await window.crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce }, key, ciphertext);
            const decoder = new TextDecoder();
            return decoder.decode(decryptedData);
        } catch (e) {
            continue;
        }
    }
    return null;
}

function hexToBuffer(hex) {
    return new Uint8Array(hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
}

This code ensures that the correct message is revealed based on the password provided. If the decoy password is entered, the decoy message is decrypted and displayed. If the real password is entered, the true message is revealed.

Real-World Applications

The potential applications for deniable encryption extend far beyond simple message encryption. Here are a few scenarios where this technology could be invaluable:

  1. Journalism and Activism: Journalists and activists often handle sensitive information that could put them or their sources at risk. Deniable encryption allows them to protect their data even if they are forced to reveal their decryption keys. In countries with oppressive regimes, this can mean the difference between safety and persecution. By using deniable encryption, journalists can protect their sources and activists can safeguard their plans and communications.

  2. Corporate Espionage: In the cutthroat world of corporate espionage, protecting trade secrets and sensitive information is crucial. Deniable encryption can provide an extra layer of security for companies. Imagine a scenario where a competitor attempts to steal your trade secrets. With deniable encryption, you can reveal decoy data that appears valuable but is ultimately useless, protecting your real secrets from falling into the wrong hands.

  3. Personal Privacy: For everyday users, deniable encryption can protect personal data, financial records, and private communications. It’s an essential tool for anyone who values their privacy. In an era where data breaches are common and personal information is a valuable commodity, deniable encryption provides an additional safeguard. Whether you’re protecting your personal journal, sensitive financial information, or private communications, deniable encryption ensures that your data remains secure.

  4. Legal Protection: Lawyers and legal professionals can use deniable encryption to protect privileged communications and sensitive case information, ensuring client confidentiality. In legal disputes, protecting client information is paramount. Deniable encryption ensures that even if a lawyer is compelled to reveal information, the most sensitive data remains protected.

  5. Government and Military: Government agencies and military organizations can use deniable encryption to protect classified information and maintain national security. In the realm of national security, protecting classified information is critical. Deniable encryption provides an additional layer of security, ensuring that even if an agent is forced to reveal a password, the most sensitive information remains hidden.

Overcoming Technical Challenges

Building the PoC for deniable encryption wasn’t without its challenges. One of the key issues was ensuring that the system was both secure and user-friendly. Here are some of the technical hurdles we faced and how we overcame them:

  1. Key Derivation and Management: Deriving keys securely from passwords and managing multiple keys for decoy and real messages required careful implementation. Using PBKDF2 for key derivation ensured that the keys were robust and secure. This process involves using a salt to ensure that even if two users choose the same password, their keys will be different. Additionally, the use of a large number of iterations makes it computationally expensive for attackers to guess the password through brute-force attacks.

  2. Data Integrity and Authentication: Ensuring that the encrypted data had not been tampered with was crucial. AES-GCM provided the necessary integrity checks, ensuring that any tampering would be detected during decryption. AES-GCM combines encryption and integrity protection in one algorithm, ensuring that any modifications to the ciphertext are detected during decryption. This is critical for maintaining the integrity of the encrypted data and ensuring that it has not been altered.

  3. Testing and Validation: Thorough testing was necessary to ensure that the encryption and decryption processes worked correctly and securely. This involved rigorous testing with various input scenarios and edge cases. Testing included verifying that the correct message was revealed based on the password provided, and ensuring that the system behaved correctly when faced with incorrect passwords or tampered data. This testing process was critical for ensuring the robustness and reliability of the system.

Ayende's article explored the possibility of adding up to five extra decoy keys, providing multiple layers of plausible deniability. For this PoC, however, we kept it simple with just one decoy key to focus on demonstrating the core concept. Adding multiple decoy keys increases the complexity and security of the system, but also requires careful management of the keys and encrypted data. For this initial PoC, focusing on a single decoy key allowed us to clearly demonstrate the concept and functionality of deniable encryption.

The Road Ahead

As we wrap up this deep dive into deniable encryption, it's important to note that this PoC is just the beginning. There are numerous potential applications for deniable encryption beyond journalism and activism. Corporate environments, personal privacy tools, and even secure communications apps could benefit from incorporating deniable encryption.

Moving forward, we aim to refine the app, making it even more robust and user-friendly. We plan to add features like multi-layered encryption, support for more encryption algorithms, and perhaps even a mobile app version. Multi-layered encryption would allow users to create multiple layers of deniable encryption, adding additional decoy keys and messages for even greater security. Supporting more encryption algorithms would provide users with additional options and flexibility in securing their data.

We also want to explore integrating deniable encryption with other privacy tools, such as secure messaging apps and encrypted storage solutions. By combining these technologies, we can create comprehensive privacy solutions that offer unparalleled protection for sensitive data. For example, integrating deniable encryption with a secure messaging app would allow users to protect their communications with an additional layer of security. Similarly, integrating with encrypted storage solutions would provide a secure way to store and manage sensitive data.

Final Thoughts

Deniable encryption is a fascinating and powerful tool in the realm of digital security. It offers a unique solution to a critical problem: protecting sensitive information even when you’re forced to reveal a password. This PoC demonstrates that it’s not only feasible but also practical to implement deniable encryption using modern web technologies.

In a world where privacy is constantly under threat, having an extra layer of security can make all the difference. So, whether you’re an investigative journalist, a corporate whistleblower, or just someone who values their privacy, deniable encryption is worth exploring.

Remember, in the world of secrets, trust no one, encrypt everything, and always have a decoy ready.

If you’re curious to see this in action, the app is ready to be tested here: Deniable Encryption App.

For those who want to dive into the code, the implementation in Python, JavaScript, and C can be found here: GitHub Repository.