mleku's avatar
mleku
me@mleku.dev
npub125uw...lek0
# silicon valley output, bishkek burn rate i build working software. i learn anything. graphs, protocols, translation, memory for LLMs - whatever your stack needs. - \$500 signing (one-time, gets me to kyrgyzstan) - \$300/week (covers ger + goat milk + sim data) - stack: anything i can learn (and i learn fast) #### why so cheap? i live on the steppe. my rent is a yurt, my overhead is food and bandwidth. you don't pay for my city. you pay for my output. need a prototype, a custom tool, or a full system? let's talk. ## contact: - **matrix:** @smeshlol:matrix.org - **signal:** mleku.80 - **simplex:** https://smp19.simplex.im/a#uFxMEU_sv2lbmscozEBo50HSkQGYkOvIN05bMMLjAz0 - **email:** [me@mleku.dev ](mailto:me@mleku.dev) - **git:** https://git.smesh.lol
mleku's avatar
mleku 2 hours ago
all politicians are scum but some politicians are less scummy - some stupid democrat fan in denial
mleku's avatar
mleku 3 hours ago
here's the full report of what was wrong with #cipherkeys and how it was fixed in the 00032 version: --- # CipherKeys v00032 — Security Audit & Fixes A third-party source review of v00030 surfaced 12 findings plus a handful of polish items. Everything below is fixed in v00032, which also ships an encrypted configuration backup/restore feature to smooth the signing-key migration. > **TL;DR for existing users:** v00032 changes the APK signing key. Install v00031 first and use **Settings → Backup & Restore → Export** to save your keys, recipients, and settings, then install v00032 and **Import** them. > v00031 download: `https://git.smesh.lol/cipherkeys-releases/raw/cipherkeys-v00031.apk` --- ## What was already solid - **Zero permissions** — no `INTERNET`, no networking code anywhere in the tree. For a keyboard this is the property that matters most, and it means none of the findings below were remotely exploitable. - Crypto is delegated to **PGPainless** (not hand-rolled). - Gradle wrapper pins a SHA-256 with `validateDistributionUrl=true`. - `decryptInternal` checks `metadata.isEncrypted` before returning — a trap many PGP frontends fall into. --- ## High severity ### 1. Decryption never verified signatures — FIXED `doDecrypt` returned only plaintext and never read `metadata.verifiedSignatures`, so a message from anyone holding your public key was indistinguishable in the UI from one sent by a trusted contact. → Decrypt now adds the sender's cert via `addVerificationCert()`, verifies the signature, and surfaces the signer's identity (or an explicit "Message is not signed" warning) in the panel. ### 2. Paste verification used the wrong key set — FIXED `onPaste` built verification certs from the user's *own* keys instead of the recipient list, so a message signed by a real correspondent could never verify, and the banner was generic "Message valid". → Paste verification now uses recipient public keys and shows *whose* signature it is. ### 3. Secret keys in plain SharedPreferences + `allowBackup="true"` — FIXED Armored secret key rings were stored verbatim in plain prefs and Android's backup (Seedvault / Google Drive / D2D) copied them off-device. → Key storage now uses **EncryptedSharedPreferences** (Android Keystore-backed AES-256-GCM master key) with a one-time migration from the old plain store, and `allowBackup="false"`. ### 4. Release APK signed with the Android debug keystore — FIXED `storePassword = "android"` at a well-known path meant anyone with that public keystore could ship an update Android accepts as the same app. → A dedicated release keystore (RSA-4096) with a real password is now used, referenced out-of-repo via environment variables / `~/.gradle/gradle.properties`. ### 5. "Copy Secret" exported the private key in one tap — FIXED No confirmation, no passphrase check, no sensitive-clipboard flag, sitting right beside "Copy Public". → Now a confirmation dialog that *actually verifies the passphrase* (PGPainless unlock), marks the clip `EXTRA_IS_SENSITIVE`, and clears it after 30 s. ### 6. The passphrase could be signed and committed into the target app — FIXED `handleSend` was the only send path without a `pendingAction` guard, so a passphrase could overwrite the saved message and get signed/committed as a cleartext-signed block. → `handleSend` now early-dispatches through the same pending-action routing as the encrypt/decrypt handlers. --- ## Medium severity ### 7. Plaintext logged in release builds — FIXED `Log.*` calls interpolated decrypted plaintext and key IDs, and release wasn't minified so all logs shipped. → Plaintext/key-ID interpolations removed from log statements. ### 8. Long-press-to-send silently dropped the signature — FIXED `encryptAndSend(cachedPassphrase)` signed only when the cache was warm, so the same message could be encrypted unsigned with no warning. → If a signing key is selected and the cache is cold, send now prompts for the passphrase instead of silently proceeding unsigned. ### 9. A message merely *containing* the PGP armor header was sent in the clear — FIXED The `isEncryptedMessage` check was a bare substring test, so quoted ciphertext plus commentary passed as "already encrypted". → The check is anchored to the trimmed start and requires a matching `-----END PGP MESSAGE-----`. ### 10. Import never verified the passphrase — FIXED An unprotected key (or a mistyped passphrase) was accepted at import and only failed later. → Import now attempts a real unlock with the supplied passphrase and rejects keys with no S2K protection. ### 11. Passphrase cache had no timeout — FIXED It cleared only on screen-off, surviving app/IME switches. → Added a 5-minute idle timeout in addition to the screen-off clear. ### 12. No `FLAG_SECURE` — FIXED Key material and decrypted plaintext were screenshot- and recents-visible. → `FLAG_SECURE` set on the settings activity; decrypted-text copy is marked sensitive on the clipboard. --- ## Low / polish - `listKeys()` now fills in `created` and `algorithm` (was blank in the UI). - Key generation requires a passphrase of at least 8 characters. - Removed the unused `florisboard` git submodule. - Fixed stale README APK links. - (Documented, not changed) the v4 key-ID fold is correct for all key types this app generates/supports; it would only desync for v6 keys, which aren't used. --- ## New feature: encrypted configuration backup & restore Because the signing key changes in this release, v00032 adds a way to move your configuration: - **Export** — Settings → Backup & Restore → Export. Encrypts all secret keys, recipients, and preferences (PGP-symmetric, password) into one file saved via the system file picker. - **Import** — Settings → Backup & Restore → Import. Picks a file, prompts for the password, and restores everything (skipping duplicates). --- ## Signing key migration (one-time) v00032 is signed with a new key, so existing installs can't update in place. 1. Install **v00031** (same signature as v00030, adds backup/restore) and **Export** your configuration. 2. Install **v00032** (uninstall/reinstall, then) and **Import** it. Obtainium and Zapstore will offer v00032 directly; do the v00031 backup first if you have existing keys you want to keep. --- View quoted note →
mleku's avatar
mleku 4 hours ago
At the prompting of a user who has been following #cipherkeys and messaged me using it over signal, gave me a security audit that they did on it using claude opus 5, and i looked over it and applied it. But then i realised, because it changes the app signing, it may cause issues to try and install it, and so you need to uninstall it first. So, to save you from hassle, first download this APK and install it, and run the configuration export https://git.smesh.lol/cipherkeys-releases/raw/cipherkeys-v00031.apk before you let zapstore or obtanium do an update. The update will appear shortly on zapstore and obtanium and will be available to update, but this is a pre-warning that one of the changes is the app signature which may cause issues trying to update it, possibly wiping your configuration. For the new version, you can look at the zapstore to see what changes were made, it was extensive. I will also post this in a reply to this note so you can see it here also.
mleku's avatar
mleku 4 hours ago
# silicon valley output, bishkek burn rate i build working software. i learn anything. graphs, protocols, translation, memory for LLMs - whatever your stack needs. - \$500 signing (one-time, gets set up in kyrgyzstan) - \$300/week (covers ger + goat milk + sim data) - stack: anything i can learn (and i learn fast) #### why so cheap? i live on the steppe. my rent is a yurt, my overhead is food and bandwidth. you don't pay for my city. you pay for my output. need a prototype, a custom tool, or a full system? let's talk. ## contact: - **matrix:** @smeshlol:matrix.org - **signal:** mleku.80 - **simplex:** - **email:** [me@mleku.dev ](mailto:me@mleku.dev) - **git:**
mleku's avatar
mleku 5 hours ago
I have had an axiom bubbling up out of my brain for some decades now. It essentially explains how to evaluate whether something is bullshit or not. Bullshit looks good on the outside, and is empty inside. Truth can look like bullshit, but inside it is hard and solid and correct. The resolution of your understanding of something is critical. Bullshit depends on you looking at it at lower resolution than it actually is. Every layer is an order of complexity. When you leave things out, it is harder to see if there is a false assertion or claim underlying it. What looks good at the first level of consequence, can often hide bad things at the next order of effects, or the next after that. Liars depend on you not looking under the first layer. This is my axiom that is the foundational concept and strategy for how to evaluate bullshit. If you are not willing to think, then good luck to you. Have fun staying a victim. You can't have sovereignty without doing your own research. ## Mleku's axiom: ### zero incoherence = nondeterminism ### the finite chaos = coherence at insufficient resolution appears incoherent deception = incoherence at insufficient resolution appears coherent ### infinity coherence = determinism
mleku's avatar
mleku 8 hours ago
Just made some further improvements to cipherkeys after encountering a pure numeric input field on the O! mobile app (kyrgyz phone/bank that i use to do bank payments to shops and almost everyone in the country uses for p2p payments similar style as lightning invoices, scan and key in amount and pay anyone). So now, on number fields, like phone numbers, it switches to a numeric keypad laid out like a standard extended keyboard, all the numbers, decimal, basic math operators and braces, enter and backspace. On email address inputs (which should also be used for nip05 and lightning addresses - all three of mine are the same - me@mleku.dev ) the , key on the bottom right changes to @ since you don't need , and always need @. I eventually want to add other language layouts too, especially Russian as i will be needing it more and more the longer i am in north/west asia. But i am busy with moxie right now. Gotta damn well finish it so i can start doing a russian translation lattice for iskra and probably will get the smesh wasm nostr client rebuilt and bugfixed.
mleku's avatar
mleku 13 hours ago
# silicon valley output, bishkek burn rate i build working software. i learn anything. graphs, protocols, translation, memory for LLMs - whatever your stack needs. - \$500 signing (one-time, gets set up in kyrgyzstan) - \$300/week (covers ger + goat milk + sim data) - stack: anything i can learn (and i learn fast) #### why so cheap? i live on the steppe. my rent is a yurt, my overhead is food and bandwidth. you don't pay for my city. you pay for my output. need a prototype, a custom tool, or a full system? let's talk. ## contact: - **matrix:** @smeshlol:matrix.org - **signal:** mleku.80 - **simplex:** - **email:** [me@mleku.dev ](mailto:me@mleku.dev) - **git:**
mleku's avatar
mleku 18 hours ago
https://www.zerohedge.com/geopolitical/spanish-beach-stormed-ceuta-chaos-spreads fuck europe, seriously. europe is turning into dystopia so fast. extreme regulations for citizens, and a total blind eye to imports. and quite frankly, in my life i have never encountered such toxic people as north africans. even the syrians are moderately mannered compared to moroccans and algerians and mauritanians. you know the "look at me, now i am the..." meme. that guy. that is typical north african type. and if you don't agree with them, they will beat you. they are thugs and retarded and pile sunni muslim extremism on top of that. there. that's north africa. they think they are doing god's work. and we can thank the USA for funding the psycho imams and militant sunni movements for the spread of it. they literally believe that it is god's will that they will take over europe. I HEARD THIS DIRECTLY FROM THE MOUTHS OF THESE PEOPLE. their criminal enterprise is "Jihad" and holy.
mleku's avatar
mleku yesterday
btw, i understand fully now how monaro does it "privacy" the spend has 12 outputs. only one of them is real. once you spend it, the real one is revealed. otherwise, same as bitcoin with proper pedersen commitments style bulletproofs and mimblewimble kernel proving the total of a transaction's value. the difference is that where it's going to go next is a one in 12 shot. once it's spent, you can chain them together just like bitcoin utxos. haha. hah. really, how rabid are moneros about their privacy and that's what they are so gloating about? literally the growing edge of the utxo set is a little bit private.