AES256 password and iv, the right way - node.js

I want to create and manage user sessions with AES256 encrypted tokens.
I am using node's crypto library and followed this stackoverflow question.
I am using this to create session token that will be sent to frontend and stored in the backend for verification purpose and the data is stringified JSON.
Here I see two things one is password and other is iv.
so two questions,
Is the iv is safe to sent to frontend (iv + "." + encData)?
How should the password be generated? How about a SHA256 of (e.g. user's password that I store in db at signup)
This way I will be using a different password for each user. Is this approach correct?
P.S. Both of the answers below helped a lot, If you are here, do read all the comments and attached So question and the linked articles.

Let's keep to the question at hand:
Is the iv is safe to sent to frontend (iv + "." + encData)?
Well, yes. The IV may be public knowledge; as long as it is unique and - in the case of CBC mode encryption - random then this is fine. Of course, the IV and encData should be suitably encoded, for instance using hex (as in the linked answer) or base 64. This is not often done as the IV is always 16 bytes for AES, so it is easy to simply prefix the binary IV to the encData instead.
Beware of hackers changing the input; if the dot or colon is removed then you may have just an array of one element and accessing the ciphertext may result in an error or the decryption of empty data.
How should the password be generated? How about a SHA256 of (e.g. user's password that I store in db at signup)
No, you should use a password hash for that; SHA-256 is a cryptographically secure hash but not a password hash such as PBKDF2, bcrypt, scrypt or Argon2. And if you want to store something in the DB, then please do not let that be the AES secret key generated from the password.
This does not in any way invalidate any of the concerns in the answer of TheGreatContini. This is not security advice, just the cryptography related advice you asked for.

You may want AES encryption, but encryption is not what you need! For the security of your application, message integrity is more important than encryption.
Encryption does not generally provide message integrity (see section 7 of Top 10 Developer Crypto Mistakes) unless you specifically use a mode of operation that provides it (such as GCM mode). Therefore, the solution you are designing in inherently wrong. More info in footnote (!) below.
Understand what you need -- message integrity + encryption, or message integrity only. If it is message integrity only, then use HMAC.
Another thing you need to understand is that functions like AES and HMAC do not use passwords, instead they use cryptographic keys. See section 6 of Top 10 Developer Crypto Mistakes.
It is not clear whether your question on IV matters, given that your approach is wrong, but to answer it anyway, the IV does not need to be secret. See section 2 of Top 10 Developer Crypto Mistakes.
I generally agree with the comments above: use JWT the way it was meant to be used rather than trying to build your own solution. JWT has a claim reserved for expiration, so there is no reason not to.
footnote (!): If you want to see how confusion between message integrity and encryption gets abused, you can try this exercise from Pentester Labs (unfortunately it requires a subscription, but it is cheap). Granted that this is for ECB mode, a similar concept can work for CBC mode.

Related

Can salted passwords be reversed?

I have just pressed 'forgot password' on hosting24.com, only to have my password emailed to me in plain text (see image below). I contacted their technical support to question this and they have told me:
We are using Salt encryption on our website, passwords are not stored
in plain text. Please let us know if you have any concerns regarding
the security of your data.
The way I understand it, is that once a password is 'salted' it cannot be reversed back to plain text. I am also very concerned, considering their partner company 000webhosting was victim of a massive hacking incident recently, which exposed that their security was sub-par.
Thanks.
EDIT:
After a few heated emails I finally got this response:
Our passwords are encrypted with a secure encryption method in the
database. Although we do have a decryption method in place (that is
used to prevent fraud), all this is going to change as we are
re-designing the project and updating the code to adhere to new age
standards. We are sorry to have let you down on this one.
Please contact us with any additional questions. Happy holidays!
'New age'. Amazing.
EDIT:
I sent the website this link to prove a point, so I anticipate a load of down votes from their tech support.
Salted hashed passwords are not directly reversible—that's the point of hashing. However one can always try to recover them through brute force, trying all possible/likely passwords to see if the hash matches.
How expensive that is to do depends on the strength of the hash used, but you would never build a system that stores and decrypts passwords that way. If they said they were storing only salted hashes, and still were able to send you the password you originally set yourself, they're clearly lying.
They don't mention hashing though:
We are using Salt encryption on our website, passwords are not stored in plain text.
“Salt encryption” isn't a thing, but let's be as generous here as we can.
It is possible they mean they're using reversible encryption with some randomised element (variable IV, or extra data in the encrypted message) which would ensure two passwords don't get matching encrypted versions (ie the same purpose as the ‘salt’ in a hashing operation).
It's also conceivable that there could be some valid reason why they need reversible passwords, for example if they need to use the passwords to authenticate to another separate system. It's possible to build reasonable systems with reversible passwords, but compared to Good Old Bcrypt it's a whole lot more effort to manage this way (eg keys on the application server; wide-ranging internal policies to manage that; HSMs; and watertight code auditing).
Let's say we accept that this is what they've done and they've implemented it solidly (which is highly doubtful—much more likely they've got plaintext passwords or a hacked-up and vulnerable AES). Even then, they've then blown it by sending you the reversed password in a mail over the unencrypted public SMTP infrastructure.
There are things you can do to mitigate the untrustworthiness of the mail channel, such as sending a single-use token or temporary password that requires a new password to be set afterwards. But there is never a good reason to send an existing password, that will continue to work on the target site and which you might have used to secure other services. User-set passwords should never touch SMTP.
No, they can't without astronomical computing power. I'd bet large sums of money that they have a second database of plaintext passwords.

How to have my deployed application securely encrypt a password and then decrypt it later for automation use

This question has been answered before but the key difference may be that I want to be able to decrypt the password later on and that this is for a deployed application where someone could get a handle on the code assemblies (as opposed to a website behind a firewall)
Basically, I want my application, when deployed, to accept a user password. I want to store that user password somewhere (encrypted) and then decrypt it later for use in an automation routine.
I'll make a few assumptions to simplify things. You can assume that the password in memory is secure (while it is in memory) and that a strong hasing algorithm (feel free to name the best options) is sufficient. Even so, what would prevent someone from reflecting my code and finding the hash key or technique i'm using to decrypt the password (would i even store the hashkey in the code?). I could obfuscate but my understanding is that it is still possible to read. Also, note that one way encryption is not sufficient here. I need to decrypt and use the password later on. Any ideas?
To directly answer the question, you're looking for asymmetric encryption (not hashing which is a one-way process) if you want to encrypt then decrypt your data. The OWASP Top 10 on Insecure Cryptographic Storage is a good jumping off point to learn more about this.
Now to indirectly answer your question, don't do this! Passwords should be stored with a strong cryptographic hash function including a random salt (you'll see this mentioned in the OWASP link as well). If you're trying to return password ciphertext to plain text text then authenticate to other services whilst impersonating someone else, you're missing the root cause of your problem. You've not provided much info on this but it seems the question you should be asking is how you (securely) go about identity impersonation and authentication to a downstream service.

Can I use PBKDF2 to generate an AES256 key to encrypt and implicitly authenticate?

I have 2 devices and I want to set up a secure communication channel between them. The only shared secret is a (7- to 20- character ASCII) passphrase. If I use PBKDF2 (from RFC 2898) with a common salt, iterations, and passphrase to generate an AES256-CBC key and IV on both sides, I think I can authenticate the user and provide an encrypted channel all in one step. Is that true, or is there some reason why I've only seen people use PBKDF2 to verify passwords?
My reasoning is that both sides need to know the passphrase to generate the same key and IV. So if device B can decrypt data from device A, they both have demonstrated that they have the same passphrase.
PBKDF2 is a fine way to generate a common key from a shared secret (you should not be generating the IV in such a way though - the IV should be random, and sent alongside the ciphertext).
However, CBC is not an authenticating cipher mode. This is because an attacker can take an encrypted message and make predictable modifications to it, without needing to be able to read the message or know the key. Such attacks have broken real world systems in the past.
You can use an authenticating cipher mode, like Galois Counter Mode (GCM) instead of CBC.
An alternative is Encrypt-Then-MAC. Use PBKDF2 with two different salts to generate two different keys - first the data is encrypted using CBC with the first key, and then a HMAC is calculated over the ciphertext using the second key.
You will also need to use single-use-nonces to prevent replay attacks.
In general, you wouldn't be able to authenticate a message using a cipher, because the message could be anything. However, if the message conforms to some specified format, I suppose it's reasonable to assume the ciphertext must have been produced with the shared key—with longer messages in more complex formats giving better assurance. For example, the padding in a block cipher can serve as a weak authentication.
For better security, compute a MAC using the shared secret and send that with the ciphertext.
While PBKDF2 can be used to produce an IV, it can only do so for a single message. In most cases it's better to select a random IV and send it with the ciphertext.
PBKDF2 does not "verify passwords". It generates keys from passwords.
To verify a password, normally you have a thing that gets encrypted with a key. The key is generated from the original password, via PBKDF2. Then the cryptotext is saved.
When you want to check whether the user-entered text matches the password, generate the key from the password candidate using PBKDF2, then try to decrypt the saved cryptotext. If the decryption works, then you have a match.
Normally, though, you would not use the password-based key as a session key.
So, NO, you normally would not protect the secure channel with the password-based key.
caf's answer is good. I'd just like to add that you're trying to implement crypto, and even for trained experts that's generally a bad idea. Using the highest-level library you can is much safe.

Symmetric Key to Asymmetric key handoff

I'm not a cryptography expert, I actually only have a little bit of experience using it at all. Anyways, the time has come where one of my applications demands that I have some encryption set up. Please note, the program won't be managing anything super critical that will be able to cause a lot of damage.
Anyways, I was just trying to see if this scheme that I'm using is common and if there are flaws (of which there may be completely stupid & horribly flawed design, that's why I'm asking).
Ok, I have a client -> server communication. The Client I can hard code in the public portion of a 2048-bit RSA key. When the client wants to initiate a secure connection, he sends his username, md5 hash of his password, and a hash of a random UUID, all of which has been encrypted against the server's Public Key. The server receives the information and decrypts using its private key. Checks the database to see if his login + pass work & if they do, create a new entry in the "Sessions" table in the DB. This includes a SessionID, UID (user ID), and the UUID hash. Using the corresponding session ID's UUID as the keyphrase, the server will then send back a message that has the Blowfish encrypted word "Success!" + a random UUID (this message is Digitally Signed so we can determine if it came from the server or not). From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID's blowfish secret (stored encrypted in the DB) as the key to encrypt / decrypt.
Specifically, I am curious as to whether this system "should work" or if anyone notices that it's glaringly obvious that a vulnerability exists, such as MITM.
Issues I can see off the top of my head (although you have left out most of the details, which is where the devil famously resides):
If you're using a UUID generator rather than a real cryptographic RNG, it likely has insufficient entropy. Don't discount this - in the real world, the favourite way of covertly weakening an encryption system has been to weaken the RNG;
Your initial RSA encryption sounds like it is susceptible to a small-exponent attack, and potentially other creative attacks. There's too much structure there to be comfortable;
It sounds like there's numerous opportunities for replay attacks;
What block cipher mode are you using with Blowfish?
I recommend using TLS/SSL - it's had a lot more friendly eyes looking at it for a lot longer than anything you build yourself ever will.
Just use SSL or DTLS, IKEv2, HIP, EAP or some suitable standard protocol. Don't try to invent your own crypto protocols, nobody has enough expertise to do this on their own. Your protocol doesn't have nearly enough entropy in it, so far as I can see, so your resulting keys will be pretty weak.
From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID as the key to encrypt / decrypt.
If you're sending the session id in plaintext, and using it as the encryption key, how is that secure?
I see no reason why you can't use standard SSL authentication and let the library implementer worry about the handshaking.

For sending passwords over the wire, which is more secure: Diffie-Hellman/AES or RSA? (It bothers me that AES doesn't obscure password length)

I was given advice that I am suspicious about so I'm looking for support here to go back and challenge the advice.
I was advised to use Diffie-Hellman to get both sides to agree on a secret key, use the secret key to generate an AES key, and then use AES to encrypt/decrypt passwords that are being transmitted. Pretty much like the sample code here
When using this scheme, the length of the encrypted password is the same as the length of the unencrypted password. Should I be worried about this?
Before, I was using RSA, encrypting the passwords with the receiver's public key. This was resulting in an encrypted length of 256 no matter what the password length. Isn't that better?
You can just pad to whatever length with any data. It doesn't have to be random. As long as it's all encrypted. I think though that is the least of your worries.
Note if you use Diffie-Hellman you still need to authenticate the parameters sent, which you probably need to do with RSA.
The alternatives are:
Use RSA to exchange an encrypted secret key that you then use to encrypt your data.
Use Diffie-Hellman to exchange a secret key and then use RSA to sign values sent to authenticate the transaction.
If you do all this, then you have to also worry about whether exchanges have been replayed to make you reuse keys etc.
To be honest if you need to ask this question then you probably are not qualified to write a crypto protocol. They are extremely hard to get right and not for the faint hearted.
Suggest you use SSL/TLS for your exchange if you need to stream a lot of data. PGP/PKCS#7 if you just need to send a single message.
First off: Don't invent your own authentication protocol. Period. If you do, you WILL get it wrong even if you're using strong encryption. There are a number of existing well documented authentication protocols that have been vetted by cryptographers and thus are thought to be secure. Don't be tempted to "simplify" them, they've already been simplified.
Second: IMHO you should never send passwords on the wire for authentication (I'm not aware of any authentication protocol which does, including the hideously insecure NTLMv1 protocol)[1].
If you're dead set on going down the "roll my own authentication scheme" path, here's how I'd make the scheme you described above more secure (Caveat: I'm not a cryptographer - I believe that there are serious weaknesses in what I'm describing here):
Instead of sending the password directly, send a one-way-function (also known as a OWF, often implemented as a cryptographic hash like SHA256 or stronger) of the password.
In other words, have the server send the client a salt value, add the salt to the password, compute the OWF of the password+salt value and send the OWF result to the server. On the server, add the salt to the password and also perform the OWF calculation. If the results are the same, the password is valid, if they're not it's invalid.
And finally have whatever you do reviewed by a real cryptographer. They will find problems in your implementation and you're going to have to fix them. They're likely to suggest that you abandon your effort in favor of an existing published protocol.
[1] AFAIK, the only time you should send the password on the wire is when you're changing the password and even then, you should pad the length to a multiple of the block size (include the length in the cybertext so that when you decrypt it you can distinguish between the password and the padding).
If you can help it, don't send passwords over the wire at all. Instead, use a scheme like SRP, which authenticates both parties with one password.

Resources