A standalone PHP library for creating encrypted, self-destructing messages with view limits and optional password protection. Based on the CryptNote.pro encryption system.
- 🔐 AES-256-CBC Encryption - Military-grade encryption for your messages
- 🔑 Optional Password Protection - Add an extra layer of security with PBKDF2 key derivation
- 👁️ View Limits - Messages self-destruct after a specified number of views
- ⏰ Time Expiration - Set messages to expire after a certain time
- 📝 Markdown/HTML Support - Store and retrieve formatted content
- 🗄️ SQLite Storage - Zero-configuration database included
- 🧹 Auto Cleanup - Automatic removal of old, unviewed messages
- 🔒 Secure Deletion - Data is overwritten before deletion
- PHP 8.0 or higher
- OpenSSL extension
- PDO extension with SQLite driver
composer require dolutech/cryptnote-php- Download or clone this repository
- Include the autoloader or require the files directly:
require_once 'path/to/library-open/src/CryptNote.php';
require_once 'path/to/library-open/src/CryptNoteStandalone.php';<?php
use CryptNote\CryptNote;
// Initialize with default settings
$cryptnote = new CryptNote();
// Create an encrypted note
$result = $cryptnote->create('This is a secret message!', [
'max_views' => 1, // Self-destruct after 1 view
]);
echo "Token: " . $result['token'];
// Token: a1b2c3d4e5f6...
// View the note (this will decrement the view count)
$note = $cryptnote->view($result['token']);
echo $note['content'];
// Output: This is a secret message!
// The note is now destroyed (max_views reached)<?php
use CryptNote\CryptNote;
$cryptnote = new CryptNote();
// Create a password-protected note
$result = $cryptnote->create('Top secret information', [
'password' => 'mySecretPassword123',
'max_views' => 3,
]);
// View requires the password
$note = $cryptnote->view($result['token'], 'mySecretPassword123');
echo $note['content'];<?php
use CryptNote\CryptNote;
$cryptnote = new CryptNote();
// Create a note that expires in 60 minutes
$result = $cryptnote->create('Time-sensitive information', [
'max_views' => 10,
'expire_minutes' => 60, // Expires in 1 hour
]);
echo "Expires at: " . $result['expires_at'];<?php
use CryptNote\CryptNote;
$cryptnote = new CryptNote();
$status = $cryptnote->status($token);
if ($status['status'] === 'active') {
echo "Note is active";
echo "Remaining views: " . $status['remaining_views'];
echo "Requires password: " . ($status['requires_password'] ? 'Yes' : 'No');
} elseif ($status['status'] === 'expired') {
echo "Note has expired";
} else {
echo "Note not found";
}If you want to handle storage yourself, use the CryptNoteStandalone class:
<?php
use CryptNote\CryptNoteStandalone;
$crypto = new CryptNoteStandalone();
// Generate a key
$key = $crypto->generateKey();
// Encrypt
$encrypted = $crypto->encrypt('My secret data', $key);
// Decrypt
$decrypted = $crypto->decrypt($encrypted, $key);
// With password
$encrypted = $crypto->encryptWithPassword('My secret', $key, 'password123');
$decrypted = $crypto->decryptWithPassword($encrypted, $key, 'password123');$cryptnote = new CryptNote([
// Database path (default: ./data/cryptnote.db)
'db_path' => '/path/to/your/database.db',
// Encryption method (default: AES-256-CBC)
'encryption_method' => 'AES-256-CBC',
// Token length in bytes (default: 32, produces 64 hex chars)
'token_length' => 32,
// Maximum content length (default: 50000)
'max_content_length' => 50000,
// PBKDF2 iterations for password derivation (default: 100000)
'pbkdf2_iterations' => 100000,
// Enable automatic cleanup (default: true)
'auto_cleanup' => true,
// Days after which unviewed notes are cleaned (default: 15)
'cleanup_days' => 15,
// Base URL for generating share links (optional)
'base_url' => 'https://yoursite.com/view',
]);$crypto = new CryptNoteStandalone([
'encryption_method' => 'AES-256-CBC',
'pbkdf2_iterations' => 100000,
]);Create an encrypted note.
Options:
password(string|null): Optional password for additional protectionmax_views(int): Maximum views before destruction (1-100, default: 1)expire_minutes(int|null): Minutes until expiration (max: 10080 = 7 days)is_markdown(bool): Whether content is Markdown (default: false)is_html(bool): Whether content is HTML (default: false)
Returns:
[
'success' => true,
'token' => 'abc123...',
'has_password' => false,
'max_views' => 1,
'is_markdown' => false,
'is_html' => false,
'expires_at' => '2026-01-15 12:00:00',
'created_at' => '2026-01-15 11:00:00',
'share_url' => 'https://yoursite.com/view?token=abc123...', // if base_url configured
]View and decrypt a note.
Returns:
[
'success' => true,
'content' => 'The decrypted message',
'is_markdown' => false,
'is_html' => false,
'remaining_views' => 0,
'max_views' => 1,
'expires_at' => null,
'destroyed' => true,
]Check note status without viewing.
Returns:
[
'success' => true,
'status' => 'active', // 'active', 'expired', 'not_found', 'invalid_token'
'requires_password' => false,
'is_markdown' => false,
'is_html' => false,
'max_views' => 3,
'remaining_views' => 2,
'expires_at' => null,
'created_at' => '2026-01-15 11:00:00',
]Manually delete a note.
Get database statistics.
Generate a secure random token.
Generate a random encryption key.
Encrypt content.
Decrypt content.
Encrypt with password protection.
Decrypt with password.
Validate token format.
Generate a secure random password.
- Database Security: Ensure your SQLite database file is not publicly accessible. Store it outside the web root.
- HTTPS: Always use HTTPS when transmitting tokens or passwords
- Password Strength: Minimum 6 characters required. Encourage users to use strong passwords
- Key Storage: Never log or expose encryption keys
- Secure Deletion: The library overwrites data before deletion, but consider disk-level encryption for additional security
- PBKDF2: Uses 100,000 iterations by default. For high-security applications, consider increasing or using Argon2id
- Rate Limiting: Implement rate limiting in your application to prevent brute-force attacks on password-protected notes
Here's a simple example of building a web interface:
<?php
// create.php
use CryptNote\CryptNote;
$cryptnote = new CryptNote([
'base_url' => 'https://yoursite.com/view.php',
]);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$result = $cryptnote->create($_POST['content'], [
'password' => $_POST['password'] ?: null,
'max_views' => (int)$_POST['max_views'],
'expire_minutes' => $_POST['expire_minutes'] ?: null,
]);
echo "Share this link: " . $result['share_url'];
}<?php
// view.php
use CryptNote\CryptNote;
$cryptnote = new CryptNote();
$token = $_GET['token'] ?? '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$note = $cryptnote->view($token, $_POST['password'] ?? null);
echo htmlspecialchars($note['content']);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Packagist: packagist.org/packages/dolutech/cryptnote-php
- GitHub: github.com/dolutech/cryptnote-php
- CryptNote.pro: cryptnote.pro
Developed by Dolutech - Based on CryptNote.pro encryption system.