Security Architecture &
Technical Internals

A complete breakdown of how Qlerky Password Manager handles encryption, key derivation, TOTP two-factor authentication, and all four export formats — including the steganographic image encoding pipeline.

System Architecture #

Qlerky is designed around a zero-trust, offline-first architecture. The application makes no outbound network requests related to user data. There is no backend service, no authentication server, no telemetry endpoint, and no cloud synchronization layer. The entire security perimeter is the user's physical device.

Master Password ──KDF──▶ Derived Key ──AES──▶ Encrypted Vault stored locally on device Android App Sandbox ◀── no network ── Internet

Core Design Principles

  • Local-only storage: All vault data resides in the Android app's private data directory, inaccessible to other apps without root access.
  • Encryption at rest: The vault file is always stored in encrypted form. The derived key only exists in memory during an active session.
  • No plaintext persistence: Decrypted data is never written to disk, log files, or shared storage.
  • Zero network surface: No passwords, keys, or credentials are transmitted over any network interface under any circumstances.
  • Offline TOTP: Time-based one-time passwords are calculated locally using device time, with no external time server required.
Security Property Even if a malicious actor gains access to the encrypted vault file on disk, without the correct master password they obtain an opaque encrypted blob that reveals no information about the stored credentials.

Threat Model #

Understanding what Qlerky protects against — and what it does not — is essential for correct usage.

Threats Mitigated

Threat Mitigation Confidence
Server breach / cloud hack No server exists. No data is stored remotely. 🟢 Eliminated
Network interception (MITM) No network transmission of vault data. 🟢 Eliminated
Third-party data sale No third-party involved. No account created. 🟢 Eliminated
App shutdown / service discontinuation Data is local. App can be sideloaded. CSV export always available. 🟢 Mitigated
Unauthorized device access AES encryption + master password required to read vault. 🟡 Mitigated (depends on password strength)
Malware on same device Android sandbox + no plaintext persistence reduces risk. 🟡 Partially mitigated

Out of Scope

  • Compromised device (rooted/jailbroken): Root access can bypass the Android sandbox. If your device is rooted, no application can guarantee complete security.
  • Weak master password: Qlerky's encryption strength is directly proportional to master password entropy. A weak password significantly degrades protection.
  • Physical coercion: Qlerky cannot protect against someone forcing you to reveal your master password.
  • Screen recording / keylogging malware: If malware is already installed and active on your device, it may capture credentials as you type them into Qlerky.
Important Qlerky is designed for users who prefer local control over convenience. It is not a substitute for device-level security: use a strong device PIN, enable full-disk encryption (enabled by default on modern Android), and avoid installing apps from untrusted sources.

AES Encryption #

Qlerky uses AES (Advanced Encryption Standard), the same symmetric cipher used by governments, financial institutions, and security-critical applications worldwide. AES was selected by NIST in 2001 and remains unbroken by any publicly known attack against properly implemented instances.

Why AES?

AES offers an optimal balance of security, performance, and hardware acceleration. On modern Android devices, AES operations are accelerated by dedicated CPU instructions (AES-NI on ARMv8), making encryption and decryption fast enough to be imperceptible to the user while maintaining cryptographic strength.

Key Derivation with Argon2

A master password alone cannot directly serve as an AES key — passwords are short, human-memorable strings with insufficient entropy and non-uniform bit distribution. Qlerky uses Argon2 — the winner of the Password Hashing Competition (PHC) in 2015 and the current gold standard for password-based key derivation — to transform the master password into a cryptographically strong encryption key.

Argon2 is superior to older KDFs like PBKDF2 and bcrypt because it is designed to be:

  • Memory-hard: Requires a configurable amount of RAM to compute, making GPU and ASIC-based brute-force attacks extremely costly
  • Time-hard: Configurable iteration count adds CPU cost on top of memory cost
  • Parallelism-resistant: Controls how many parallel threads can be used, limiting attacker hardware advantage
  • Salt-protected: A random salt prevents precomputed rainbow table attacks
  • Deterministic: The same password + salt + parameters always produces the same key
Argon2 Variants Argon2 comes in three variants: Argon2d (GPU resistance), Argon2i (side-channel resistance), and Argon2id (hybrid — recommended by RFC 9106). Qlerky uses Argon2id, the variant recommended for password hashing and key derivation in interactive applications.
pseudocode · Argon2id
// Key derivation pipeline
salt        = generateRandomBytes(32)     // 256-bit random salt

key         = Argon2id(
                password    = masterPassword,
                salt        = salt,
                memory      = 65536,           // 64 MB RAM required
                iterations  = 3,               // time cost passes
                parallelism = 4,               // thread lanes
                keyLength   = 32               // 256-bit AES key output
              )

// Encrypt vault with derived key
iv             = generateRandomBytes(12)    // 96-bit IV for GCM
encryptedVault = AES_GCM_encrypt(key, iv, vaultJSON)

// Stored on disk: salt + iv + encryptedVault
// masterPassword and key are NEVER persisted
            

The 64 MB memory requirement is the key differentiator from PBKDF2. An attacker trying to brute-force a master password cannot run millions of parallel attempts on a GPU — each attempt consumes 64 MB of RAM, making large-scale parallelism hardware-prohibitive rather than just computationally slow.

Master Password Handling

The master password has a carefully constrained lifecycle inside Qlerky:

1

Password Entry

The user types the master password into a secure text field. The string is held in memory only for the duration of key derivation.

2

Key Derivation

Argon2id transforms the password into a 256-bit AES key. The original password string is released for garbage collection immediately after.

3

Session Key in Memory

The derived key remains in memory for the duration of the active session. It is used to decrypt vault entries on-demand.

4

Session Termination

When the app is backgrounded, locked, or closed, the in-memory key is zeroed out. The next open requires re-entry of the master password (or biometric verification if configured).

Developer Note Qlerky uses AES-GCM (Galois/Counter Mode) rather than AES-CBC. GCM provides authenticated encryption — any tampering with the ciphertext is detected before decryption, preventing padding oracle attacks and ciphertext manipulation.

Biometric Unlock

For user convenience, Qlerky supports Android's BiometricPrompt API to allow fingerprint or face unlock. Biometric authentication does not replace the master password — instead, the derived key is stored in the Android Keystore (hardware-backed secure enclave when available) and is only released by the OS after successful biometric verification. The master password is still required to initially unlock after a fresh install or if biometrics are unavailable.

TOTP Two-Factor Authentication #

Qlerky implements TOTP (Time-based One-Time Password) as defined in RFC 6238. TOTP is the standard used by Google Authenticator, Authy, Microsoft Authenticator, and all major 2FA implementations.

TOTP Algorithm Internals

A TOTP code is generated from two inputs: a shared secret (the Base32-encoded key from a QR code scan) and the current Unix timestamp divided into 30-second time windows.

TOTP · RFC 6238
// Step 1: Calculate current time window (T0 = 0, step = 30s)
T = floor(currentUnixTime / 30)

// Step 2: HMAC-SHA1 with secret key and time counter
hmac = HMAC_SHA1(
    key     = base32Decode(sharedSecret),
    message = toBytes(T, length=8)           // 8-byte big-endian
)  // Returns 20-byte hash

// Step 3: Dynamic truncation
offset = hmac[19] & 0x0F
binary = (hmac[offset]   & 0x7F) << 24
        | (hmac[offset+1] & 0xFF) << 16
        | (hmac[offset+2] & 0xFF) <<  8
        | (hmac[offset+3] & 0xFF)

// Step 4: Extract 6-digit code
otp = binary % 1_000_000   // yields 000000 – 999999
            

Next Code Preview

Most TOTP authenticators show only the current time window's code. This creates a frustrating user experience when a code expires in 1-3 seconds — not enough time to switch apps and paste it into a login field. Qlerky solves this with a next code preview.

The implementation is straightforward: Qlerky computes TOTP for both T (current window) and T + 1 (next window) simultaneously, displaying both codes side by side with a countdown timer for the current code's remaining validity.

Next Code Logic
currentT = floor(unixTime / 30)
nextT    = currentT + 1

currentCode = computeTOTP(secret, currentT)
nextCode    = computeTOTP(secret, nextT)

secondsRemaining = 30 - (unixTime % 30)

// UI: show currentCode + countdown + nextCode preview
            
Why This Matters Users who frequently log into crypto exchanges, trading platforms, or services with strict 2FA requirements will find next-code preview eliminates login failures caused by expiring codes.

2FA Secret Key Storage

The Base32-encoded TOTP secret (the key that would be revealed if you click "Can't scan QR code?" on a 2FA setup page) is treated identically to any other sensitive field in Qlerky — it is encrypted inside the vault using the same AES-GCM scheme. The secret is only decrypted into memory when the TOTP screen is active, and is zeroed from memory when the screen is dismissed.

Note on 2FA Backup Strategy Since Qlerky stores 2FA secrets locally, losing access to your device without a backup means losing access to your 2FA codes. Always maintain an encrypted backup using the Qlerky File export format, or record recovery codes from each service you register.

Export Architecture #

Qlerky supports four export formats for individual vault entries. Each format makes a deliberate trade-off between security, portability, and covertness.

🗝️ Qlerky File

Max Security
EncryptionAES-GCM
FormatProprietary binary
Readable byQlerky only
Password neededYes
Best forBackups, device migration

📷 QR Code

Encrypted
EncryptionAES-GCM
FormatBase64 in QR
Readable byQlerky (scan)
Password neededYes (to decode)
Best forQuick device-to-device

🖼️ Inside Image

Steganographic
EncryptionAES-GCM + LSB
FormatPNG image
Readable byQlerky (image import)
Password neededYes
Best forCovert transfer

📄 CSV

Unencrypted
EncryptionNone
FormatPlain text CSV
Readable byAny password manager
Password neededNo
Best forMigration to other apps

Qlerky File Format (.qlerky) #

The .qlerky file is Qlerky's native export format. It encodes a single vault entry as an encrypted, self-contained binary blob that can only be opened by another Qlerky installation knowing the correct export password.

File Structure

binary layout
┌─────────────────────────────────────────────────────┐
│  4 bytes   │  Magic header: 0x514C4B59 ("QLKY")    │
│  1 byte    │  Format version                        │
│  32 bytes  │  KDF salt (random per export)          │
│  4 bytes   │  KDF iteration count                   │
│  12 bytes  │  AES-GCM IV (nonce)                   │
│  16 bytes  │  GCM authentication tag               │
│  N bytes   │  AES-GCM encrypted JSON payload        │
└─────────────────────────────────────────────────────┘

// Decrypted JSON payload structure
{
  "version": 1,
  "title":   "Discord",
  "login":   "user@multitools.ovh",
  "password": "s3cur3p4ss",
  "totp_secret": "BASE32SECRET...",   // optional
  "notes":   "...",
  "tags":    ["exchange", "2fa"],
  "created_at": "2025-01-15T10:00:00Z"
}
            

The export password (which can differ from the master password) is used as input to the same KDF pipeline. This means sharing a .qlerky file requires communicating only the export password to the recipient — the file itself reveals nothing without it.

QR Code Export #

QR code export is designed for rapid, cable-free transfer between two Android devices running Qlerky. It encodes the same encrypted payload as the Qlerky File format, but represents it as a scannable QR code rather than a file.

Encoding Pipeline

1

Serialize entry to JSON

The vault entry is serialized to a compact JSON string.

2

AES-GCM encrypt

The JSON is encrypted using the same AES-GCM scheme with a user-provided export password.

3

Base64 encode

The binary ciphertext (salt + IV + tag + ciphertext) is Base64-encoded to produce a printable string safe for QR encoding.

4

QR generation

The Base64 string is encoded into a QR code using Error Correction Level M (15% redundancy). The QR is displayed full-screen for scanning.

Capacity Note QR codes have a maximum data capacity (~3KB in binary mode). For entries with long notes or multiple fields, very large payloads may exceed this limit. In such cases, the Qlerky File format is recommended instead.

Steganographic Image Export (LSB) #

Inside Image is Qlerky's most technically sophisticated export format. It uses Least Significant Bit (LSB) steganography to embed encrypted payload data into a cover image in a way that produces no visually detectable change to the image.

What is Steganography?

Steganography is the practice of hiding information inside a non-secret carrier medium. Unlike encryption (which obscures content but reveals the existence of a secret), steganography aims to hide the very existence of the hidden message. The word comes from Greek: steganos (covered) + graphein (writing).

In Qlerky's implementation, the carrier medium is a PNG image chosen by the user. The hidden payload is the AES-encrypted vault entry. The resulting stego-image is visually identical to the original — it can be shared publicly without revealing that any hidden data exists.

LSB Encoding Explained

Each pixel in a digital image is represented by three color channels: Red, Green, Blue (RGB). Each channel is an 8-bit value (0–255). The least significant bit of any channel value contributes only 1 unit out of 255 to the color — a change of 1 is completely imperceptible to human vision.

Original pixel values
R: 200  →  11001000
G: 140  →  10001100
B:  80  →  01010000
After LSB encoding (1 bit hidden)
R: 201  →  11001001  ← bit changed
G: 140  →  10001100
B:  80  →  01010000

By modifying only the LSB of the Red channel, the pixel color shifts from RGB(200, 140, 80) to RGB(201, 140, 80) — a difference of one unit in a range of 256. This change is far below the threshold of human color discrimination (typically ~2-5 units) and is also below the noise introduced by most camera sensors.

Full Encoding Pipeline

LSB Steganography Pipeline
// Phase 1: Prepare payload
entryJSON  = serialize(vaultEntry)
encrypted  = AES_GCM_encrypt(exportPassword, entryJSON)
payload    = [4-byte length header] + encrypted

// Phase 2: Convert to bit stream
bits = toBitArray(payload)     // e.g. [1,0,1,1,0,0,1,0, ...]

// Phase 3: Embed bits into image pixels
for i, bit in enumerate(bits):
    pixel = coverImage[i / 3]     // one bit per R/G/B channel
    channel = i % 3               // 0=R, 1=G, 2=B

    // Replace LSB of channel with payload bit
    pixel[channel] = (pixel[channel] & 0xFE) | bit

// Phase 4: Export as lossless PNG
savePNG(coverImage)   // PNG preserves exact pixel values
                      // JPEG would destroy LSB data
            

Capacity Calculation

Each pixel can hold 3 bits of payload (one per RGB channel). A 1920×1080 cover image has 2,073,600 pixels, giving a maximum capacity of ~6.2 million bits (~776 KB). A typical Qlerky vault entry (with password, login, 2FA secret, and notes) is well under 1 KB when JSON-serialized, so even a small 200×200 thumbnail has sufficient capacity.

Image Size Pixels Max Payload Suitable for
200×200 40,000 ~15 KB Single entry ✓
1280×720 921,600 ~345 KB Multiple entries ✓
1920×1080 2,073,600 ~776 KB Full vault export ✓

Why PNG Only?

LSB steganography requires the cover image to preserve exact pixel values after saving. PNG uses lossless compression — pixel values are stored bit-for-bit identically. JPEG uses lossy compression — its discrete cosine transform (DCT) quantization step modifies pixel values throughout the image, destroying any LSB-encoded data. This is also why sharing the stego-image through platforms that re-compress images (WhatsApp, Instagram, most messengers) will corrupt the payload.

Critical Requirement Always transfer steganographic images as lossless files. Use: direct USB transfer, Google Drive / Dropbox (download original file), Telegram "Send as File" option, or AirDrop. Do NOT use: WhatsApp photo send, Instagram DM, Twitter/X image upload — these will destroy the hidden data.

CSV Export #

CSV (Comma-Separated Values) export produces a plaintext, unencrypted file compatible with most major password managers including Bitwarden, 1Password, LastPass, KeePass, and others. It is intended for data migration scenarios — not for secure long-term storage.

CSV Schema

CSV Format
name,login,password,totp_secret,url,notes,tags
"Discord","user@multitools.ovh","p4ssw0rd!","BASE32SECRET","discord.com","","social"
"Binance","trader@mail.com","exch4ng3pass","TOTPSECRET123","binance.com","Main account","exchange,2fa"
            
Security Warning — Handle with Care The CSV file contains your passwords and 2FA secrets in plain text. After importing into another application, delete the CSV file securely. Do not store it in cloud storage, email it, or leave it in your Downloads folder. On Android, you can delete it via a file manager immediately after the import is complete.

Ready to take back control of your credentials?

Qlerky is free, offline, and available right now on Android.

Download on Google Play →

Technical FAQ #

Can I verify Qlerky isn't making network requests?

Yes. Enable Android's built-in Developer Options → Network traffic monitor, or use an app like NetGuard to observe that Qlerky makes zero outbound connections during normal operation. You can also run it in airplane mode — all functionality remains available.

How does Qlerky compare to KeePass for Android?

Both are offline-first password managers. Qlerky differentiates with native TOTP 2FA storage with next-code preview, steganographic export, and a purpose-built mobile UI designed specifically for credential management for exchanges and services. KeePass-compatible formats (KDBX) are not directly supported, but CSV import/export enables migration in both directions.

What happens to the vault if I uninstall the app?

Android removes the app's private data directory on uninstall by default. Your vault is deleted along with the app unless you first export a backup using the Qlerky File format. Always export a backup before uninstalling.

Is the source code available?

Qlerky is a private application by Hidden Flame. The security model described in this document represents the implemented architecture. If you are a security researcher and wish to discuss the implementation in more detail, feedback and responsible disclosure inquiries are welcome through the app's Play Store listing.

Does Qlerky support HOTP (counter-based OTP)?

Currently, Qlerky supports TOTP (time-based) only, which covers the vast majority of 2FA implementations used by exchanges, email providers, and social platforms. HOTP (HMAC-based, counter-driven) support is under consideration for future releases.

Topic Index #

Keywords and topics covered in this documentation, useful for finding related information:

Security Concepts

AES-256 encryption AES-GCM authenticated encryption Argon2 key derivation master password salt + IV Android Keystore biometric unlock zero-trust architecture local-only encryption offline password manager ciphertext authentication tag padding oracle prevention rainbow table protection Argon2id KDF memory-hard key derivation key entropy

Two-Factor Authentication

TOTP RFC 6238 2FA code manager next code preview Google Authenticator alternative HMAC-SHA1 Base32 secret 30-second time window offline TOTP two factor authentication app Android OTP generator authenticator app no cloud HOTP time-based one-time password

Steganography

LSB steganography least significant bit encoding hide data in image steganographic password export PNG lossless pixel color channels RGB bit manipulation covert data transfer image steganography Android steganalysis resistance cover image payload capacity lossless image format JPEG compression artifact

Export Formats

Qlerky file format .qlerky export QR code password export encrypted QR code CSV password manager export password manager migration Bitwarden import CSV 1Password import Base64 QR encoding device-to-device transfer backup vault no cable transfer

Use Cases

crypto exchange password manager wallet credential storage API key manager offline no cloud sync password manager private key storage app seed phrase manager exchange 2FA manager Android security app password manager for traders Binance 2FA app offline authenticator Android no internet password app DeFi credential manager