Cipher

The Fossil IO Cipher module provides a unified, string-identified interface for encoding and decoding text using a curated set of classical and utility ciphers such as Caesar, Vigenère, Base64, ROT13, and Morse. The C API exposes simple, stateless functions that perform cipher lookup via a static registry and return newly allocated results, making the module easy to embed and thread-safe by design. On top of this, the C++ wrapper offers a thin, header-only façade that integrates cleanly with std::string, enabling safer and more idiomatic use in modern C++ while preserving the ABI and behavior of the underlying C implementation.

HEADER REFERENCE #

#ifndef FOSSIL_IO_CIPHER_H
#define FOSSIL_IO_CIPHER_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Cipher Registry and Internal Logic
 *
 * This module provides unified encode/decode APIs for a set of supported text ciphers.
 * Each cipher is identified by a string ID and registered in a static lookup table.
 *
 * Available cipher string IDs:
 *   - "caesar"
 *   - "vigenere"
 *   - "base64"
 *   - "base32"
 *   - "binary"
 *   - "morse"
 *   - "baconian"
 *   - "railfence"
 *   - "haxor"
 *   - "leet"
 *   - "rot13"
 *   - "atbash"
 *
 * Internal logic:
 *   - Ciphers are registered in a static table: static const cipher_entry cipher_table[].
 *   - Lookup is performed by string ID (case-insensitive) using a linear search (O(n) time).
 *   - Each cipher_entry contains the cipher's string ID and a function pointer.
 *   - The encode/decode API calls the cipher function with the input text and mode.
 *   - Cipher functions return a newly allocated string (caller must free).
 *   - If an unknown cipher ID is provided, the API returns NULL.
 *
 * Example usage:
 *   char *encoded = fossil_io_cipher_encode("Hello", "caesar");
 *   char *decoded = fossil_io_cipher_decode(encoded, "caesar");
 *   free(encoded);
 *   free(decoded);
 *
 * Notes:
 *   - All cipher functions are stateless and thread-safe.
 *   - The registry is static and not extensible at runtime.
 *   - The lookup is O(n) (linear in number of ciphers).
 *   - Input validation is performed; NULL is returned for invalid arguments.
 *   - The encode/decode APIs are symmetric for reversible ciphers.
 *   - Some ciphers (e.g., vigenere, railfence) use fixed parameters in this implementation.
 *   - The caller is responsible for freeing returned buffers.
 */

/**
 * Encode text using a named cipher.
 *
 * Internal logic:
 *   - Ciphers are registered in cipher_table[].
 *   - Lookup is performed by string ID (case-insensitive).
 *   - Encode API selects the cipher and calls its function.
 *   - Returns a newly allocated string (caller must free).
 *   - If an unknown cipher ID is provided, returns NULL.
 *
 * Available cipher string IDs:
 *   - "caesar"
 *   - "vigenere"
 *   - "base64"
 *   - "base32"
 *   - "binary"
 *   - "morse"
 *   - "baconian"
 *   - "railfence"
 *   - "haxor"
 *   - "leet"
 *   - "rot13"
 *   - "atbash"
 */
char *fossil_io_cipher_encode(const char *text, const char *cipher_id);

/**
 * Decode text using a named cipher.
 *
 * Internal logic:
 *   - Ciphers are registered in cipher_table[].
 *   - Lookup is performed by string ID (case-insensitive).
 *   - Decode API selects the cipher and calls its function.
 *   - Returns a newly allocated string (caller must free).
 *   - If an unknown cipher ID is provided, returns NULL.
 *
 * Available cipher string IDs:
 *   - "caesar"
 *   - "vigenere"
 *   - "base64"
 *   - "base32"
 *   - "binary"
 *   - "morse"
 *   - "baconian"
 *   - "railfence"
 *   - "haxor"
 *   - "leet"
 *   - "rot13"
 *   - "atbash"
 */
char *fossil_io_cipher_decode(const char *text, const char *cipher_id);

#ifdef __cplusplus
}

#include <string>

namespace fossil {
    namespace io {
    
        /**
         * Cipher
         *
         * Thin C++ wrapper around Fossil IO cipher encode/decode API.
         *
         * This class:
         *  - Owns returned buffers safely
         *  - Does not throw
         *  - Does not allocate unless the C layer does
         *  - Is header-only and ABI-neutral
         */
        class Cipher {
        public:
            /**
             * Encode text using a named cipher.
             *
             * Internal logic:
             *   - Ciphers are registered in cipher_table[].
             *   - Lookup is performed by string ID (case-insensitive).
             *   - The encode API selects the cipher and calls its function.
             *   - Returns a newly allocated string (caller must free).
             *   - If an unknown cipher ID is provided, returns an empty string.
             *
             * Available cipher string IDs:
             *   - "caesar"
             *   - "vigenere"
             *   - "base64"
             *   - "base32"
             *   - "binary"
             *   - "morse"
             *   - "baconian"
             *   - "railfence"
             *   - "haxor"
             *   - "leet"
             *   - "rot13"
             *   - "atbash"
             */
            static std::string encode(const std::string &text,
                                      const std::string &cipher_id) {
                return fossil_io_cipher_encode(text.c_str(), cipher_id.c_str());
            }

            /**
             * Decode text using a named cipher.
             *
             * Internal logic:
             *   - Ciphers are registered in cipher_table[].
             *   - Lookup is performed by string ID (case-insensitive).
             *   - The decode API selects the cipher and calls its function.
             *   - Returns a newly allocated string (caller must free).
             *   - If an unknown cipher ID is provided, returns an empty string.
             *
             * Available cipher string IDs:
             *   - "caesar"
             *   - "vigenere"
             *   - "base64"
             *   - "base32"
             *   - "binary"
             *   - "morse"
             *   - "baconian"
             *   - "railfence"
             *   - "haxor"
             *   - "leet"
             *   - "rot13"
             *   - "atbash"
             */
            static std::string decode(const std::string &text,
                                      const std::string &cipher_id) {
                return fossil_io_cipher_decode(text.c_str(), cipher_id.c_str());
            }
        
        };
    
    } // namespace io
} // namespace fossil

#endif

#endif /* FOSSIL_IO_FRAMEWORK_H */

SAMPLE CODE C #

#include "fossil/io/cipher.h"
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    const char *text = "Hello, World!";

    /* Encode using a Caesar cipher */
    char *encoded = fossil_io_cipher_encode(text, "caesar");
    if (!encoded) {
        fprintf(stderr, "Encoding failed\n");
        return 1;
    }

    printf("Encoded: %s\n", encoded);

    /* Decode back to original */
    char *decoded = fossil_io_cipher_decode(encoded, "caesar");
    if (!decoded) {
        fprintf(stderr, "Decoding failed\n");
        free(encoded);
        return 1;
    }

    printf("Decoded: %s\n", decoded);

    /* Caller owns the returned buffers */
    free(encoded);
    free(decoded);

    return 0;
}

SAMPLE CODE C++ #

#include "fossil/io/cipher.h"
#include <iostream>

using fossil::io::Cipher;

int main() {
    std::string text = "Attack at dawn";

    /* Encode using ROT13 */
    std::string encoded = Cipher::encode(text, "rot13");
    if (encoded.empty()) {
        std::cerr << "Encoding failed\n";
        return 1;
    }

    std::cout << "Encoded: " << encoded << '\n';

    /* Decode back */
    std::string decoded = Cipher::decode(encoded, "rot13");
    if (decoded.empty()) {
        std::cerr << "Decoding failed\n";
        return 1;
    }

    std::cout << "Decoded: " << decoded << '\n';

    return 0;
}

What are your feelings

Updated on February 6, 2026