
r/crypto

OTRv4+ post-quantum OTR messaging over Tor/I2P IRC, Rust double ratchet, ML-DSA-87/ML-KEM-1024, 313 test suite, v10.5.5 security hardening. Working prototype
​
I've been building an extended OTR implementation for IRC that goes beyond the OTRv4 spec draft, targeting high-threat privacy scenarios like Tor hidden services and I2P eepsites. Just pushed v10.5.5 with a significant Rust core security hardening pass. Wanted to share it here because the crypto design decisions are the interesting part and I'd genuinely like feedback on them.
GitHub: https://github.com/muc111/OTRv4Plus
What it actually does cryptographically
The core ratchet is a Rust implementation (zeroize on drop via the zeroize crate) with a PyO3 binding layer. The key exchange uses X448 for the DH ratchet and ML-KEM-1024 (NIST FIPS 203) for the brace key, so every ratchet epoch is hybrid classical/post-quantum. The brace key rotates via KDF SHAKE-256 on each epoch, which means a quantum attacker harvesting ciphertexts today can't retroactively decrypt past epochs even if they break X448 later.
Identity signatures use ML-DSA-87 (NIST FIPS 204) implemented through a C extension that calls into the OpenSSL EVP layer for the actual CRYSTALS operations. I didn't roll my own lattice arithmetic, just the binding code and the OTR DAKE integration. Public key bytes are 2592, signatures are 4627 bytes per FIPS 204.
The SMP implementation follows the OTRv4 spec section 4.6. Standard Boudot/Jacobi ZK proof over a 3072-bit safe-prime group, but I added session binding so the hashed secret is KDF(SHAKE-256, secret || session_id || fingerprint_alice || fingerprint_bob). This prevents cross-session replay where an attacker captures SMP transcripts from one session and replays them in a different context.
The DAKE uses the ring signature construction from the OTRv4 draft for deniability. You get auth without a PKI trail.
v10.5.5 security hardening (latest commit)
This was an audit pass on the Rust double ratchet core. Fixed several things that were bugging me:
· RNG: Switched from rand::random() to OsRng with fill_bytes(). The old approach wasn't guaranteed cryptographically secure across all target platforms and I don't know why I used it in the first place.
· KDF forward secrecy: Message encryption keys now derive from the next chain key rather than the current one. Previously a compromise of the current chain key could decrypt the current message. Now it can't.
· Hybrid key composition: The root ratchet KDF now domain separates DH and PQ contributions using distinct usage IDs (ROOT_DH and ROOT_PQ) before combining. Previously they were concatenated raw which felt sloppy and could allow cross-protocol confusion.
· DoS bounds: Added explicit bounds checks on ratchet skip loops. An attacker could previously trigger a near unbounded chain key derivation loop. Now capped at MAX_SKIP = 1000.
· Replay cache: Switched from linear VecDeque scan to HashSet plus VecDeque for O(1) replay lookup. Previously an attacker could degrade performance by forcing linear scans over a full cache.
Test suite now passes 313 tests including a new adversarial security suite that specifically targets each of these issues to prevent regression. Caught several of these during testing which was satisfying.
Seven CVEs patched in earlier releases
These were mostly implementation bugs rather than spec issues:
· Timing side channel in the SMP proof verification (non constant time modular exponentiation, replaced with Montgomery ladder via OpenSSL BN_mod_exp_mont_consttime)
· MAC key reveal list wasn't being zeroed after transmission (forward secrecy leak)
· Fragment reassembly buffer had no per sender ceiling, trivial DoS
· Session expiry check happened after key material was loaded rather than before
· SOCKS5 proxy hostname resolution was happening locally not at the proxy (.onion addresses were being passed to the OS resolver before Tor saw them)
· Two others in the key derivation path.
What I'd actually like feedback on
The brace key rotation. I'm using kdf_1(BRACE_KEY_ROTATE, old_brace_key || KEM_ss, 32) where kdf_1 is SHAKE-256 with a usage ID prefix. Is there a cleaner way to handle the hybrid KEM forward secrecy contribution without coupling the brace key state to the ratchet epoch counter?
The SMP session binding. I'm not aware of this being in the OTRv4 spec draft, I added it myself. Has anyone seen a formal analysis of whether stock OTRv4 SMP is vulnerable to cross session attacks, or am I defending against a threat that doesn't exist in practice?
ML-DSA-87 key sizes are large for IRC (2592 byte public keys in DAKE messages). Anyone dealt with this in practice in constrained message size protocols? Feels heavy but I don't see a way around it.
The hybrid KDF domain separation approach in v10.5.5 using separate usage IDs for DH and PQ contributions then concatenating. Is this the right pattern or should I be using a proper KDF combiner like HKDF with info strings? I went with what felt clean but open to being wrong here.
Disclosure (subreddit rule)
Claude AI assistance throughout this project I just could not have achieved this working prototype took 13+ Months so far still working on improvements would love fresh eyes on it fine bugs etc.
Thanks!
We beat Google’s zero-knowledge proof of quantum cryptanalysis
blog.trailofbits.comWe’ve published the cryptographic architecture behind City of Hats.
We’ve been working on a secure messaging protocol and recently made the cryptographic design public for review.
The system uses:
– Double Ratchet (Signal-style)
– Hybrid key exchange (X25519 + ML-KEM-768)
– Encrypted headers and metadata padding
– Sender keys for group messaging
We’re exploring an identity model that avoids phone numbers/emails and instead uses context-specific identifiers.
We’ve documented:
– Protocol details
– Key exchange design
– Threat model (including limitations)
We have not completed a third-party audit yet.
I’m interested in feedback from people here on:
– the hybrid PQ approach (ML-KEM-768 integration)
– identity abstraction vs traditional accounts
– any obvious weaknesses or design concerns
Happy to share details if useful.
Question About Breaking Encrypted Files
Good morning everyone,
A bit of a novice question here but hope you will be able to give me some insights.
Using VeraCrypt I mount an *.HC file as a drive on my computer. This drive is encrypted as it holds all my sensitive personal files. I also have a few Word documents on my computer that are encrypted, again as they contain sensitive personal info.
I have a regular schedule of backing up my computer, including these encrypted files to a RAID Array. The result of this is that there are multiple copies of the *.HC file and Word files on the RAID Array. Because each of these copies was made on a different day there is almost always changes in these files (hence of course the reason to back up daily!).
On the assumption that the individual *.HC and Word files are well encrypted in all reasonable ways, my question is:
Can the differences in the various versions of the same encrypted file be used to crack the encryption. Or to put it another way, if someone had 10+ versions of the same encrypted file, with each version having small editing differences between saving them, is there some process of subtractive differentiation that could be used to crack the file? (I hope this is clear).
EDIT to add, that a Word file would get longer as data is added but a *.HC file container would not - would this make any difference?
Sorry if this is too basic of a question but I can not find a good answer online and the way I back-up my files got me thinking of this.
Thanks :)
Data in Use Protection: How MPC Keeps Inputs Hidden from the Cloud - Stoffel - MPC Made Simple
stoffelmpc.comA Cryptography Engineer’s Perspective on Quantum Computing Timelines
words.filippo.ioBitsliced first-order masked AES-128 decryption in Cortex-M0 assembly — how many traces to break it?
Wrote this from scratch for a university smart card lab course — couldn't find any usable reference implementation of bitsliced first-order masked AES in assembly, so I had to write one.
Key details:
- Platform: STM32F051 (Cortex-M0, 8 MHz)
- 26,801 cycles
- Bitsliced representation: 16-bit per bit-plane
- S-box: Boyar-Peralta depth-16 circuit
- Masking: first-order Boolean masking with ISW multiplication
Evaluation so far:
- Fixed-vs-Random TVLA (5,000 traces): passes for all intermediate rounds, expected endpoint leakage at unmask boundary only
- CPA (5,000 traces, single-bit): no key recovered
The honest question: does it hold up at larger trace counts, or did I miss something? Would love to see someone actually run a second-order attack on it and report back.
Repo: https://github.com/Changyin-4B4/Masked-AES-Decryption-CortexM0
Did we lose the weekly and monthly automod posts again?
They went dark 5 and 11 months back.
This subreddit is now about Quantum Cryptography
In order to keep up with quantum leaps in a technology which is about to leave the lab at the rate of graphene, a change in phase is necessary and we will need to align with the virtual sea of change with full charge.
If it makes your head spin then won't worry, if you're not a physicist then the complexity is only imaginary. All you need is to ensure physical integrity and deliver a confirmation secret by courier and you're all good.
Moving forwards with invincible technology like quantum key distribution will finally break out of the cat and mouse game and leave adversaries behind, all while enabling unparalleled new business models.
This is not a bit. We're quantum, this is a qubit.
It is possible to use the Ueli Maurer s Diffie Hellman reduction to transfer the discrete logarithm problem from an elliptic curve to a finite field?
The original paper ("Towards the equivalence of breaking the Diffie-Hellman protocol and computing discrete logarithms") solves the discrete logarithm problem using a Diffie-Hellman oracle and auxiliary groups. It also transfers the problem from a finite field to solving the discrete logarithm on an elliptic curve. It was since extended for transferring the problem from an elliptic curve to a different elliptic curve which isn't isomorphic to the original.
Would it be possible to perform the reverse operation? That is, from the elliptic curve, to transfer the problem to a finite field, and possibly do it to an additive group?
Of course, the MOV attack already allows that, but the interest here would be to use the oracle in order to bypass the embedding degree restrictions.
If possible, what would be the exact steps to perform it?
Mongoose: Preauth RCE and mTLS Bypass on Millions of Devices
evilsocket.netPGP Tools: A zero-permission Chrome extension using WebAuthn PRF for PGP key management
I built Chrome extension for PGP and I think the cryptographic approach is interesting enough to share here.
The extension uses WebAuthn PRF to derive a master key from a passkey, which encrypts/decrypts the user's PGP private keys and contacts at rest. No passwords if you don't want them, no key files - the passkey handles both authentication and key derivation in one step. As far as I know, nobody else is doing PGP key management this way, especially not on the Chrome Web Store.
PGP operations use SequoiaPGP compiled to WASM with the Zeroize crate. The reason for keeping everything in WASM rather than JS where possible is that JS gives you zero guarantees about when memory gets freed, so private key material can just hang around in the GC. WASM with Zeroize gives explicit control over that.
The extension also requires zero browser permissions. No content scripts, no host permissions, nothing. So even if there was a vulnerability in the extension itself, the blast radius is significantly reduced - there's no ambient authority to abuse. Most other PGP extensions on the store request a bunch of permissions that massively expand their attack surface.
The main thing this doesn't protect against is a fully compromised browser process - if someone has code execution in your browser, it's game over regardless. But short of that, you get convenient PGP encryption/decryption/signing/verification without trusting a server, without exposing keys to garbage collection, and without granting unnecessary permissions.
I should also point out that if you're using the CWS install, you'd have to trust me not to bake in some fetch for the decrypted content - although you can build and install it from the source (which does mean there's no integrity checks iirc). There's no great solution to this, but if anyone has ideas here then let me know!
Why did I build it? Because I wanted it. Most of my PGP usage is encrypting vulnerability reports for coordinated disclosure via email, and I got tired of context-switching to the CLI every time. I looked at what was on the Chrome Web Store and nothing hit the combo of zero permissions, passkey-based key management, open source, and good UX - so I made it.
Feedback on the crypto approach is very welcome, especially around the PRF key derivation. Happy to answer questions!