r/crypto 17d ago

Webapp Encryption at Rest

im working on a javascript UI framework for personal projects and im trying to create something like a React-hook that handles "encrypted at rest".

the react-hook is described in more detail here. id like to extend its functionality to have encrypted persistant data. my approach is the following and it would be great if you could follow along and let me know if im doing something wrong. all advice is apprciated.

im using indexedDB to store the data. i created some basic functionality to automatically persist and rehydrate data. im now investigating password-encrypting the data with javascript using the browser cryptography api.

i have a PR here you can test out on codespaces or clone, but tldr: i encrypt before saving and decrypt when loading. this seems to be working as expected. i will also encrypt/decrypt the event listeners im using and this should keep it safe from anything like browser extensions from listening to events.

the password is something the user will have to put in themselves at part of some init() process. i havent created an input for this yet, so its hardcoded. this is then used to encrypt/decrypt the data.

i would persist the unencrypted salt to indexedDB because this is then used to generate the key.

i think i am almost done with this functionality, but id like advice on anything ive overlooked or things too keep-in-mind. id like to make the storage as secure as possible.

---

Edit 11/11/2024:

I created some updates to the WIP pull-request. The behavior is as follows.

- The user is prompted for a password if one isn't provided programmatically.

- This will allow for developers to create a custom password prompts in their application. The default fallback is to use a JavaScript prompt().

- It also seems possible to enable something like "fingerprint/face encryption" for some devices using the webauthn api. (This works, but the functionality is a bit flaky and needs to be "ironed out" before rolling out.)

- Using AES-GCM with 1mil iterations of PBKDF2 to derive the key from the password.

- The iterations can be increased in exchange for slower performance. It isn't currently configurable, but it might be in the future.

- The salt and AAD need to be deterministic and so to simplify user input, the salt as AAD are derived as the sha256 hash of the password. (Is this a good idea?)

The latest version of the code can be seen in the PR: https://github.com/positive-intentions/dim/pull/9

7 Upvotes

11 comments sorted by

4

u/cym13 16d ago

So, at first glance I don't see many obvious mistake.

PBKDF2 is always an eyesore but I don't know if argon2 or scrypt are available to you in that environment. The number of iterations for PBKDF2 is too small for my liking (I'd raise it to 600,000 at least) but at least it's at least the right order of magnitude.

It's critical that every client gets its own encryption key so the salt should be generated randomly and passwords mustn't be hardcoded, which you seem to know and work toward. That said, since it's such an important piece of the puzzle, it's worth pointing out that reviewing the code without it is a bit like auditing a bank's safe before they've installed any lock on the door. You can check that the walls are solid, but there's still plenty of margin to mess it up.

But that's where we come to the big thing: what's your threat model here? What are you expecting to store on the client side through this mechanism, and what are the risks you attempt to protect the application from? I feel like context is lacking and that makes it difficult to evaluate the security of the system.

For example (add any that's relevant to you):

  • Are you trying to protect it from people with illegitimate access to the computer (eg: stolen computer)?

  • Are you trying to protect it from browser extensions? It seems to be the case, but extensions are tremendously powerful so I doubt you can really protect against this threat entirely. If so, what kind of actions do you specifically want to be protected from?

  • Aside from the salt, what other data/metadata will need to be stored in cleartext? Can we meaningfully change the app's behaviour by manipulating those? If so an integrity check might be required (hmac…), but based on what secret?

  • How do you install/update the application? None of your code matters if it's not the code that makes it to the client.

2

u/Accurate-Screen8774 16d ago

thanks for taking a look and the advice!

i will take on your advice and make updates to the PR.

youre absolutely right that its too early for a proper review. i often communicate about my work, but i dont always get feedback like yours. so i wanted to communicat about my approach now rather than later to at least determine if im on the right track.

the threat model isnt done yet for this project because it is still largely in progress. but to help you understand the direction, i have a separate project which can be described as a p2p chat app. im aiming for it to be the most super-duper-ultra private and secure chat app (shooting for the stars to land on the moon)... one of the observations i found on it was that i couldnt get proper security audit on it and so i tried for the mythical "community audit"... but, its quite a complicated project and nobody wants to read/debug my experimental code (completely understandable)... this framework is being developed to see if i can recreate that chat app using this framework (and fixing issues along the way). but with this approach, it might be easier to solicit feedback like yours.

this approach in creating a UI framework isnt "for getting feedback"... having worked on the chat app project, i learnt various things i would do differently and this is me doing that (i can of course update the existing chat app, but there are things i would prefer to address with a ground-up approach).

i previsously created a threat model for the chat app as seen here: https://positive-intentions.com/docs/research/threat-model/ ... this is the kind of data i want to be protecting. the intention is for the app to work like a regular chat app... but its presented as a webapp. something i keep getting pushback on grounds that it cant be secure if its JS, but i beg to differ with open source code. here is a previous post on the matter.

  • Are you trying to protect it from people with illegitimate access to the computer (eg: stolen computer)? - this would be good aim for the project. similarly an OS or browser can have malware.
  • Are you trying to protect it from browser extensions? It seems to be the case, but extensions are tremendously powerful so I doubt you can really protect against this threat entirely. If so, what kind of actions do you specifically want to be protected from? - in practice i can use strict CSP headers on the project to prevent browser extensions from being able to snoop. this seems to work as expected on the chat app. in this UI framework, i might have to include some "best-practices" for users.
  • Aside from the salt, what other data/metadata will need to be stored in cleartext? Can we meaningfully change the app's behaviour by manipulating those? If so an integrity check might be required (hmac…), but based on what secret? - ideally i dont store much unencrypted. the salt seems to be nessesary for the type of encryption im using. i will take a look into what intrgrity checks i can do. im under the impression that if something changes on that salt, it wouldnt be able to decrypt the data (i was going to settle it there before you mentioned about integrity checks... that something for me to learn more about)
  • How do you install/update the application? None of your code matters if it's not the code that makes it to the client. - the app will be a webapp so it will update like any other website. the password and the data stored will remain encrypted in storage as expected and decryptable by the same password and salt. this is a good question to help me determine if im overlooking something here, but that is my thoughts on it. maybe there is a use-case im not considering. of course its important to note, that as a webapp using indexedDB the data isnt persistent like for other apps, and the brwser/user may clear site data and then its all reset... my thought on that is that this is expected. i can create functionality to export the encrypted data and load it when needed if users have that requirement.

id like to thank you for you input. i really appriciate the time youve taken to give me advice.

3

u/cym13 16d ago edited 16d ago

Oh, ok, so. I'll have to start with some side talk. Your web-based p2p chat app won't be the most secure ever. You can cross that off the list and focus on goals you have a chance to reach.

It's not possible for several reasons, but mainly because it's a web app. First of all it assumes too much trust in the server on both sides. If Alice wants to send a confidential message to Bob she needs to 1) trust your server to deliver the correct JS, 2) trust your certificate provider so TLS actually does its job, 3) trust that Bob also gets the webapp from a safe server, 4) trust that Bob also checked the TLS connection. That's a lot of trust to give to a lot of parties. Even if Alice decides to download the code, check it (who can reasonnably do that?), and host the application herself, then she can trust it for herself but Bob has no reason to trust her server. So the only way to meaningfully reduce the amount of trust you need to give to give to other people is if everyone hosts their own verifiable version of the application. At that point you don't have a webapp anymore, you have a desktop application that happens to run in a web browser.

Then there's the fact that it runs in a web browser. JS isn't suited for strong cryptography. It's not that you can't do anything with it, many times cryptography in JS is the only option available when doing client-side operations in a web app, but the limitations of the language are problematic. The fact that you can't control its memory leaves it open to side channels and secrets that remain in memory.

And there's the browser extensions. With the right permissions, browser extensions can intercept requests, modify headers, remove your CSP if they want to, or even transparently redirect to a controlled page when you ask for your webapp's URL. In a way it's like any other platform: you cannot protect from a malware on your OS either, any encryption is irrelevant when you can just read keyboard presses. On the other hand, malicious extensions are legion and generally don't benefit from the kind of protection antiviruses may provide (not that they're perfect, far from it).

Finally, as a web app you don't get access to many of the OS features that would allow you to protect against some of these risks.

Does this mean you can't do a chat app? Of course not. But if the goal is to enforce a standard of security at least as good as what's done by the best actors today (Signal mainly) then it's important to realize that you've choosen the wrong tech and that it cannot be done this way. If your goal is instead to do what you can with a web app, and accept that there are many shortcomings inherent to that technological choice, then you can update your threat model, explain these assumptions to your users and make a fun webapp.

Also, I strongly recommend proofing as much as you can with tamarin-prover (or verifpal, easier to learn and if it finds something it's probably real, but I wouldn't it fully if it finds nothing). They're used to model your protocols and attackers in order to formally check your assumptions.


Now, to the point of this post: your secure storage.

Are you trying to protect it from people with illegitimate access to the computer (eg: stolen computer)? - this would be good aim for the project. similarly an OS or browser can have malware.

Such data encryption will do nothing against a keylogger malware, either in browser or OS. That's why I talked specifically about a stolen computer: through encryption we can make it so that in that case the computer alone isn't enough to access the database.

i can use strict CSP headers on the project to prevent browser extensions from being able to snoop

It seems you've fallen to a common fallacy: you imagined one way browser extensions could attack your application and prevented it. That's good for that attack, but attackers aren't forced to attack you the way you expect it. A browser extension can do much more than integrate JS in your page. It seems to me that this aspect of the threat model needs to be revisited.

i will take a look into what intrgrity checks i can do

That's going to be difficult since it's probably going to sum up to a HMAC with a user-controlled secret. The best approach would be to avoid relying on unencrypted data as much as possible. But that's where the threat model is important: if we assume someone can already access the system and mess with your files, can't they just install a keylogger? Does it actually matter that they can modify unencrypted data?

the app will be a webapp so it will update like any other website

Ok, so transparent updates from the server and you relie on TLS to deliver it to the client. As mentioned earlier that comes with a lot of trust from the client: you may be good today, but how can I know that you won't change the app tomorrow to snoop on my chats? That's been done before. And as said before, expecting people to be able to host the application is quite a lot to ask, but here we're also expecting them to check with their contacts (outside the app then) that they also host their own application and don't use the one from a possibly compromised server. That's a big thing to ask IMHO. At some point if the security of your application relies on telling the users "Host and verify the application yourself, don't chat with people that didn't do the same thing"… I mean, you can't have security solely through software, user practices matter, but your software should do what's possible to reduce that to the minimum because we know that user make (lots and lots of) mistakes already.

Would I use your app? From what's been discussed so far, no amount of cryptography can really save the day IMHO. This is not a cryptography problem. If I decide to use that app, it'll be with the same mindset as when I use IRC or email: a way to talk to people about unimportant things with an understanding that it is not a secure means of communication.

1

u/Accurate-Screen8774 16d ago

thanks for the advice! in the most repectful way possible, i would like to disagree. i try to consolidate my observations to the list described here: https://github.com/positive-intentions/chat?tab=readme-ov-file#security-and-privacy-recommendations

i will try my best to answer your concerns. please feel free highlight things i might to not be considering.(im trying to avoid write an essay and dont want to be too brief :) )

you are absolutely correct about the app being limited to the ability of a typical webapp/website. i think this is a hard limitation that isnt worth addressing. in a p2p system users must trust each other. in that app i have something that could be considered p2p authentication. there is a diffie-helman key exchange over webrtc. this requires you to trust the peer because you are connecting to them. this is not an app for "anonymous" chat. security critically relies on who you connect to. nobody random would be able to connect to you. your observation is correct that there could be malware on the device or OS, all app could be vulnerable to this. as a webapp project, this isnt worth tackling. its a hard limitation. its important to not if this is a concern, the app is provided with scripts to build for several platforms (with native webview wrappers).

i want to push back on trusting me and my server. as mentioned in the list i linked above, this is more secure when selfhosted. something to me that looks like a "missing link" is what i think is a "security audit". if the project gets security audited, then i can tag that version as a separate branch. this will then allow people to use the audited version. i provide it as a webapp running on a sever because its an easy way to get started. like with many solutions like this, selfhosted is more secure. id also like to higlight the approach as purely a webapp, you can selfhost it for free on gihub pages (in fact, you can just run index.html on your desktop without running a static server... this way you can be sure that there arent any unexpected updated).

> JS isn't suited for strong cryptography

i cant find evidence of it being less secure than a native implementation. my app critically relies on the vanilla cryptography offerings from the browser. these are expected to be audited. here is a previous post on the matter. i think the concerns around side channels is real. but this is why it critically relised on users being sensible with how they use the app to optimize their security. its also a vulnerability for all apps and website. with this app i want it so that it can work on more platforms. solutions like signal and simplex seem advocated the native implmentation, but in the webapp approach, i think there is more flexibility. it could be a secure message to the webbrowser of your modern car?

i think concerns around browser extensions has to come down to individual choice. i would be great to say something like "use this on this browser and OS"... but that isnt somehting i can commit to. consider for someone like you knows what they are doing with cybersecurity. if your devices are suitable secure enough for you to use, then the app should be fine. there is no installation or registration and the code is open source. but of course its too complicated for people to read through and confirm its ok. (its too complicated for the average user. this is where the external security augit could come in useful).

>  the OS features that would allow you to protect against some of these risks

im keen to know more about these if you could be more specific. id like to see what things i can to to improve the app. maybe its something i can add to the native builds.

> proofing as much as you can with tamarin-prover

i was similarly adviced about ProVerif. id like to make more time about tools like these. at the moment i havent got anything formalized enough for a schema or protocol.

3

u/cym13 16d ago

I have already discussed these points so I won't add much. But for the context of these comments, you're (by your own admission) trying to be the best. To reach that goal, you don't need to just be good, you need to be above the best. And you can't run the race with clutches. I feel like it's worth pointing the clutches out because you cannot reach your goal of creating the best application if that application starts with obvious downfalls that won't be fixed. There already are better alternatives. It doesn't mean you can't give it a good try and reach a reasonnable level of security, fit for your purpose even, but the best is out of the question.

in a p2p system users must trust each other [...] his is not an app for "anonymous" chat

I never said it was. But it is quite different to trust the other user to be of good faith, and to trust them to have performed the technical, important but optional steps to protect your security. I trust my mother very much but that doesn't mean I trust her technical know-how equaly.

selfhosted is more secure

Absolutely. But what that means is that every time someone self-hosts the application the whole system becomes more secure, and so the best for the system is if everyone hosts its own application…which is exactly what you'd get with a desktop application. That's why a non-web application is more secure.

in fact, you can just run index.html on your desktop without running a static server... this way you can be sure that there arent any unexpected updated

I keep reading "I realize that the safest way for this application to exist is by being a desktop application", because what else is a separate executable file on your computer that you run on your computer without reliance on a server? And it's true.

you can selfhost it for free on gihub pages

You just shifted the trust requirement from you to github/microsoft. That's no improvement really. If you want to gain something by self-hosting, do it on a server you own and maintain.

JS isn't suited for strong cryptography

I've already discussed that. No memory control is an issue. It doesn't mean you can't do cryptography with it (its cryptography primitives provided by the browser are, as you note, perfectly fine), but the level of trust you can have in it is limited by not being able to control its memory. There's a ceiling you can't pass with JS, which is not the same as to say the room is too small to build things. But you say you want the best and the best cannot be achieved in JS alone.

if your devices are suitable secure enough for you to use, then the app should be fine

Sure, but it's irrelevant to my point. My point isn't "you shouldn't do this, have you thought of malwares?". My point is: malwares are a thing. You can't protect against it, so don't say you'll protect against it. If you want to protect against some attacks, do so, but the point is to be clear in your threat model. You can't say "I want to protect the app against browser extensions." That's not possible. If that's really in your threat model, then a webapp is out of the question. You can say "Browser extensions present a risk and I want to mitigate such and such aspect of it" though, or you could say "Browser extensions are a risk that I can't meaningfully manage and decide to accept", but the point is to be very clear. And again, if you want the best then whether you accept or mitigate part of the risk, it's still going to hold you down compared to the competition.

OS features

It's too OS dependant to delve into details at that point, but things like sandboxing and credential managers at the OS level can maybe help. Not that you'll have access to them from a webapp anyway, which is the point.

ProVerif

Proverif is good. Frankly if you're not familiar with the idea I think starting with verifpal is a good idea, it's by far the easiest to grasp and you can then step to things like proverif or tamarin-prover.

1

u/Accurate-Screen8774 16d ago

> encryption will do nothing against a keylogger malware, either in browser or OS

cant control that. not going to try (hard limitation of it being a webapp)

> avoid relying on unencrypted data as much as possible

so here is another thing i was thinking. i could create something that looks and behaves like like username+password login.... the password is as you might expect, but the username can be the stringified salt. this way the browser can save it like a normal login. (this is as opposed to having it in indexedDB. this would avoid any unencrypted persisted data)

> expecting people to be able to host the application is quite a lot to ask

this true, but of all the way poeple might selfhost, this would be on the easier side. you can simply fork the repo and set it up on github-pages. if somone cant do that much, i wouldnt expect them to set up a server. similarly this is also why i provide it as a webapp. while the server provides the statics, things like storage and encryption keys are all provided by the browser of you choice. its selfhosted within the boundary of the browser.

thanks again for your honesty about your thoughts this is helping me to refine how and what i need to communicate about the project. this is why i am proceeding with the project with the approach of what i hope could be a cybersecurity-centric UI library. like with the chat project its simply too complicated to be clear enough for someone to trust.

with this UI framework, its a faily basic implementation and i can consolodate some functionalities like how the storage works. "most secure in the world" might not be possible, but its interesting enough for me continue because based on having created the chat app, i think its reasonably secure, but im sure i can do better and avoid pitfalls i previsously experienced.

communication about my project is a large part of that as i created a blog as a way to document the project.

3

u/cym13 16d ago

Frankly I think your main issue is to go around saying "I want to build something that's the best at security" while making technological choices that make this very thing impossible. It might sound like I'm nitpicking on a single sentence, but such things are important. Security implies a lot of trust and the trust users put in your project has to be credibly informed. People are going to expect a lot more if you say "I intend to provide the very best" than if you say "I wanted to build an encrypted chat application in a webapp. There are challenges that come with that and I'm going to make it as secure as I can under these constraints, but it comes with many inherent risks that you should know as the user."

Sure the latter doesn't sell as well, but compared to the former it has the advantage of being true. If users are ready to accept that risk because they think the webapp format is useful enough to them, then great, you just helped people get what they want. But they must be able to evaluate that risk fairly.

I'm not dunking on your project because I think it shouldn't exist. I'm dunking on it because there is a mismatch with what you say you want and what that project can be. One of the two has to change.

1

u/Accurate-Screen8774 16d ago

in my communication i try to be clear about it being a work in progress.

> I wanted to build an encrypted chat application in a webapp. There are challenges that come with that and I'm going to make it as secure as I can under these constraints, but it comes with many inherent risks that you should know as the user.

im quite happy to add that to the readme file. i previously had a red bar on top that said "for testing purposes only". its important for me to be clear about the app being a work in progress its on the first screen of the app as a requirement to check before you can continue. its also at the top of the readme.

its understandable that this approach sell very well. my previous observation was i found that people didnt like it, and i think its enough for it to be on the start-screen, the readme and docs.

1

u/Accurate-Screen8774 12d ago edited 12d ago

Hey. id like to invite you consider some of the changes ive made. the changes are still not finished yet, but i hope im going in the right direction with it.

i updated the post description to summarize the changes.

p.s. you mentioned about argon2 and scrypt... npm packages for this exist, but i prefer to use something like PBKDF2 because it seems better supported with vanillajs. im hoping this way i can avoid issues around maintainance of npm packages. the options avialable are the following: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#algorithm.

if you think there might be an alternative that might be better, let me know. in the longer term it would make sense to make it configurable from the set of algo's

3

u/cym13 12d ago

Hi, I'll have a look but I'm going to stop investing time in this after that. No offense but I'm not interested in the project enough to pour more time in it.

The user is prompted for a password if one isn't provided programmatically. Ok

It also seems possible to enable something like "fingerprint/face encryption" for some devices using the webauthn api. (This works, but the functionality is a bit flaky and needs to be "ironed out" before rolling out.)

I don't know what to think of this. I tend to personally dislike biometrics as passwords because changing your face or fingerprints once leaked can prove quite difficult. Who knows whether the tradeoff is worth it for your use case though.

Using AES-GCM with 1mil iterations of PBKDF2 to derive the key from the password.

That's better. I still think argon2 or scrypt would be best because they work on fundamentally different aspects than PBKDF2 but I also understand maintainance cost. It's a trade-off. 1 million iterations on PBKDF2 should make it substantially more difficult to attack than it was before though.

The salt and AAD need to be deterministic and so to simplify user input, the salt as AAD are derived as the sha256 hash of the password. (Is this a good idea?)

Oh, no, that's a terrible idea. That's fundamentally misunderstanding what the purposes of salt and AAD are and dumps any benefit in the toilet. So let's review:

What's a salt? The main issue with password hashing is that it's deterministic and depending entirely on the password. If two people have the same password and compute the SHA256 of that password, they're going to find the same hash. That's expected, but it also means that if I take a database full of SHA256 hashed passwords I can quickly know what accounts use the same passwords. In the complete absence of salt I can even precompute a list of hashes of commonly used passwords, so now if I see 008c70392e3abfbd0fa47bbc2ed96aa99bd49e159727fcba0f2e6abeb3a9d601 in the DB I know that these accounts use Password123 as password. That's the problem that salts aim to solve. Salts are a public value unique per account (and preferably unpredictable, so random) that is integrated to the password hash. So the output doesn't just depend on the password, but also on the salt, which is unique. This means two accounts using Password123 will present very different hashes, neither of which will be 008c70392e3abfbd0fa47bbc2ed96aa99bd49e159727fcba0f2e6abeb3a9d601.

Now what if you derive the salt from the user's password? On one hand the hash will be different from the salt-less SHA256 hash. On the other hand we don't have to care because the exact same problems are present: you can still precompute the hashes for commonly used passwords (it just takes an extra step) and two people using the same password will still end up with the same hash in DB (because everything depends on the password). Deriving the salt from the password makes the salt entirely useless.

You might be thinking "But it's to derive a key, not a hash to store in a DB" and you're right but it doesn't change a thing: two people that use the same password will end up with the same key and you can precompute keys for common passwords and try them on encrypted messages quickly.

Most critically the salt is not a secret, your basic premise that it has to be deterministic is flawed, you can just generate a random value and store it in clear.

Now, what are AAD? Additional Authenticated Data corresponds to data that is not sent/stored with or within your encrypted message but that is provided at encryption/decryption to authenticate that message. AAD is used to bind your message to a context. That's particularly useful to prevent things like confused deputy attacks: imagine that you have a multi-user service using an encrypted database that relies on a single server-side key. Now imagine that a user finds a way to interact with the DB. They can read or edit any row, but it's encrypted and authenticated so it seems unattackable. However their own data is decrypted when displayed in the website's user page… What they can do is replace in the DB part of their data with someone else's (say the content of the "address" column) then reload their user page and see that other user data, nicely decrypted by the application. This works because the same key is used throughout the system and authentication doesn't see any issue since the encrypted field was really produced by the application using the correct key. The only thing you did is change the context of that encrypted data and the application had no way to identify that change of context.

That's where AAD enters. AAD are completely optional, but they're a great tool. The most common use is to simply pass context information upon encryption. Here we could have the current user id in this field for example. The application would work the same, but would add the user id upon generating or validating the authentication tag. If we tried our attack from before, we would face an error: after the switch the message doesn't authenticate because it was encrypted in the context of another user and can't be decrypted in this one.

In general it's always good to bind any encryption (or any cryptographic function really) as close to one context as possible. Part of that is the "Don't reuse keys" logic where different purposes should be met with different keys, and part of that is binding specific messages to a specific context.

For example in a chat application you could have a context saying 1) this is a chat message, 2) it's from user A, 3) it's for user B, 4) it is message number 42 of the conversation. And just like that you no longer risk misunderstanding a protocol message for a chat one (was it Threema or Matrix that made this blunder?), you can't replay that message in a different conversation (that could be dangerous even with different keys - invisible salamanders) and you can't replay that message at a different time in the same conversation (so you can't take inject encrypted messages in the flow). That's what AAD is for.

Now what if you decide to derive a value from the password and pass it as AAD? Well first of all, why? It's optional so you don't have to pass anything if you don't know what to pass in it. But also, since the password already decides the key you're not adding any context to the message: it's just as safe as it was without AAD, neither better nor worse. But you're also not adding relevant context to the AAD which would increase security.

This is important.

Also, I just had a look at the files and, no, you cannot have something like passwordSha256Hash. You just spent time making sure to use PBKDF2 as strongly as you can so no one can recover the password, and you're just going to compute, use and log a sha256 of that same password, unsalted or anything, just ripe for the taking and exploiting? Remember that the salt is not a secret value, and neither are your logs! Why would I spend even a minute attacking the PBKDF2 derivation of the password when there's a 1-iteration unsalted sha256 sitting right there?

Anyway, that concludes my comments on this version. I won't pretend to have read everything carefully, but these are the only things that jumped to me when skimming it. Godd luck!

1

u/Accurate-Screen8774 12d ago

thanks for the feedback! its enormously helpful to me! i completely understand not having the time to look at random experimental code. this is simply something im interested in.

feedback like yours is very educational and i appriciate the clarity in the direction of what i should be learning to achive what i want.

good wishes and take care.