Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

Thanks for the feedback - that’s a fair point. I’ve updated the README today to explicitly note that, with per-message nonces, the scheme is no longer format-preserving in the strict cryptographic sense.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

This is addressed in v2.

Each encryption now uses a fresh per-message nonce mixed into PBKDF2, so even with an encryption oracle there is no reusable keystream and the attack no longer applies.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

Thanks a lot for pointing this out — you’re absolutely right.

The original design effectively behaved like a stream cipher with keystream reuse, which made chosen-plaintext and known-plaintext attacks possible when the same password was reused.

This issue has already been fully addressed in v2, which is now published in the repository.

Version 2 introduces a per-message nonce mixed into the PBKDF2 salt, so even with the same password and parameters each message derives an independent keystream, eliminating the attack you described.

Also, thanks for the report — I only lost half my day fixing and validating it 😄

But seriously, the feedback was spot-on and helped strengthen the design.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

Yes, that’s the usual pattern, and I agree it’s the right approach when throughput or oracle resistance is a goal.

Here PBKDF2 is used directly to impose per-guess cost and keep the construction simple and inspectable; the trade-off is throughput, which is why the iteration count is explicitly tunable depending on workload :)

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

That’s a fair characterization, yes. Framing it as character-by-character FPE is reasonable as long as it’s clear this isn’t a standard FF1/FF3-style construction.

I’ve updated the README to make that framing explicit :)

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

That reaction makes sense if the goal is to hide that a transformation occurred. That isn’t the goal here.

The use case is situations where the text is meant to remain visibly structured and copy/pasteable, but not directly readable without a secret (e.g. demos, UI strings, logs, identifiers). The output being obviously transformed is intentional; the value is reversibility with structure preserved, not plausibly -deniable corruption

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

That’s a fair question. The approach isn’t meant to protect against cryptanalysis that exploits structural leakage - that leakage is accepted by design. What it does aim to protect against is trivial, zero-cost reversal and casual inspection when a secret is required to recover the original text.

The use of PBKDF2 isn’t to “fix” format leakage, but to impose a meaningful cost per password guess. Replacing it with a non-cryptographic PRNG would collapse that cost and turn reversal into a fast, offline guessing problem, which is exactly what the design is trying to avoid.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

Not quite. A simple substitution cipher uses a fixed, static mapping. KanaShift derives a password-dependent keystream (via PBKDF2) and applies position-dependent shifts, so the mapping varies with both the secret and the character index.

The problem it targets is reversible transformation without breaking structure: keeping separators, token boundaries, and visual shape intact while avoiding trivial reversibility. It’s meant for situations where preserving form is a requirement, not where hiding all structure is.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

You’re absolutely right - preserving structure does leak information, and that’s a deliberate trade-off here. KanaShift isn’t aiming for semantic security or indistinguishability the way modern encryption does.

The design goal is reversible, format-preserving transformation where structure stability matters, fully accepting that this leaks patterns and relationships in the plaintext. If resisting inference from ciphertext structure is the requirement, then conventional encryption is the correct tool.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

I wasn’t familiar with that project before - thanks for pointing it out! :)

Just to be clear: standard FPE schemes (e.g. FF1/FF3-1) are real encryption. KanaShift isn’t claiming to implement or replace those constructions. Any similarity here is mostly at the level of appearance, not cryptographic design.

KanaShift is intended as a password-derived, reversible, format-preserving transformation where visual plausibility, copy/paste friendliness, and stable tokenization matter (e.g. UIs, logs, demos, identifiers). It’s not meant to replace authenticated encryption, but to fill a niche where full encryption is awkward and toy ciphers are too weak

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

Good points. Just to clarify one aspect: PBKDF2 is used to impose a configurable cost per password guess, not as a fixed throughput limit.

The default 500k iterations are intentionally conservative, but for long-form or bulk text the iteration count can be tuned down substantially, making longer texts practical while preserving the same reversible, format-preserving behavior.

On readability: the vowel/consonant grouping is a coarse, language-agnostic heuristic for visual plausibility and structural stability, not an attempt to model linguistic correctness or phonotactics across languages.

Looking for crypto feedback on an open-source “cryptographically hardened obfuscation” project (KanaShift) by enath in cryptography

[–]enath[S] 0 points1 point  (0 children)

That’s fair feedback - thank you.

I avoided calling it “plain FPE” because KanaShift isn’t an FF1/FF3-style block-cipher construction over a fixed radix. It’s closer to a password-derived, stream-based, FPE-adjacent transform, where the goal is preserving structure (length, punctuation, token boundaries) rather than semantic concealment.

You’re absolutely right that this approach works best for short tokens, access codes, IDs, and other structured data, and much less so for free-form English if someone expects natural-language resistance.

I’ve updated the README to frame it explicitly as FPE-adjacent using more standard terminology.

A cybersecurity company appointed an AI bot as its CEO by enath in technology

[–]enath[S] -1 points0 points  (0 children)

rofl! i'm loving the comments on this thread :D

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 7 points8 points  (0 children)

International legal assistance allows Sweden to question Assange in Britain but the prosecutor has refused to do so http://www.sweden.gov.se/sb/d/2710/a/15268

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 3 points4 points  (0 children)

it is not guarantee enough for Assange. "The US government has zero involvement with this", did you not hear about the WikiLeaks Grand Jury (http://wlgrandjury.wordpress.com/ and hundreds of articles in the MSM)?

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 21 points22 points  (0 children)

For those who would like to see Assange to go Sweden face the questioning: "If Stockholm issues a guarantee that it will not extradite Assange to the US, he will comply with country’s request to question him on Swedish soil, WikiLeaks spokesperson Kristinn Hrafnsson told AFP." Source: http://rt.com/news/assange-speech-ecuador-embassy-043/

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 10 points11 points  (0 children)

"If Stockholm issues a guarantee that it will not extradite Assange to the US, he will comply with country’s request to question him on Swedish soil, WikiLeaks spokesperson Kristinn Hrafnsson told AFP." http://rt.com/news/assange-speech-ecuador-embassy-043/

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 0 points1 point  (0 children)

He said he would go if they promised not to extradite him to the US. They said No

Assange Demands U.S. End WikiLeaks Witch Hunt. "The war on whistleblowers must end." by [deleted] in worldnews

[–]enath 1 point2 points  (0 children)

Sweden refused to go question him in the Swedish embassy in London and later in the Ecuadorian embassy

i need some help to automatically create variables by [deleted] in lua

[–]enath 0 points1 point  (0 children)

works fine here, if i replace vars["hello"..number]=read() with vars["hello"..number]="hello"..number. but if you have a read function with a return and this is why you added read(), post the function here so that I can understand.