VB.NET Encryption using a password - vb.net

I have a desktop application where the user has a library of encrypted ZIP files. The configuration file holds the master password to decrypt these ZIPs. The idea is that the user enters the program password they chose when they installed the application to open the program and that password is used to decrypt the master password stored in the configuration file.
The main point of all of this security is that even if someone had access to the hard disk and user's Windows account, they still can't get inside the ZIP files without their password, ideally.
To validate the program password the user typed in I'm using the C# hashing code (converted to VB) from here (at the bottom of the page):
http://crackstation.net/hashing-security.htm
So far so good. We're only storing a hash of the program password, so a hacker couldn't read it by looking at the config file.
Now, I'm trying to implement encryption as found here:
http://msdn.microsoft.com/en-us/library/yx129kfs.aspx
Actual Question:
So which of the following gets stored as plain text in the config file to be used to decrypt the ZIP master password at runtime with the program password the user entered?
The salt used to generate the encryption key (can this be the same as
the salt used to hash the password as above?)
The initialization vector (IV)?
The encryption key? (Probably not...) (k1 in MS's example)
The decryption key? (k2 in MS's example)
In MS's example, they've got the encryption and decryption all jumbled up together... I've got a lot of pieces but I don't know how to put them together...
Update
I've read that AES encryption is more secure than the Triple DES encryption MS is using in their example above. Seeing that we're using AES on the zip files, it would be nice to use AES for the ZIP file password too.
So, how can I combine this AES example:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider.aspx#Y2300
With PBKDF2 to generate the encryption key?

You need to store the salt and iteration count for the PBKDF function (which must not be the same salt used to hash the password).
The key would be the result of PBKDF, which, for a given salt and iteration count, is fixed.
You also need to store the IV.
If you want to, you can use a (PBKDF) hash of the password using a third (stored) salt as the IV.

Related

How to store encryption key?

I look out many password managers like keeper, 1password, secret-in and I am following secret-in password manager to create my own project and trying to add same features, but got stuck at storing the data of users like his/her secrets, payment secrets in encrypted form. I read encryption model of keeper here but still didn't understand. Where to store a server side encryption key?
I have some data that is symmetrically encrypted with a single key in my database. Rather than hard coding it into my code, I am looking for a safer way to store the encryption key. Where can I safely store it?
The approach here is quite simple.
You only send encrypted data to the server for storage/backup.
The encrypted data received doesn't come with a key.
You need to ensure all encryption and decryption occurs locally on the users device. Thus the user needs to supply the key.
Users aren't good at providing high quality key material, so instead, require the user to provide a password, take that password and pass it through a hash-based key derivation function with parameters that make the function slow (high ops, high mem requirements). An algorithm like pbkdf2 with a strong PRF like HMAC-SHA-2 should be sufficient.
Update:
To answer your specific questions, you need to perform the following steps, you will need to use a cryptographic library that supports key derivation from password and symmetric encryption, like libsodium.
request password from user on first use
run this password through key derivation to derive a key from it: https://libsodium.gitbook.io/doc/key_derivation
execute encryption of user data with key: https://libsodium.gitbook.io/doc/secret-key_cryptography
destroy the key and send data to server for backup

how do password protected files work?

I was looking at an app on blackberry app world to create pdf files and that app claims to be able to password protect the files. How does one password protect a file. Isn't the code to read the file available, thus the password will be useless if the program decides not to check the password?
In addition to the other answers (which focus on encryption of arbitrary files) here an answer focusing on encryption of PDFs which was the use case initially startling the OP:
The PDF standard (ISO 32000-1) describes in section 7.6 how PDFs shall be encrypted in a manner that keeps the file structure of a PDF while hiding the content. PDFs are built from numerous objects (numbers, strings, arrays, dictionaries, streams, references, ...) and the mechanism described by the specification essentially only encrypts strings and stream contents.
Just like in the generic case described e.g. by #Mark, these encrypted string and stream contents are merely a bunch of random-looking data and have to be decrypted before the PDF can be displayed, but the remaining objects are unencrypted allowing PDF viewers and editors to recognize the file as a PDF.
Furthermore the PDF specification allows for two basic encryption types, by
a user password which anyone has to enter who wants to use the PDF in any way, and
an owner password which only needs to be entered for a configurable set of uses of a PDF (e.g. printing or editing) but not for merely viewing it.
Encryption using the latter kind of password obviously can be circumvented: After all, if you can view the PDF, you can extract all the data and do essentially what you want with unless your software co-operates with the scheme and forbids you to. And, obviously, not all software does co-operate.
Essentially the owner password mechanism stores a value in the PDF derived from the password which is sufficient to decrypt the encrypted data but does not allow for easy calculation of the original password.
Assuming the app is competently written, the .pdf file is encrypted using the password to derive the encryption key -- that is, the file is not, properly speaking, a .pdf file until it gets decrypted. Before that, the file is merely a bunch of random-looking data, and the program does not know what the decryption key is until you enter the password.
If done correctly a password protected file will be encrypted with an algorithm that needs the original password to undo the encryption. The password is used to initialize the encryption/decryption process and is not stored in the file. If you give the wrong password the decryption will not work and there is no way for the program to know the correct decryption key (except doing a brute force attack).

how to store a password in webapp that needs to be passed in plain text to a third party?

I have a simple webapp which users login to access to a third party API that also require their personal credential in plain text username and password (no OAuth or anything). What's a proper, safe-ish, and straightforward way to store these third-party passwords so I can decrypt them to plain text when needed and minimise leakage of these passwords?
I'm thinking of just hardcoding GPG keys in to encrypt in webapp for storage and decrypt from another machine behind firewall when needed.
I don't think this is a GPG-specific problem. You could think of a scheme like the following (no need for public key crypto):
Generate a random password to encrypt the plaintext credentials you want to protect
Derive a key to protect this random password from the user's password
Encrypt the password from step 1 with the password from step 2
Now you can access the protected credentials after the user has logged in (since you know the password the user entered). When the user changes his password, you only have to re-encrypt the key from step 1 (in case you use this key in multiple places; so you can't miss one).
For step 2, you should use some (slow) key derivation function like PBKDF2. This makes sure that in case of a security breach, a simple dictionary attack on the encrypted credentials is not possible.

VB.NET: Password encryption

What's the simplest way to upgrade a VB.NET site to using encrypted passwords? Are there easy to use encryption algorithms built in to System.UI?
My site is using plain text password storage, and it will soon be going to a public server at godaddy from a private one on the local network. I'm going to have to start adding in encryption algorithms to all the password parsing functions, and it would be nice if I could just set a SALT key in the web.config file and Encrypt(password) or something like that.
Not in System.UI but definitely in System.Security.Cryptography:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx
There are definitely standard "good practices" you'll want to follow. No point in re-inventing the wheel, especially when it comes to password storage. There are a lot of resources for that, and they're better at it than I am :)
Generate a salt for each user and store it in the database. Then hash the users incoming plain text password, add the salt to it and hash it again. For extra security, hash the password at the client before posting back to your server. Once you have the posted hash, you can add the salt to it and hash it again then store that value as the users password. This basically ensures that no one, even if they have access to your database can easily get to the users passwords.
This is the simplest way and all that is required is a reference to the cryptography libraries. You can get as fancy as you want with your algorithm. I've just provided a loose example of something that could be easily done in just a few minutes.

VB.Net Password Hashing practices

I'm trying to secure a website that is being moved to a public server soon. I've just finished adding the password hashing functions to all of my login scripts. I'm using FormsAuthentication.HashPasswordForStoringInConfigFile(pw, method) to do so. I have a question about the process I'm using and whether or not it's secure for a web server:
Password is sent in plain text over HTTPS to the server
The server looks in the Users table to find the user's Salt (several random characters) and their hashed and salted stored password
The plain text password is appended with the Salt
The new string is hashed using the above function
The newly hashed version is compared to the stored version
If equal, login is allowed
If not equal, the login attempt is logged in Session variables, up to 3 times before locking out the user's machine from accessing the login page until an admin verifies IP address and unlocks.
Does this look about right? I just don't see how the salt is effective in this method... Anyway, all I've done is add a salt and hash. Is this considered Encryption? Or am I missing a step? I remember reading that hashing algorithms like SHA1 and MD5 are not encyption algorithms, so what else needs to be done?
That is correct. The salt is used to prevent rainbow table attacks where a dictionary of common works hashed with MD5 is used to try to gain entry. Using the salt ensures that even if they had an MD5 hash of the word, it wouldn't work because they don't know the salt.
The MD5 algorithm is a 1 way hash algorithm, and not an encryption value. The difference is, once you've hashed the value, there is no way to get back to the original value. Encryption allows you to decrypt the data and get back the original value. So you are correct, they are not the same, and your passwords are not encrypted, they are hashed. This means that if someone forgets their password, you cannot send it to them. You have to provide a way for them to reset their password instead. This also means that anyone with access to the database would not have access to raw passwords. Which is good because a lot of people use the same password everywhere, and if you had access to a large list of usernames and passwords, someone could decide to start trying to log into bank / credit card websites.
What you are doing is a recommended practice.
You shouldn't be storing the retry count in the session - an attacker could simply discard their session cookie after each attempt, allowing them to retry as many times as they wish. Instead, store it against the user record.