Compare commits

...

35 Commits

Author SHA1 Message Date
8616e78547 Version v0.3.4 - Checking build.sh 2025-09-01 15:25:06 -04:00
8327ee125b Version v0.3.3 - testing build.sh 2025-09-01 15:20:30 -04:00
5dadd948e6 Version v0.3.2 - Testing build script 2025-09-01 15:11:17 -04:00
02044f1054 Cleanup 2025-09-01 13:54:08 -04:00
194bd5fea5 Version v0.2.110 - Clean up functionality 2025-09-01 10:14:57 -04:00
eb126bb663 Version v0.2.109 - Simplify command line mode 2025-09-01 07:11:51 -04:00
a4a4c0d8b2 Version v0.2.108 - Fixed piping issues 2025-08-31 16:43:04 -04:00
0c4ef55a98 Version v0.2.107 - Update comments 2025-08-31 11:25:03 -04:00
4a651da067 Version v0.2.106 - Test version string replacement 2025-08-31 11:03:08 -04:00
7b5db60d80 Version v0.2.105 - Test version string replacement 2025-08-31 11:03:02 -04:00
84e2ee5639 Version v0.2.104 - Cleaned up build.sh 2025-08-31 10:43:36 -04:00
0f3af174b0 Clean up 2025-08-31 09:46:56 -04:00
3f0a258c21 Version v0.2.103 - Various 2025-08-30 18:56:11 -04:00
2a5aec7dce Version v0.2.102 - Add entropy 2025-08-29 09:10:39 -04:00
6c796df30a Version v0.2.101 - Update entropy addition 2025-08-29 08:45:08 -04:00
09ea57f146 Version v0.2.100 - Correct bug 2025-08-27 09:15:30 -04:00
0ae2423f19 Version v0.2.99 - Correct bug 2025-08-27 09:12:58 -04:00
3859e6492a Version v0.2.98 - Silent mode 2025-08-27 09:03:22 -04:00
0978d0323a Version v0.2.96 - Refactor code 2025-08-27 09:00:44 -04:00
0ea8b2dd32 Version v0.2.95 - Refactor code 2025-08-27 08:56:39 -04:00
12f92d2c96 Version v0.2.94 - Refactor code 2025-08-27 08:44:11 -04:00
aea69148a8 Version v0.2.93 - Clean warnings 2025-08-27 08:23:31 -04:00
d537bc4948 Version v0.2.92 - Menu changes 2025-08-27 08:11:26 -04:00
42a8f5c358 Version v0.2.91 - Menu changes 2025-08-27 08:06:35 -04:00
7a30949ddd Version v0.2.89 - Add default pad support for -e option 2025-08-27 07:57:42 -04:00
eb8a5b6565 Version v0.2.87 - Fix default pad preferences to store full file paths instead of relative paths 2025-08-27 07:53:15 -04:00
d0a5628072 Version v0.2.86 - config 2025-08-26 16:29:25 -04:00
5498a2321e Version v0.2.85 - readme.md 2025-08-26 15:54:25 -04:00
fe2eb40ead Readme 2025-08-26 15:52:05 -04:00
0db1988d8f todo 2025-08-21 12:24:39 -04:00
97530c8eb3 Version v0.2.83 - Fixed all remaining buffer size warnings - eliminated all compile warnings 2025-08-14 12:38:02 -04:00
a85c4ed55b Version v0.2.82 - Fixed final buffer size warning in /run/media path handling 2025-08-14 12:37:28 -04:00
a9974c7e87 Version v0.2.81 - Fixed remaining buffer size warnings - increased all preferences buffer sizes to 2048 2025-08-14 12:36:56 -04:00
592d54728b Version v0.2.80 - Fixed compile warnings - increased buffer sizes and added length validation 2025-08-14 12:36:06 -04:00
21b3c4de52 Version v0.2.79 - Fixed decrypt output - added newline and flush to ensure proper output 2025-08-14 12:29:23 -04:00
23 changed files with 2737 additions and 1797 deletions

View File

@@ -1,7 +1,29 @@
When building, use build.sh, not make.
Use it as follows: build.sh -m "useful comment on changes being made"
When making TUI menus, try to use the first leter of the command and the key to press to execute that command. For example, if the command is "Open file" try to use a keypress of "o" upper or lower case to signal to open the file. Use this instead of number keyed menus when possible. In the command, the letter should be underlined that signifies the command.
## Buffer Size Guidelines
### Path Handling
- Always use buffers of size 1024 or PATH_MAX (4096) for file paths
- When concatenating paths with snprintf, ensure buffer is at least 2x the expected maximum input
- Use safer path construction patterns that check lengths before concatenation
### String Formatting Safety
- Before using snprintf with dynamic strings, validate that buffer size >= sum of all input string lengths + format characters + 1
- Use strnlen() to check actual string lengths before formatting
- Consider using asprintf() for dynamic allocation when exact size is unknown
- Add length validation before snprintf calls
### Compiler Warning Prevention
- Always size string buffers generously (minimum 1024 for paths, 512 for general strings)
- Use buffer size calculations: `size >= strlen(str1) + strlen(str2) + format_overhead + 1`
- Add runtime length checks before snprintf operations
- Consider using safer alternatives like strlcpy/strlcat if available
### Code Patterns to Avoid
- Fixed-size buffers (512 bytes) for path operations where inputs could be 255+ bytes each
- Concatenating unchecked strings with snprintf
- Assuming maximum path component sizes without validation

7
.gitignore vendored
View File

@@ -1,9 +1,8 @@
otp
pads/
files/
Gemini.md
TropicOfCancer-HenryMiller.txt
.gitea_token
# Auto-generated version files
src/version.h
src/version.c
VERSION
# Auto-generated files (none currently)

View File

@@ -1,361 +0,0 @@
# Generic Automatic Version Increment System for Any Repository
Here's a generalized implementation guide for adding automatic versioning to any project:
## Core Concept
**Automatic patch version increment with each build** - Every build automatically increments the patch version: v0.1.0 → v0.1.1 → v0.1.2, etc.
## Implementation Steps
### 1. Add Version Increment Function to Build Script
Add this function to your build script (bash example):
```bash
# Function to automatically increment version
increment_version() {
echo "[INFO] Incrementing version..."
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "[WARNING] Not in a git repository - skipping version increment"
return 0
fi
# Get the highest version tag (not chronologically latest)
LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -n 1 || echo "v0.1.0")
if [[ -z "$LATEST_TAG" ]]; then
LATEST_TAG="v0.1.0"
fi
# Extract version components (remove 'v' prefix)
VERSION=${LATEST_TAG#v}
# Parse major.minor.patch using regex
if [[ $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
else
echo "[ERROR] Invalid version format in tag: $LATEST_TAG"
echo "[ERROR] Expected format: v0.1.0"
return 1
fi
# Increment patch version
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="v${MAJOR}.${MINOR}.${NEW_PATCH}"
echo "[INFO] Current version: $LATEST_TAG"
echo "[INFO] New version: $NEW_VERSION"
# Create new git tag
if git tag "$NEW_VERSION" 2>/dev/null; then
echo "[SUCCESS] Created new version tag: $NEW_VERSION"
else
echo "[WARNING] Tag $NEW_VERSION already exists - using existing version"
NEW_VERSION=$LATEST_TAG
fi
# Update VERSION file for compatibility
echo "${NEW_VERSION#v}" > VERSION
echo "[SUCCESS] Updated VERSION file to ${NEW_VERSION#v}"
}
```
### 2. Generate Version Header Files (For C/C++ Projects)
Add this to the increment_version function:
```bash
# Generate version.h header file (adjust path as needed)
cat > src/version.h << EOF
/*
* Auto-Generated Version Header
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
*/
#ifndef VERSION_H
#define VERSION_H
#define VERSION_MAJOR ${MAJOR}
#define VERSION_MINOR ${MINOR}
#define VERSION_PATCH ${NEW_PATCH}
#define VERSION_STRING "${MAJOR}.${MINOR}.${NEW_PATCH}"
#define VERSION_TAG "${NEW_VERSION}"
/* Build information */
#define BUILD_DATE "$(date +%Y-%m-%d)"
#define BUILD_TIME "$(date +%H:%M:%S)"
#define BUILD_TIMESTAMP "$(date '+%Y-%m-%d %H:%M:%S')"
/* Git information */
#define GIT_HASH "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
#define GIT_BRANCH "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
/* Display versions */
#define VERSION_DISPLAY "${NEW_VERSION}"
#define VERSION_FULL_DISPLAY "${NEW_VERSION} ($(date '+%Y-%m-%d %H:%M:%S'), $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown'))"
/* Version API functions */
const char* get_version(void);
const char* get_version_full(void);
const char* get_build_info(void);
#endif /* VERSION_H */
EOF
# Generate version.c implementation file
cat > src/version.c << EOF
/*
* Auto-Generated Version Implementation
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
*/
#include "version.h"
const char* get_version(void) {
return VERSION_TAG;
}
const char* get_version_full(void) {
return VERSION_FULL_DISPLAY;
}
const char* get_build_info(void) {
return "Built on " BUILD_DATE " at " BUILD_TIME " from commit " GIT_HASH " on branch " GIT_BRANCH;
}
EOF
```
### 3. Generate Version File for Other Languages
**Python (`src/__version__.py`):**
```bash
cat > src/__version__.py << EOF
"""Auto-generated version file"""
__version__ = "${MAJOR}.${MINOR}.${NEW_PATCH}"
__version_tag__ = "${NEW_VERSION}"
__build_date__ = "$(date +%Y-%m-%d)"
__build_time__ = "$(date +%H:%M:%S)"
__git_hash__ = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
__git_branch__ = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
EOF
```
**JavaScript/Node.js (update `package.json`):**
```bash
# Update package.json version field
if [ -f package.json ]; then
sed -i "s/\"version\": \".*\"/\"version\": \"${MAJOR}.${MINOR}.${NEW_PATCH}\"/" package.json
fi
```
**Rust (update `Cargo.toml`):**
```bash
if [ -f Cargo.toml ]; then
sed -i "s/^version = \".*\"/version = \"${MAJOR}.${MINOR}.${NEW_PATCH}\"/" Cargo.toml
fi
```
**Go (generate `version.go`):**
```bash
cat > version.go << EOF
// Auto-generated version file
package main
const (
VersionMajor = ${MAJOR}
VersionMinor = ${MINOR}
VersionPatch = ${NEW_PATCH}
VersionString = "${MAJOR}.${MINOR}.${NEW_PATCH}"
VersionTag = "${NEW_VERSION}"
BuildDate = "$(date +%Y-%m-%d)"
BuildTime = "$(date +%H:%M:%S)"
GitHash = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
GitBranch = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
)
EOF
```
**Java (generate `Version.java`):**
```bash
cat > src/main/java/Version.java << EOF
// Auto-generated version class
public class Version {
public static final int VERSION_MAJOR = ${MAJOR};
public static final int VERSION_MINOR = ${MINOR};
public static final int VERSION_PATCH = ${NEW_PATCH};
public static final String VERSION_STRING = "${MAJOR}.${MINOR}.${NEW_PATCH}";
public static final String VERSION_TAG = "${NEW_VERSION}";
public static final String BUILD_DATE = "$(date +%Y-%m-%d)";
public static final String BUILD_TIME = "$(date +%H:%M:%S)";
public static final String GIT_HASH = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')";
public static final String GIT_BRANCH = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')";
}
EOF
```
### 4. Integrate into Build Targets
Call `increment_version` before your main build commands:
```bash
build_library() {
increment_version
echo "[INFO] Building library..."
# Your actual build commands here
make clean && make
}
build_release() {
increment_version
echo "[INFO] Building release..."
# Your release build commands
}
build_package() {
increment_version
echo "[INFO] Building package..."
# Your packaging commands
}
```
### 5. Update .gitignore
Add generated version files to `.gitignore`:
```gitignore
# Auto-generated version files
src/version.h
src/version.c
src/__version__.py
version.go
src/main/java/Version.java
VERSION
```
### 6. Update Build System Files
**For Makefile projects:**
```makefile
# Add version.c to your source files
SOURCES = main.c utils.c version.c
```
**For CMake projects:**
```cmake
# Add version files to your target
target_sources(your_target PRIVATE src/version.c)
```
**For Node.js projects:**
```json
{
"scripts": {
"build": "node build.js && increment_version",
"version": "node -e \"console.log(require('./package.json').version)\""
}
}
```
### 7. Create Initial Version Tag
```bash
# Start with initial version
git tag v0.1.0
```
## Usage Pattern
```bash
./build.sh # v0.1.0 → v0.1.1
./build.sh release # v0.1.1 → v0.1.2
./build.sh package # v0.1.2 → v0.1.3
```
## Manual Version Control
### Major/Minor Version Bumps
```bash
# For feature releases (minor bump)
git tag v0.2.0 # Next build: v0.2.1
# For breaking changes (major bump)
git tag v1.0.0 # Next build: v1.0.1
```
### Version Reset
```bash
# Delete incorrect tags (if needed)
git tag -d v0.2.1
git push origin --delete v0.2.1 # If pushed to remote
# Create correct base version
git tag v0.2.0
# Next build will create v0.2.1
```
## Example Build Script Template
```bash
#!/bin/bash
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_status() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Insert increment_version function here
case "${1:-build}" in
build)
increment_version
print_status "Building project..."
# Your build commands
;;
clean)
print_status "Cleaning build artifacts..."
# Your clean commands
;;
test)
print_status "Running tests..."
# Your test commands (no version increment)
;;
release)
increment_version
print_status "Building release..."
# Your release commands
;;
*)
echo "Usage: $0 {build|clean|test|release}"
exit 1
;;
esac
```
## Benefits
1. **Zero maintenance** - No manual version editing
2. **Build traceability** - Every build has unique version + metadata
3. **Git integration** - Automatic version tags
4. **Language agnostic** - Adapt generation for any language
5. **CI/CD friendly** - Works in automated environments
6. **Rollback friendly** - Easy to revert to previous versions
## Troubleshooting
### Version Not Incrementing
- Ensure you're in a git repository
- Check that git tags exist: `git tag --list`
- Verify tag format matches `v*.*.*` pattern
### Tag Already Exists
If a tag already exists, the build continues with existing version:
```
[WARNING] Tag v0.2.1 already exists - using existing version
```
### Missing Git Information
If git is unavailable, version files show "unknown" for git hash and branch.

View File

@@ -1,22 +1,21 @@
CC = gcc
CFLAGS = -Wall -Wextra -std=c99
LIBS =
LIBS_STATIC = -static
LIBS = -lm
LIBS_STATIC = -static -lm
TARGET = otp
SOURCE = otp.c
VERSION_SOURCE = src/version.c
CHACHA20_SOURCE = nostr_chacha20.c
# Default build target
$(TARGET): $(SOURCE)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(VERSION_SOURCE) $(LIBS)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(CHACHA20_SOURCE) $(LIBS)
# Static linking target
static: $(SOURCE)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(VERSION_SOURCE) $(LIBS_STATIC)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(CHACHA20_SOURCE) $(LIBS_STATIC)
clean:
rm -f $(TARGET) *.pad *.state
rm -f src/version.h src/version.c VERSION
install:
sudo cp $(TARGET) /usr/local/bin/

View File

@@ -1,6 +1,47 @@
# OTP Cipher - One Time Pad Implementation
A secure one-time pad (OTP) cipher implementation in C with automatic versioning system.
## Introduction
A secure one-time pad (OTP) cipher implementation in C.
## 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
@@ -13,15 +54,6 @@ A secure one-time pad (OTP) cipher implementation in C with automatic versioning
- **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
@@ -31,7 +63,7 @@ Current version can be viewed with: `./otp --help` or by running the interactive
- Git (for version tracking)
- Make
**Note: OpenSSL is no longer required! This implementation is now completely self-contained.**
### Build Commands
@@ -119,10 +151,7 @@ git tag v1.0.0 # Next build: v1.0.1
- 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
The build system automatically manages Git versioning by incrementing tags.
These files are excluded from git (.gitignore) and regenerated on each build.
@@ -144,9 +173,6 @@ otp/
├── 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)
```

3
TODO.md Normal file
View File

@@ -0,0 +1,3 @@
# TODO
## The pad menu in interactive encrypt mode gives numbers instead of checksum selection

265
build.sh
View File

@@ -100,13 +100,13 @@ increment_version() {
print_success "Created new version tag: $NEW_VERSION"
# Push changes and tags to remote repository
if git push ssh://ubuntu@laantungir.net:/home/ubuntu/git_repos/otp 2>/dev/null; then
if git push 2>/dev/null; then
print_success "Pushed changes to remote repository"
else
print_warning "Failed to push changes to remote repository"
fi
if git push ssh://ubuntu@laantungir.net:/home/ubuntu/git_repos/otp --tags 2>/dev/null; then
if git push --tags 2>/dev/null; then
print_success "Pushed tags to remote repository"
else
print_warning "Failed to push tags to remote repository"
@@ -123,106 +123,180 @@ increment_version() {
fi
fi
# Update VERSION file for compatibility
echo "${NEW_VERSION#v}" > VERSION
print_success "Updated VERSION file to ${NEW_VERSION#v}"
# Update version strings in source code
update_source_version "$NEW_VERSION"
# Generate version.h header file
mkdir -p src
cat > src/version.h << EOF
/*
* Auto-Generated Version Header
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
*/
#ifndef VERSION_H
#define VERSION_H
#define VERSION_MAJOR ${MAJOR}
#define VERSION_MINOR ${MINOR}
#define VERSION_PATCH ${NEW_PATCH}
#define VERSION_STRING "${MAJOR}.${MINOR}.${NEW_PATCH}"
#define VERSION_TAG "${NEW_VERSION}"
/* Build information */
#define BUILD_DATE "$(date +%Y-%m-%d)"
#define BUILD_TIME "$(date +%H:%M:%S)"
#define BUILD_TIMESTAMP "$(date '+%Y-%m-%d %H:%M:%S')"
/* Git information */
#define GIT_HASH "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
#define GIT_BRANCH "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
/* Display versions */
#define VERSION_DISPLAY "${NEW_VERSION}"
#define VERSION_FULL_DISPLAY "${NEW_VERSION} ($(date '+%Y-%m-%d %H:%M:%S'), $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown'))"
/* Version API functions */
const char* get_version(void);
const char* get_version_full(void);
const char* get_build_info(void);
#endif /* VERSION_H */
EOF
# Generate version.c implementation file
cat > src/version.c << EOF
/*
* Auto-Generated Version Implementation
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
*/
#include "version.h"
const char* get_version(void) {
return VERSION_TAG;
print_success "Version updated to ${NEW_VERSION}"
}
const char* get_version_full(void) {
return VERSION_FULL_DISPLAY;
# Function to update version strings in source code
update_source_version() {
local NEW_VERSION="$1"
print_status "Updating version strings in source code..."
# Replace hardcoded version strings in otp.c with the current git tag
if [ -f "otp.c" ]; then
# Update main menu version
sed -i "s/OTP v[0-9]\+\.[0-9]\+\.[0-9]\+/OTP $NEW_VERSION/g" otp.c
# Update ASCII output version
sed -i "s/Version: v[0-9]\+\.[0-9]\+\.[0-9]\+/Version: $NEW_VERSION/g" otp.c
# Update usage/help text version
sed -i "s/Implementation v[0-9]\+\.[0-9]\+\.[0-9]\+/Implementation $NEW_VERSION/g" otp.c
print_success "Updated version strings in otp.c to $NEW_VERSION"
else
print_warning "otp.c not found - skipping version string updates"
fi
}
const char* get_build_info(void) {
return "Built on " BUILD_DATE " at " BUILD_TIME " from commit " GIT_HASH " on branch " GIT_BRANCH;
}
EOF
print_success "Generated version header files"
# Cross-platform build functions
check_cross_compiler() {
if ! command -v aarch64-linux-gnu-gcc > /dev/null 2>&1; then
print_error "ARM64/AArch64 cross-compiler not found!"
print_error "Install with: sudo apt install gcc-aarch64-linux-gnu"
print_error "Or on other distros: gcc-cross-aarch64"
return 1
fi
return 0
}
upload_release_asset() {
local api_url="$1"
local token="$2"
local version="$3"
local filename="$4"
if [ ! -f "$filename" ]; then
print_warning "Binary $filename not found, skipping upload"
return 1
fi
print_status "Uploading $filename to release..."
# Get release ID first
local release_id=$(curl -s -H "Authorization: token $token" \
"$api_url/releases/tags/$version" | \
grep -o '"id":[0-9]*' | head -n1 | cut -d: -f2)
if [ -z "$release_id" ]; then
print_error "Could not get release ID for $version"
return 1
fi
# Upload the asset
curl -X POST "$api_url/releases/$release_id/assets" \
-H "Authorization: token $token" \
-H "Content-Type: application/octet-stream" \
-T "$filename" \
--data-binary "@$filename" \
-G -d "name=$filename"
if [ $? -eq 0 ]; then
print_success "Uploaded $filename successfully"
else
print_warning "Failed to upload $filename"
return 1
fi
}
create_gitea_release() {
local version="$1"
# Read token from ~/.gitea_token
if [ ! -f "$HOME/.gitea_token" ]; then
print_error "No ~/.gitea_token found. Cannot create release."
print_error "Create ~/.gitea_token with your Gitea access token"
return 1
fi
local token=$(cat "$HOME/.gitea_token" | tr -d '\n\r')
local api_url="https://git.laantungir.net/api/v1/repos/laantungir/otp"
print_status "Creating Gitea release for $version..."
# Create release
local response=$(curl -s -X POST "$api_url/releases" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" \
-d "{\"tag_name\": \"$version\", \"name\": \"$version\", \"body\": \"Automated release for $version\"}")
if echo "$response" | grep -q '"id"'; then
print_success "Created release $version"
# Upload binaries
upload_release_asset "$api_url" "$token" "$version" "otp-x86_64"
upload_release_asset "$api_url" "$token" "$version" "otp-arm64"
else
print_warning "Release may already exist or creation failed"
print_status "Response: $response"
# Try to upload to existing release anyway
upload_release_asset "$api_url" "$token" "$version" "otp-x86_64"
upload_release_asset "$api_url" "$token" "$version" "otp-arm64"
fi
}
# Build functions
build_project() {
print_status "Cleaning previous build..."
make clean
increment_version
print_status "Building OTP project..."
make
if [ $? -eq 0 ]; then
print_success "Build completed successfully"
else
print_error "Build failed"
return 1
fi
}
build_static() {
print_status "Cleaning previous build..."
make clean
increment_version
print_status "Building OTP project with static linking..."
make static
# Check for cross-compiler
if ! check_cross_compiler; then
print_warning "ARM64/AArch64 cross-compiler not available, building x86_64 only"
# Build x86_64 only
print_status "Building OTP project for x86_64..."
make CC=gcc
if [ $? -eq 0 ]; then
print_success "Static build completed successfully"
mv otp otp-x86_64
print_success "x86_64 build completed successfully"
else
print_error "Static build failed"
print_error "x86_64 build failed"
return 1
fi
else
# Build both architectures
print_status "Building OTP project for x86_64..."
make clean
make CC=gcc
if [ $? -eq 0 ]; then
mv otp otp-x86_64
print_success "x86_64 build completed successfully"
else
print_error "x86_64 build failed"
return 1
fi
print_status "Building OTP project for ARM64/AArch64..."
make clean
make CC=aarch64-linux-gnu-gcc
if [ $? -eq 0 ]; then
mv otp otp-arm64
print_success "ARM64/AArch64 build completed successfully"
else
print_error "ARM64/AArch64 build failed"
return 1
fi
fi
# Create Gitea release with binaries
if [ -f "$HOME/.gitea_token" ]; then
create_gitea_release "$NEW_VERSION"
else
print_warning "No ~/.gitea_token found. Skipping release creation."
print_warning "Create ~/.gitea_token with your Gitea access token to enable releases."
fi
print_success "Build completed successfully"
}
clean_project() {
print_status "Cleaning build artifacts..."
make clean
rm -f VERSION src/version.h src/version.c
# Remove cross-compiled binaries
rm -f otp-x86_64 otp-arm64
print_success "Clean completed"
}
@@ -253,9 +327,6 @@ case "${1:-build}" in
build)
build_project
;;
static)
build_static
;;
clean)
clean_project
;;
@@ -265,29 +336,31 @@ case "${1:-build}" in
uninstall)
uninstall_project
;;
version)
increment_version
print_status "Version information generated"
;;
*)
echo "OTP Cipher Build Script"
echo "Usage: $0 [-m \"commit message\"] {build|static|clean|install|uninstall|version}"
echo "Usage: $0 [-m \"commit message\"] {build|clean|install|uninstall}"
echo ""
echo "Options:"
echo " -m, --message \"text\" - Specify commit message (skips interactive prompt)"
echo ""
echo "Commands:"
echo " build - Build project with automatic version increment (default)"
echo " static - Build with static linking"
echo " clean - Clean build artifacts and generated files"
echo " build - Cross-compile for x86_64 and ARM64/AArch64 with automatic version increment (default)"
echo " clean - Clean build artifacts and cross-compiled binaries"
echo " install - Install to system (requires build first)"
echo " uninstall - Remove from system"
echo " version - Generate version files only"
echo ""
echo "Build Output:"
echo " otp-x86_64 - Native x86_64 binary"
echo " otp-arm64 - ARM64/AArch64 binary for Raspberry Pi (if cross-compiler available)"
echo ""
echo "Gitea Integration:"
echo " - Automatically creates releases with binaries if ~/.gitea_token exists"
echo " - Requires: ARM64 cross-compiler (gcc-aarch64-linux-gnu)"
echo ""
echo "Examples:"
echo " $0 build"
echo " $0 -m \"Fixed checksum parsing bug\" build"
echo " $0 --message \"Added new feature\" static"
echo " $0"
echo " $0 -m \"Fixed checksum parsing bug\""
echo " $0 --message \"Added new feature\" build"
exit 1
;;
esac

Binary file not shown.

Binary file not shown.

View File

@@ -1 +0,0 @@
Test file content for decryption

Binary file not shown.

View File

@@ -1 +0,0 @@
Hello, this is a test file for encryption!

View File

@@ -1,7 +0,0 @@
-----BEGIN OTP MESSAGE-----
Version: v0.2.29
Pad-ChkSum: d0d4a489354348b08d8c7b324814d8c50010042e9da47f2c973f32a16a09101b
Pad-Offset: 57
05S8GfS0tFfczNMUz0xrieFGoPSREM4uo5QhFGoBCcOzjfTXTDMt3hRtAQ==
-----END OTP MESSAGE-----

Binary file not shown.

View File

@@ -1 +0,0 @@
This is a test file for encryption.

Binary file not shown.

163
nostr_chacha20.c Normal file
View File

@@ -0,0 +1,163 @@
/*
* nostr_chacha20.c - ChaCha20 stream cipher implementation
*
* Implementation based on RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols"
*
* This implementation is adapted from the RFC 8439 reference specification.
* It prioritizes correctness and clarity over performance optimization.
*/
#include "nostr_chacha20.h"
#include <string.h>
/*
* ============================================================================
* UTILITY MACROS AND FUNCTIONS
* ============================================================================
*/
/* Left rotate a 32-bit value by n bits */
#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
/* Convert 4 bytes to 32-bit little-endian */
static uint32_t bytes_to_u32_le(const uint8_t *bytes) {
return ((uint32_t)bytes[0]) |
((uint32_t)bytes[1] << 8) |
((uint32_t)bytes[2] << 16) |
((uint32_t)bytes[3] << 24);
}
/* Convert 32-bit to 4 bytes little-endian */
static void u32_to_bytes_le(uint32_t val, uint8_t *bytes) {
bytes[0] = (uint8_t)(val & 0xff);
bytes[1] = (uint8_t)((val >> 8) & 0xff);
bytes[2] = (uint8_t)((val >> 16) & 0xff);
bytes[3] = (uint8_t)((val >> 24) & 0xff);
}
/*
* ============================================================================
* CHACHA20 CORE FUNCTIONS
* ============================================================================
*/
void chacha20_quarter_round(uint32_t state[16], int a, int b, int c, int d) {
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTLEFT(state[d], 16);
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTLEFT(state[b], 12);
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTLEFT(state[d], 8);
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTLEFT(state[b], 7);
}
void chacha20_init_state(uint32_t state[16], const uint8_t key[32],
uint32_t counter, const uint8_t nonce[12]) {
/* ChaCha20 constants "expand 32-byte k" */
state[0] = 0x61707865;
state[1] = 0x3320646e;
state[2] = 0x79622d32;
state[3] = 0x6b206574;
/* Key (8 words) */
state[4] = bytes_to_u32_le(key + 0);
state[5] = bytes_to_u32_le(key + 4);
state[6] = bytes_to_u32_le(key + 8);
state[7] = bytes_to_u32_le(key + 12);
state[8] = bytes_to_u32_le(key + 16);
state[9] = bytes_to_u32_le(key + 20);
state[10] = bytes_to_u32_le(key + 24);
state[11] = bytes_to_u32_le(key + 28);
/* Counter (1 word) */
state[12] = counter;
/* Nonce (3 words) */
state[13] = bytes_to_u32_le(nonce + 0);
state[14] = bytes_to_u32_le(nonce + 4);
state[15] = bytes_to_u32_le(nonce + 8);
}
void chacha20_serialize_state(const uint32_t state[16], uint8_t output[64]) {
for (int i = 0; i < 16; i++) {
u32_to_bytes_le(state[i], output + (i * 4));
}
}
int chacha20_block(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], uint8_t output[64]) {
uint32_t state[16];
uint32_t initial_state[16];
/* Initialize state */
chacha20_init_state(state, key, counter, nonce);
/* Save initial state for later addition */
memcpy(initial_state, state, sizeof(initial_state));
/* Perform 20 rounds (10 iterations of the 8 quarter rounds) */
for (int i = 0; i < 10; i++) {
/* Column rounds */
chacha20_quarter_round(state, 0, 4, 8, 12);
chacha20_quarter_round(state, 1, 5, 9, 13);
chacha20_quarter_round(state, 2, 6, 10, 14);
chacha20_quarter_round(state, 3, 7, 11, 15);
/* Diagonal rounds */
chacha20_quarter_round(state, 0, 5, 10, 15);
chacha20_quarter_round(state, 1, 6, 11, 12);
chacha20_quarter_round(state, 2, 7, 8, 13);
chacha20_quarter_round(state, 3, 4, 9, 14);
}
/* Add initial state back (prevents slide attacks) */
for (int i = 0; i < 16; i++) {
state[i] += initial_state[i];
}
/* Serialize to output bytes */
chacha20_serialize_state(state, output);
return 0;
}
int chacha20_encrypt(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], const uint8_t* input,
uint8_t* output, size_t length) {
uint8_t keystream[CHACHA20_BLOCK_SIZE];
size_t offset = 0;
while (length > 0) {
/* Generate keystream block */
int ret = chacha20_block(key, counter, nonce, keystream);
if (ret != 0) {
return ret;
}
/* XOR with input to produce output */
size_t block_len = (length < CHACHA20_BLOCK_SIZE) ? length : CHACHA20_BLOCK_SIZE;
for (size_t i = 0; i < block_len; i++) {
output[offset + i] = input[offset + i] ^ keystream[i];
}
/* Move to next block */
offset += block_len;
length -= block_len;
counter++;
/* Check for counter overflow */
if (counter == 0) {
return -1; /* Counter wrapped around */
}
}
return 0;
}

115
nostr_chacha20.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* nostr_chacha20.h - ChaCha20 stream cipher implementation
*
* Implementation based on RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols"
*
* This is a small, portable implementation for NIP-44 support in the NOSTR library.
* The implementation prioritizes correctness and simplicity over performance.
*/
#ifndef NOSTR_CHACHA20_H
#define NOSTR_CHACHA20_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* CONSTANTS AND DEFINITIONS
* ============================================================================
*/
#define CHACHA20_KEY_SIZE 32 /* 256 bits */
#define CHACHA20_NONCE_SIZE 12 /* 96 bits */
#define CHACHA20_BLOCK_SIZE 64 /* 512 bits */
/*
* ============================================================================
* CORE CHACHA20 FUNCTIONS
* ============================================================================
*/
/**
* ChaCha20 quarter round operation
*
* Operates on four 32-bit words performing the core ChaCha20 quarter round:
* a += b; d ^= a; d <<<= 16;
* c += d; b ^= c; b <<<= 12;
* a += b; d ^= a; d <<<= 8;
* c += d; b ^= c; b <<<= 7;
*
* @param state[in,out] ChaCha state as 16 32-bit words
* @param a, b, c, d Indices into state array for quarter round
*/
void chacha20_quarter_round(uint32_t state[16], int a, int b, int c, int d);
/**
* ChaCha20 block function
*
* Transforms a 64-byte input block using ChaCha20 algorithm with 20 rounds.
*
* @param key[in] 32-byte key
* @param counter[in] 32-bit block counter
* @param nonce[in] 12-byte nonce
* @param output[out] 64-byte output buffer
* @return 0 on success, negative on error
*/
int chacha20_block(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], uint8_t output[64]);
/**
* ChaCha20 encryption/decryption
*
* Encrypts or decrypts data using ChaCha20 stream cipher.
* Since ChaCha20 is a stream cipher, encryption and decryption are the same operation.
*
* @param key[in] 32-byte key
* @param counter[in] Initial 32-bit counter value
* @param nonce[in] 12-byte nonce
* @param input[in] Input data to encrypt/decrypt
* @param output[out] Output buffer (can be same as input)
* @param length[in] Length of input data in bytes
* @return 0 on success, negative on error
*/
int chacha20_encrypt(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], const uint8_t* input,
uint8_t* output, size_t length);
/*
* ============================================================================
* UTILITY FUNCTIONS
* ============================================================================
*/
/**
* Initialize ChaCha20 state matrix
*
* Sets up the initial 16-word state matrix with constants, key, counter, and nonce.
*
* @param state[out] 16-word state array to initialize
* @param key[in] 32-byte key
* @param counter[in] 32-bit block counter
* @param nonce[in] 12-byte nonce
*/
void chacha20_init_state(uint32_t state[16], const uint8_t key[32],
uint32_t counter, const uint8_t nonce[12]);
/**
* Serialize ChaCha20 state to bytes
*
* Converts 16 32-bit words to 64 bytes in little-endian format.
*
* @param state[in] 16-word state array
* @param output[out] 64-byte output buffer
*/
void chacha20_serialize_state(const uint32_t state[16], uint8_t output[64]);
#ifdef __cplusplus
}
#endif
#endif /* NOSTR_CHACHA20_H */

BIN
otp-arm64 Executable file

Binary file not shown.

BIN
otp-x86_64 Executable file

Binary file not shown.

3216
otp.c

File diff suppressed because it is too large Load Diff

239
otp.h Normal file
View File

@@ -0,0 +1,239 @@
#ifndef OTP_H
#define OTP_H
////////////////////////////////////////////////////////////////////////////////
// OTP CIPHER - FUNCTION PROTOTYPES HEADER
// One Time Pad Implementation v0.2.109
//
// This header file contains all function prototypes extracted from otp.c
// Organized by functional categories for better maintainability
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <termios.h>
#include <sys/stat.h>
#include <time.h>
// Constants
#define MAX_INPUT_SIZE 4096
#define MAX_LINE_LENGTH 1024
#define MAX_HASH_LENGTH 65
#define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals
#define DEFAULT_PADS_DIR "pads"
#define FILES_DIR "files"
#define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer
////////////////////////////////////////////////////////////////////////////////
// TYPE DEFINITIONS
////////////////////////////////////////////////////////////////////////////////
// Decrypt operation modes for universal decrypt function
typedef enum {
DECRYPT_MODE_INTERACTIVE, // Interactive text decryption with prompts
DECRYPT_MODE_SILENT, // Silent text decryption (no prompts/labels)
DECRYPT_MODE_FILE_TO_TEXT, // File to text output with prompts
DECRYPT_MODE_FILE_TO_FILE // File to file output (binary)
} decrypt_mode_t;
// Pad filter types for selection functions
typedef enum {
PAD_FILTER_ALL, // Show all pads
PAD_FILTER_UNUSED_ONLY // Show only unused pads (0% usage)
} pad_filter_type_t;
// Enhanced entropy system state structure
typedef struct {
size_t target_bytes; // Target entropy to collect
size_t collected_bytes; // Bytes collected so far
size_t unique_keys; // Number of unique keys pressed
double collection_start_time; // Start timestamp
double last_keypress_time; // Last keypress timestamp
unsigned char quality_score; // Entropy quality (0-100)
int auto_complete_enabled; // Allow auto-complete at minimum
unsigned char key_histogram[256]; // Track key frequency
} entropy_collection_state_t;
////////////////////////////////////////////////////////////////////////////////
// CORE APPLICATION FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Main application entry points
int main(int argc, char* argv[]);
int interactive_mode(void);
int command_line_mode(int argc, char* argv[]);
int pipe_mode(int argc, char* argv[], const char* piped_text);
////////////////////////////////////////////////////////////////////////////////
// INPUT/OUTPUT DETECTION FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Stdin detection functions
int has_stdin_data(void);
char* read_stdin_text(void);
////////////////////////////////////////////////////////////////////////////////
// PREFERENCES MANAGEMENT FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Configuration and preferences handling
int load_preferences(void);
int save_preferences(void);
char* get_preference(const char* key);
int set_preference(const char* key, const char* value);
char* get_default_pad_path(void);
int set_default_pad_path(const char* pad_path);
////////////////////////////////////////////////////////////////////////////////
// HARDWARE DETECTION FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// OTP thumb drive detection function
int detect_otp_thumb_drive(char* otp_drive_path, size_t path_size);
////////////////////////////////////////////////////////////////////////////////
// EXTERNAL TOOL INTEGRATION FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Editor and file manager functions
char* get_preferred_editor(void);
char* get_preferred_file_manager(void);
int launch_text_editor(const char* initial_content, char* result_buffer, size_t buffer_size);
int launch_file_manager(const char* start_directory, char* selected_file, size_t buffer_size);
////////////////////////////////////////////////////////////////////////////////
// CORE CRYPTOGRAPHIC OPERATIONS
////////////////////////////////////////////////////////////////////////////////
// Primary encryption/decryption functions
int generate_pad(uint64_t size_bytes, int show_progress);
int encrypt_text(const char* pad_identifier, const char* input_text);
int decrypt_text(const char* pad_identifier, const char* encrypted_message);
int encrypt_file(const char* pad_identifier, const char* input_file, const char* output_file, int ascii_armor);
int decrypt_file(const char* input_file, const char* output_file);
int decrypt_binary_file(FILE* input_fp, const char* output_file);
int decrypt_ascii_file(const char* input_file, const char* output_file);
////////////////////////////////////////////////////////////////////////////////
// ENHANCED ENTROPY SYSTEM FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Terminal control for entropy collection
int setup_raw_terminal(struct termios* original_termios);
void restore_terminal(struct termios* original_termios);
// Entropy collection and feedback
int collect_entropy_with_feedback(unsigned char* entropy_buffer, size_t target_bytes,
size_t* collected_bytes, int allow_early_exit);
void display_entropy_progress(const entropy_collection_state_t* state);
void draw_progress_bar(double percentage, int width);
void draw_quality_bar(double quality, int width, const char* label);
// Entropy quality calculation
double calculate_timing_quality(const entropy_collection_state_t* state);
double calculate_variety_quality(const entropy_collection_state_t* state);
unsigned char calculate_overall_quality(const entropy_collection_state_t* state);
double get_precise_time(void);
// Entropy processing and application
int derive_chacha20_params(const unsigned char* entropy_data, size_t entropy_size,
unsigned char key[32], unsigned char nonce[12]);
int add_entropy_to_pad(const char* pad_chksum, const unsigned char* entropy_data,
size_t entropy_size, int show_progress);
int handle_add_entropy_to_pad(const char* pad_chksum);
// Enhanced entropy system helper functions
int update_pad_checksum_after_entropy(const char* old_chksum, char* new_chksum);
int rename_pad_files_safely(const char* old_chksum, const char* new_chksum);
int is_pad_unused(const char* pad_chksum);
////////////////////////////////////////////////////////////////////////////////
// DIRECTORY MANAGEMENT FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Directory handling and path management
int ensure_pads_directory(void);
void get_pad_path(const char* chksum, char* pad_path, char* state_path);
const char* get_files_directory(void);
void get_default_file_path(const char* filename, char* result_path, size_t result_size);
void get_directory_display(const char* file_path, char* result, size_t result_size);
////////////////////////////////////////////////////////////////////////////////
// UTILITY FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// General utility and helper functions
uint64_t parse_size_string(const char* size_str);
char* find_pad_by_prefix(const char* prefix);
int show_pad_info(const char* chksum);
void show_progress(uint64_t current, uint64_t total, time_t start_time);
////////////////////////////////////////////////////////////////////////////////
// FILE OPERATIONS
////////////////////////////////////////////////////////////////////////////////
// File state and checksum operations
int read_state_offset(const char* pad_chksum, uint64_t* offset);
int write_state_offset(const char* pad_chksum, uint64_t offset);
int calculate_checksum(const char* filename, char* checksum_hex);
////////////////////////////////////////////////////////////////////////////////
// UNIVERSAL CORE FUNCTIONS FOR CODE CONSOLIDATION
////////////////////////////////////////////////////////////////////////////////
// Consolidated cryptographic operations
int universal_xor_operation(const unsigned char* data, size_t data_len,
const unsigned char* pad_data, unsigned char* result);
int parse_ascii_message(const char* message, char* chksum, uint64_t* offset, char* base64_data);
int load_pad_data(const char* pad_chksum, uint64_t offset, size_t length, unsigned char** pad_data);
int generate_ascii_armor(const char* chksum, uint64_t offset, const unsigned char* encrypted_data,
size_t data_length, char** ascii_output);
int validate_pad_integrity(const char* pad_path, const char* expected_chksum);
// Universal decrypt function - consolidates all decrypt operations
int universal_decrypt(const char* input_data, const char* output_target, decrypt_mode_t mode);
////////////////////////////////////////////////////////////////////////////////
// BASE64 ENCODING FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Custom base64 implementation
char* custom_base64_encode(const unsigned char* input, int length);
unsigned char* custom_base64_decode(const char* input, int* output_length);
////////////////////////////////////////////////////////////////////////////////
// MENU SYSTEM FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Interactive menu interface functions
void show_main_menu(void);
int handle_generate_menu(void);
int handle_encrypt_menu(void);
int handle_decrypt_menu(void);
int handle_pads_menu(void);
int handle_text_encrypt(void);
int handle_file_encrypt(void);
////////////////////////////////////////////////////////////////////////////////
// ENHANCED INPUT FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Advanced input handling
int get_filename_with_default(const char* prompt, const char* default_path, char* result, size_t result_size);
////////////////////////////////////////////////////////////////////////////////
// PAD SELECTION FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Unified pad selection interface
char* select_pad_interactive(const char* title, const char* prompt, pad_filter_type_t filter_type, int allow_cancel);
////////////////////////////////////////////////////////////////////////////////
// USAGE AND HELP FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
// Help and usage display
void print_usage(const char* program_name);
#endif // OTP_H

BIN
otp.o Normal file

Binary file not shown.