Asymmetric encryption with attr_encryption - ruby

We're using the Gem: https://github.com/attr-encrypted/attr_encrypted as a way to encrypt some of our fields in our Rails application database.
Because we don't want the data to be accessible (even to developers) who don't know the key we have looked into using the Gem to do proper asymmetric encryption whereby the key is with the user itself and would require their password in order to decrypt certain fields.
For example:
attr_encrypted :example_field, key: proc { |user| user.key }
However I have two questions:
1.) How would we make sure the key itself had to be decrypted on user login? As the current implementation just means we have only made a key per user and moved it into the database and instead of an environment variable.
2.) According to the rules of asymmetric encryption we'd use a public key to encrypt the data and then the private (user key) to decrypt the data... but haven't been able to see how this Gem would support this as seems to only care about a single key for an attribute rather than proper public/private keys.

Related

Go x/crypto/bcrypt: Using a custom salt when generating the password hash

I am trying to implement a basic authentication system for a Go server that consists of users with multiple server-generated passwords (tokens essentially) which must be securely stored in a database.
One way of accomplishing this would be to hash the passwords with a one-way function and a globally unique salt.
However, since users have multiple passwords in my case, this creates a problem for authentication; each of the user's passwords would likely have a different salt, so the server would need to iterate through the passwords in the database, hash the supplied password using the same salt as the one in the database, and then compare. This does not seem efficient.
Alternatively, I was thinking that I could relax the "globally unique" constraint on the salt and randomly generate a salt when the user is created, and use it for all that user's passwords. With this, I would only need to hash the user-supplied password once, and could then use an SQL query to perform authentication. This is also the solution suggested in this related question.
However, the Go x/crypto/bcrypt package does not expose a function which hashes passwords with a custom salt, its salt generation is private. Is this for a good reason? Are there vulnerabilities with this approach of using a common salt for all of a user's passwords?
This problem seems common enough given that sites like GitHub and GitLab would have to deal with it for their personal access token storage, yet it appears that GitLab (by default) simply performs a sha256 hashing on their generated tokens.
By design each hash would have it's own salt, this is stored in the database. as a string with the salt, password hash, bcrypt passes etc. It appears all or most newer gen cryptography does this so each hash would have to be cracked individually. If you want something stored in your code I'd add a pepper to every password and then let their salts be unique in the db.
You're worried about efficiency of iterating over each password but I wouldn't be, security is probably better than your login efficiency. Just store their login session for x days?
Are there vulnerabilities
Well yes, bcrypt itself is considered vulnerable if that's an answer?
I think you should go with argon2id since it is what is considered "good" today, and since your program is new
https://pkg.go.dev/golang.org/x/crypto/argon2
This is a wrapper so it is safe as far as the Go crypto is concerned, and very easy to use:
https://github.com/alexedwards/argon2id
If you're wanting tokens you should probably use UUIDs

Password encoding and decoding using Spring Security, Spring Boot and MongoDB

I use the mentions software stack above and I need to encrypt password before save into database. I also need to decrypt password because when someone will change password he she needs to give in the old password and then the new onw twice and I need to check the old password.
I have searched a lot but I still not sure what is the right way to do this.
I have found this link Encrypting but are there other hints to do this?
I also not sure if maybe MongoDB provides something to protect passwords.
First read Steven CarlsonĀ“s answer about password hashing.
The good thing is that Spring Security will do this for you. Spring Security 3.2 introduced the new org.springframework.security.crypto.password.PasswordEncoder interface and some implementations: BCryptPasswordEncoder, StandardPasswordEncoder (and NoOpPasswordEncoder).
Important: Do not confuse org.springframework.security.crypto.password.PasswordEncoder with the old deprecated org.springframework.security.authentication.encoding.PasswordEncoder
The interface (and therefore the implementations) has the two methods you need:
public String encode(CharSequence rawPassword)
public boolean matches(CharSequence rawPassword, String encodedPassword)
I recommend to use org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.
The BCryptPasswordEncoder (in contrast to the StandardPasswordEncoder) use an salt that is different for each password (but not global like the one from StandardPasswordEncoder). When you encode a raw password (public String encode(CharSequence rawPassword)) then the returned encoded password is not just the encoded password, it also contains some meta information about the used hash-algorithm, the used salt and of course the encoded password.
You should not be "encrypting" the password at all. I know this sounds counter-intuitive. But there is zero reason your system should need to decrypt the password. To do so would open your database to a hacker, because if you store your decryption password in your codes/server a hacker can steal that information.
The correct process is to hash the password. A hash is a one-way (cannot be decypted back to the original text) process. The current standard would be to use SHA256 to hash your password. Here is a basic flow-chart:
Take user submitted password. Example password "mypass" would hash out to ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222
Store this hash (ea71c25a7a602246b4c39824b855678894a96f43bb9b71319c39700a1e045222) in your database.
When a user logs in you take the password he just submitted and hash it. If he enters the same password it will hash out to the same value in your database.
When a user goes to change passwords you hash the "enter your old password" to verify the old password still matches, if it does you hash the "enter your new password" and save it.
One thing I did not mention in my example is salt. This is something you must use in your system as it protects your data from rainbow table exploits. But that is for another discussion.
Hope this helps :)

Ruby encryption/decryption with secure password

I want to connect two ruby interfaces. I want to pass key and secret from interface 1 to interface 2 in encrypted form and user in interface 2 can decrypt the key and secret if he has a specific password. Which is the best way to implement it?
Use PBKDF2 to generate a key from a salt and the password. You can use this key to perform key wrapping (encryption) over a randomized key you want to agree on. You could simply use AES in ECB mode of operation if you only encrypt a randomized key value.
If you also need to encrypt a message then take the key and use an authenticated mode of encryption like GCM and use that to encrypt. If that's not available then use CBC and HMAC, but don't forget to include the IV vector in the HMAC calculation over the ciphertext. Sending non-authenticated ciphertext over the internet is not likely to be secure.
If available you could also use TLS with PSK authentication. That would almost certainly provide better protection than some kind of proprietary scheme such as the one above.
There are lot of Options available, I liked Gibberish
Gibberish
gpgme
encrypted strings

Clarification on public key decryption

I have a key pair and I use private key to encrypt the data, public key for decryption. Is it possible to provide confidentiality in this setup ?
No, it's not. You must encrypt data using recipient's public key to have confidentiality. Now all you have are integrity and authenticity (you've got a variation of digital signature, actually)
In the setup that you're asking about, anyone who had access to the recipient's public key (which could be a lot of people if it's truly public) could then decrypt the message, so no, there is no real confidentiality.
If you want to provide both authenticity and confidentiality, you might try encrypting the data with the recipient's public key in order to provide confidentiality, then encrypting (or signing) that with your private key. The recipient would then decrypt (or verify) that data by decrypting it with your public key, thus indicating that the data really came from you, and then decrypting that data using their private key thus helping to ensure confidentiality.

What is the best way to keep database data encrypted with user passwords?

Let's say an application has really specific data which belongs to a user, and nobody is supposed to see it except the owner. I use MySQL database with DataMapper ORM mapper. The application is written in Ruby on Sinatra.
Application behavior:
User signs up for an account. Creates username and password.
Logs into his dashboard.
Some fields in specific tables must be protected.
Basically, I'm looking for auto-encryption for a model properties. Something like this:
class Transaction
include DataMapper::Resource
property :id, Serial
property :value, String, :length => 1024, :encrypted => true
... etc ...
belongs_to :user
end
I assume that encryption/decryption on the fly will cause performance problems, but that's ok. At least if that works - I'm fine.
Any ideas how to do this?
I wouldn't store any data that relies on the user remembering their password and then using that password to decrypt the data. What are you going to do when the user changes their password? Decrypt/Encrypt everything? I doubt it. What if the admin reset the password? All data lost? Again, I doubt it.
See the other links about storing secrets but please don't use any value from the user as part of your encryption.
So you want to store the data encrypted in the database? Firstly, I would ask you to consider why you need to do this? You should be able to write your application such that only the authenticated user can get to their own data.
If you do genuninely need to store encrypted data, that you also need to be able to decrypt (as opposed to a one-way hash) then there is lots about encryption in ruby here: http://www.example-code.com/ruby/encryption.asp
You certainly should encrypt/decrypt data on user side - otherwise there is no point in encrypted storage, as tracks of private data still there somewhere - in network cache, in swapfiles of different kind etc. Moreover, data can be sniffed with Man-In-The-Middle attack.
So what you probably want is javascript-based client-side encryption. Topic is greatly covered in http://javascript.about.com/library/blencrypt.htm (Rijndael encryption algorithm), and there is great AES implementation library on http://www.movable-type.co.uk/scripts/aes.html
You should encrypt data before submission of form (with onClick callback of "Submit" button f. e.), and then pass to server and process as usual.
Drawback is that you can't use any Rails with such data - only client-side javascript.
I had to do this for encrypting sensitive data. I wrapped the strongbox gem and it's on github: http://github.com/bitzesty/safe
The safe gem provides Public Key Encryption of AR attributes.
You use a one-way hashing algorithm. Hash the password and store the hash. Then whenever the user enters his password, you hash the password entered and compare it to the stored hashed password. If they're the same, you let them through. If not, they're denied.
It's generally not a good idea to ever store a user's password that can be taken to plaintext.
Typically it is stored as a salted hash of either MD5 or SHA1.
So, you have a random salt, store it in the user's table, and then you hash their pass and the salt, like this:
$hash = md5(md5(salt) + pass)
I would recommend against storing a pass that can be returned, the only way I'd recommend you store it is in a one way hash.
That said, there are some encryption schemes that you can use, such as RSA encrytion. This way, your application will encrypt the user's password that it receives from the end user using your public key, and when you need to decrypt it, do so using your private key. There's really very limited application for storing a key this way (such as providing a log in to another site automatically) and is typically frowned upon.
attr_encrypted may be also solution for encryption sensitive data, works with ruby class or ActiveRecord, DataMapper, or Sequel in Rails.
https://github.com/attr-encrypted/attr_encrypted

Resources