Knowledge Base
A transparent look at how Vault3R works under the hood. We publish selected source code to let you verify our security claims. No black boxes — just standard, auditable cryptography.
Contents
Application Architecture
Vault3R is built with .NET 8 (WPF) on Windows and Kotlin (Jetpack Compose) on Android. The codebase follows a service-oriented pattern — each responsibility lives in a dedicated static or singleton service.
CryptoService
AES-256-GCM encryption/decryption, PBKDF2 key derivation, password hashing, constant-time comparison.
DatabaseService
Encrypted vault storage on disk — load, save, merge. Binary .vlt.db container with integrity checks.
DevicePairingService
Multi-device pairing — key generation, QR exchange, channel derivation, E2E encrypted confirmation.
ExportImportService
CSV/JSON import, .vlt backup & restore, merge/overwrite modes, encoding auto-detection.
PasswordStrengthService
Real-time password strength scoring — entropy calculation, pattern detection, dictionary checks.
ClipboardService
Secure clipboard operations — copy with auto-clear after 30 seconds, preventing clipboard history leaks.
LicenseService
Device-bound license validation via Hardware ID. Checks activation status against the license server.
AutoBackupService
Automatic encrypted .vlt backups on schedule — configurable interval, retention policy, background operation.
Data Models
Vault3R stores two types of encrypted records: password entries and secure notes. Both support tagging and are serialized as JSON before encryption.
public class PasswordEntry : INotifyPropertyChanged
{
public string Name { get; set; } = string.Empty;
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Category { get; set; } = string.Empty;
public List<string> Tags { get; set; } = new List<string>();
public string Notes { get; set; } = string.Empty;
public bool IsFavorite { get; set; } = false;
[JsonIgnore]
public string TagsDisplay => Tags == null
? string.Empty
: string.Join(", ", Tags
.Where(t => !string.IsNullOrWhiteSpace(t))
.Select(t => t.Trim()));
}
public class SecureNote
{
public string Id { get; set; } = Guid.NewGuid().ToString("N");
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public List<string> Tags { get; set; } = new List<string>();
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow;
[JsonIgnore]
public string TagsDisplay => Tags == null
? string.Empty
: string.Join(", ", Tags
.Where(t => !string.IsNullOrWhiteSpace(t))
.Select(t => t.Trim()));
}
Password field in PasswordEntry is additionally encrypted per-entry with the master password.
Vault Encryption
Vault3R uses industry-standard AES-256-GCM for authenticated encryption. The encryption key is derived from your master password using PBKDF2 with a random salt and high iteration count. No secrets are stored on disk — only the derived verifier and encrypted ciphertext.
public static class CryptoService
{
private const int KeySize = 256; // AES-256
private const int V2IterationCount = 200000; // PBKDF2 iterations
private const int V2SaltSizeBytes = 16; // 128-bit random salt
private const int V2NonceSizeBytes = 12; // 96-bit GCM nonce
private const int V2TagSizeBytes = 16; // 128-bit auth tag
}
/// <summary>
/// Creates a password verifier (stored on disk to validate unlock).
/// Format: v2$pbkdf2-sha256$iterations$salt_b64$hash_b64
/// The master password itself is never stored.
/// </summary>
public static string CreatePasswordVerifier(string password)
{
var salt = RandomNumberGenerator.GetBytes(V2SaltSizeBytes);
var key = DeriveKeyPbkdf2(password, salt, V2IterationCount);
var saltB64 = Convert.ToBase64String(salt);
var hashB64 = Convert.ToBase64String(key);
return $"v2$pbkdf2-sha256${V2IterationCount}${saltB64}${hashB64}";
}
/// <summary>
/// Constant-time password comparison to prevent timing side-channel attacks.
/// </summary>
public static bool VerifyPassword(string password, string hash)
{
var a = Encoding.UTF8.GetBytes(HashPassword(password));
var b = Encoding.UTF8.GetBytes(hash);
if (a.Length != b.Length) return false;
return CryptographicOperations.FixedTimeEquals(a, b);
}
salt + nonce + auth_tag + ciphertext stored on disk. Decryption verifies the authentication tag before returning any plaintext — any tampering is detected and rejected.
Encrypted Device Sync
Vault3R syncs between Windows and Android through an ephemeral relay. All data is end-to-end encrypted with a shared 256-bit key — the relay only handles opaque ciphertext and purges it immediately after download.
Key generation
256-bit key via CSPRNG. Never leaves the devices.
QR exchange
Key transferred via QR code scan. No network involved.
AES-GCM encrypt
Vault encrypted locally before upload to relay.
Deliver & purge
Receiver decrypts. Relay data auto-deleted.
/// <summary>
/// Computes channel ID from a raw pairing key.
/// channel = HMAC-SHA256(pairingKey, "vault3r-relay-channel") → hex.
/// The relay never sees the pairing key — only the derived channel ID.
/// </summary>
public static string ComputeChannelId(byte[] pairingKey)
{
using var hmac = new HMACSHA256(pairingKey);
var hash = hmac.ComputeHash(
Encoding.UTF8.GetBytes("vault3r-relay-channel")
);
return Convert.ToHexString(hash).ToLowerInvariant();
}
/// <summary>
/// Encrypts data with a pairing key using AES-256-GCM.
/// Output format: nonce(12 bytes) + auth_tag(16 bytes) + ciphertext
/// </summary>
public static byte[] Encrypt(byte[] plaintext, byte[] pairingKey)
{
var nonce = RandomNumberGenerator.GetBytes(12);
var tag = new byte[16];
var cipher = new byte[plaintext.Length];
using var aes = new AesGcm(pairingKey, 16);
aes.Encrypt(nonce, plaintext, cipher, tag);
var result = new byte[12 + 16 + cipher.Length];
Buffer.BlockCopy(nonce, 0, result, 0, 12);
Buffer.BlockCopy(tag, 0, result, 12, 16);
Buffer.BlockCopy(cipher, 0, result, 28, cipher.Length);
return result;
}
Pairing Protocol
Each device pairing is isolated — every pair gets its own 256-bit key and derived channel. Pairing keys are exchanged via QR code using a custom URI scheme. The protocol supports multiple simultaneous pairings.
/// <summary>
/// Model for a single paired device.
/// Each pairing has its own isolated 256-bit key and derived channel.
/// </summary>
public class PairedDevice
{
[JsonPropertyName("id")]
public string Id { get; set; } = "";
[JsonPropertyName("device_name")]
public string DeviceName { get; set; } = "";
[JsonPropertyName("pairing_key")]
public string PairingKeyBase64 { get; set; } = "";
[JsonPropertyName("channel_id")]
public string ChannelId { get; set; } = "";
[JsonPropertyName("paired_at")]
public string PairedAt { get; set; } = "";
}
/// <summary>
/// Builds the pairing URI embedded in the QR code.
/// Format: vault3r-pair://KEY_BASE64?device=DEVICE_NAME
/// </summary>
public static string GetPairingUri(string base64Key)
{
var deviceName = Uri.EscapeDataString(GetLocalDeviceName());
var keyEncoded = Uri.EscapeDataString(base64Key);
return $"vault3r-pair://{keyEncoded}?device={deviceName}";
}
/// <summary>
/// Generates a new 256-bit pairing key using CSPRNG.
/// Key is not saved until the pairing is confirmed by both devices.
/// </summary>
public static string GenerateKeyBase64()
{
var key = RandomNumberGenerator.GetBytes(32);
return Convert.ToBase64String(key);
}
vault3r-pair:// URI → displays QR code → Android scans and imports the key → both devices derive the same channel ID via HMAC-SHA256 → pairing confirmation is exchanged through the relay (E2E encrypted) → both sides save the pairing only after mutual confirmation.