OTP Cipher - One Time Pad Implementation

Introduction

A secure one-time pad (OTP) cipher implementation in C with automatic versioning system.

Why One-Time Pads

Nostr and much of the web runs on public key cryptography. Public key cryptography is great, but it is vulnerable. Cryptographers know this, and they know what it takes to attack it, so what they do is just make the keys large enough such that the system is resistant to attack given computers as they are today.

There is one type of cryptography, however, that is invulnerable to any type of attack in our universe, and that is known as a one-time pad.

One-time pads rely directly on the laws of physics and what it means for a number to be truly random.

If you take your secret message and mix it with truly random numbers, and don't use those random numbers again, then that message is unbreakable by any computer, no matter how powerful, quantum or not, forever.

In fact, one-time pads are so powerful that if you have data encrypted by a one-time pad located in a distant galaxy, and that data is not kept anywhere else, then by destroying the pad used for encryption in your galaxy, the data is wiped from the universe and can never be recovered.

Advantages and Limitations

Limitations

  1. The pad must be shared between the parties wanting to use it.
  2. The pad must be as long or longer than what you want to encrypt, and it can't be used a second time.

Modern Advantages

While in the past, pad length might have been a problem, readily available USB drives in the terabytes make size less of a problem for many uses.

We are also becoming very accustomed to YubiKey authenticators in the USB ports of our computers. A small USB drive in our devices can now easily contain a key of greater length than all the text messages we would expect to send over a lifetime.

Multi-Device Coordination

One of the problems to address is the fact that to use an OTP across several devices means that they have to coordinate to know when they are encrypting new plaintext and where to start in the key. Reusing the same section of the pad, while not necessarily fatal, degrades the encryption from its status as "Information Theoretically Secure".

To address this problem, we can use Nostr to share among devices the place in the pad that was last left off.

Additional Benefits

One-time pads can be trivially encrypted and decrypted using pencil and paper, making them accessible even without electronic devices.

Features

  • Perfect Security: Implements true one-time pad encryption with information-theoretic security
  • Text & File Encryption: Supports both inline text and file encryption
  • Multiple Output Formats: Binary (.otp) and ASCII armored (.otp.asc) file formats
  • Keyboard Entropy: Optional keyboard entropy collection for enhanced randomness
  • Short Command Flags: Convenient single-character flags for all operations
  • Automatic Versioning: Built-in semantic versioning with automatic patch increment
  • Multiple Build Options: Standard and static linking builds
  • Cross-Platform: Works on Linux and other UNIX-like systems

Version Information

This project uses an automatic versioning system that:

  • Automatically increments the patch version on each build
  • Embeds build timestamp, git commit hash, and branch information
  • Creates git tags for version tracking
  • Generates version header files with detailed build metadata

Current version can be viewed with: ./otp --help or by running the interactive mode.

Building

Prerequisites

  • GCC compiler
  • Git (for version tracking)
  • Make

Note: OpenSSL is no longer required! This implementation is now completely self-contained.

Build Commands

Use the included build script for automatic versioning:

# Standard build (default)
./build.sh build

# Static linking build
./build.sh static

# Clean build artifacts
./build.sh clean

# Generate version files only
./build.sh version

# Install to system
./build.sh install

# Remove from system
./build.sh uninstall

# Show usage
./build.sh help

Traditional Make

You can also use make directly (without automatic versioning):

make            # Standard build
make static     # Static linking
make clean      # Clean artifacts
make install    # Install to /usr/local/bin/
make uninstall  # Remove from system

Usage

Interactive Mode

./otp

Command Line Mode

# Generate a new pad
./otp generate 1GB

# Encrypt text (interactive input)
./otp encrypt <pad_hash_or_prefix>

# Decrypt message (interactive input)  
./otp decrypt <pad_hash_or_prefix>

# List available pads
./otp list

Version System Details

Automatic Version Increment

Every build automatically increments the patch version:

  • v0.1.0 → v0.1.1 → v0.1.2, etc.
  • Creates git tags for each version
  • Embeds detailed build information

Manual Version Control

For major/minor releases, create tags manually:

# Feature release (minor bump)
git tag v0.2.0    # Next build: v0.2.1

# Breaking change (major bump)  
git tag v1.0.0    # Next build: v1.0.1

Version Information Available

  • Version number (major.minor.patch)
  • Git commit hash and branch
  • Build date and time
  • Full version display with metadata

Generated Files

The build system automatically generates:

  • src/version.h - Version constants and macros
  • src/version.c - Version API functions
  • VERSION - Plain text version number

These files are excluded from git (.gitignore) and regenerated on each build.

Security Features

  • Uses /dev/urandom for cryptographically secure random number generation
  • Optional keyboard entropy mixing using simple XOR operations
  • Custom 256-bit XOR checksum for pad identification (encrypted with pad data)
  • Read-only pad files to prevent accidental modification
  • State tracking to prevent pad reuse
  • Zero external crypto dependencies - completely self-contained implementation

File Structure

otp/
├── build.sh          # Build script with automatic versioning
├── Makefile         # Traditional make build system  
├── otp.c            # Main source code
├── README.md        # This file
├── .gitignore       # Git ignore rules
├── src/             # Generated version files (auto-created)
│   ├── version.h    # Version header (generated)
│   └── version.c    # Version implementation (generated)
├── pads/            # OTP pad storage directory (created at runtime)
└── VERSION          # Plain text version (generated)

File Formats

.otp File Format (Binary)

Binary encrypted files use a structured header format:

Offset | Size | Field               | Description
-------|------|-------------------|----------------------------------
0      | 4    | Magic             | "OTP\0" - File type identifier
4      | 2    | Version           | Format version (currently 1)
6      | 32   | Pad Checksum      | Binary pad checksum (32 bytes)
38     | 8    | Pad Offset        | Offset in pad file (uint64_t)
46     | 4    | File Mode         | Original file permissions (uint32_t)
50     | 8    | File Size         | Original file size (uint64_t)
58     | var  | Encrypted Data    | XOR-encrypted file contents

.otp.asc File Format (ASCII Armored)

ASCII armored files use the same format as encrypted text messages:

-----BEGIN OTP MESSAGE-----
Version: v0.2.15
Pad-ChkSum: <64-character-hex-checksum>
Pad-Offset: <decimal-offset-value>

<base64-encoded-encrypted-data>
-----END OTP MESSAGE-----

Note: ASCII armored files do not preserve original file permissions metadata.

Usage Examples

Short Command Flags

# Quick commands using short flags
./otp -g 1GB                    # Generate 1GB pad
./otp -l                        # List available pads
./otp -e 1a2b "Hello world"     # Encrypt text inline
./otp -d "-----BEGIN OTP..."    # Decrypt message inline

# File operations
./otp -f document.pdf 1a2b                # Encrypt file (binary)
./otp -f document.pdf 1a2b -a             # Encrypt file (ASCII)
./otp -f document.pdf 1a2b -o secret.otp  # Custom output name

Text Encryption

# Interactive text encryption
./otp encrypt 1a2b3c
Enter text to encrypt: This is my secret message
# Outputs ASCII armored message

# Inline text encryption
./otp -e 1a2b3c "This is my secret message"
# Outputs ASCII armored message immediately

File Encryption

# Binary format (preserves metadata)
./otp -f sensitive.doc a1b2c3

# ASCII armored format (text-safe)
./otp -f sensitive.doc a1b2c3 -a

# Custom output filename
./otp -f sensitive.doc a1b2c3 -o encrypted_document.otp

Decryption

# Auto-detect format and pad from message/file
./otp -d encrypted.otp.asc
./otp -d "-----BEGIN OTP MESSAGE-----..."

# Interactive mode
./otp decrypt
# Prompts for encrypted message input

Build and Version Tracking

$ ./build.sh build
[INFO] Incrementing version...
[INFO] Current version: v0.2.14
[INFO] New version: v0.2.15
[SUCCESS] Created new version tag: v0.2.15
[SUCCESS] Build completed successfully

$ ./otp --help
OTP Cipher - One Time Pad Implementation v0.2.15
Built on 2025-08-10 at 14:07:58 from commit ae0afcf on branch master

Advanced Features

# Generate pad with keyboard entropy
./otp generate 5GB
# Follow prompts for keyboard entropy collection

# Check pad usage
./otp -l
Available pads:
No.  ChkSum (first 16 chars) Size         Used         % Used
---  -------------------   ----------   ----------   ------
1    97d9d82b5414a943      1.00GB       156B         0.0%
2    0c8e19fde996e683      1000B        248B         24.8%

# Show detailed pad information
./otp
# Select "S" for show pad info, enter checksum or prefix

License

This project includes automatic versioning system based on the Generic Automatic Version Increment System.

Contributing

When contributing:

  1. The version will automatically increment on builds
  2. For major features, consider manually creating minor version tags
  3. Generated version files (src/version.*, VERSION) should not be committed
Description
C implementation of One Time Pad encryption and decryption.
Readme 3.6 MiB
v0.3.33 Latest
2025-12-18 14:20:36 +00:00
Languages
C 88.6%
Shell 11.2%
Makefile 0.2%