Laravel Encryptable Trait Failing Authentication - laravel

I'm running into trouble with authentication handling in my Laravel 5.5. I have installed an Encryptable trait according to this post here. I then used the authentication generator to establish the base routes, views and handler.
I can successfully register new accounts and visually see that all of the data is encrypted, but I cannot successfully authenticate through the login screen.
This seems to be failing during the Auth::attempt($credentials) call. My troubleshooting is pointing to the encryptable trait because when I comment that section out, the authentication works fine.
Can someone offer insight as to how to handle authentication using this method of model encryption?
I have attempted disabling encryption for the username field, but this didn't seem to help. The password field was never being encrypted, becasue it is being hashed by bcrypt.
1st Edit:
So, with an understanding of how traits work... The Encryptable trait seems to be overloading the getAttribute/setAttribute functions. This would mean that Eloquent's querying functions like where, find, etc. will just be "looking at" encrypted values.
2nd Edit:
The source code provided for the Encryptable trait was not returning proper values for unencrypted values. This was changed and authentication was restored. To those using the same code snippet, in the get_attribute() function, change the else block so that it return $value;.
I appreciate all insights,
Dan

This form of encryption will void your ability to search the table for the encrypted fields. You won't be able to reproduce the same string because Laravel uses a random iv when producing encrypted data. An IV, or initialization vector, serves a similar purpose as a salt in hashing, to randomize the stored data.
Due to this randomization of data, you wouldn't even be able to search your table by re-encrypting the search data:
User::where('email', Crypt::encrypt('email#email.com'));
// won't find anything even if an encrypted value of email#email.com exists
Running in an interactive shell allows you to see encrypt returns a completely different value on subsequent runs:
>>> json_decode(base64_decode(Crypt::encrypt('email#email.com')))->value
=> "zpA0LBsbkGCAagxLYB6kiqwJZmm7HSCVm4QrUw6W8SE="
>>> json_decode(base64_decode(Crypt::encrypt('email#email.com')))->value
=> "VKz8CWVzR66cv/J7J09K+TIVwQPxcIg+SDqQ32Sr7rU="
Therefore, you may want to be selective about what you actually encrypt. Encrypt things that are sensitive and you wouldn't use to lookup an entity. This could be something like social security numbers, government IDs, credit card numbers, and bank account numbers.

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

Decryption of hashed passwords

I am working on a website's framework translation. I have translate it from Yii php framework to Laravel. I have got an existing database and I have to provide login access to existing users to the new website. The problem is now I am using Laravel and Laravel does not recognizes the hashed values of the previous framework. i.e the values that are stored in the database hashed by some method in Yii framework. Is there any way to resolve this. I am using Auth::attempt() method in Laravel.
You can't... plain and simple...
hashing isn't encryption. hashing is one way, you can prove this to yourself by taking an md5 or shasum of a large file, since the file's size is larger than the hashes output, by pigeonhole principle hashes can't be restored...
you could try to rainbow table them with password lists, don't, because this is compromising users security.
you will probably have to figure out a way to mash Yii's auth module into Laravel, or use some sort of middle man auth bit... or just make everyone change passwords.
The Yii framework generates password hashes through the crypt function, and according to the documentation it generates BCrypt hashes. You can check this easily by looking at the hashes, BCrypt hashes start with $2y.
So Laravel should actually be able to check password with your hashes, if you cannot find a method which is integrated in Laravel itself, you can surely use the password_verify() function to check the hashes.

Couchdb conceptual problems

As I understand, to update any object with couchdb. I have to send the whole object back since it is actually "inserting" a new revision for the same id. This is all neat and works quite well.
But then I have a problem, I'm not so sure how should I handle that. I have an object that can't be sent to my user completely. I have to hide certain informations such as password hash.
The data is sent to the client, the revision is sent too. Now when I try to update my object I have one problem. Since some data is missing, the update will erase the attributes that are missing from my user.
That said, the easiest way I have is to get the object from couchdb, check if id and rev matches. If it does match, merge the object with the missing attributes. It will work pretty well and I can support deleting attributes too.
Then using this technique, I could add my objects to a cache that will reduce the time to query frequent objects from the database. If the object can be updated, then clear the cache for that id. If the object is newer, then I'll have to handle the error or merge the object.
Is there any better "good way" to handle this problem?
edit
After thinking about it during the night, I think I found a much much better solution. Instead of having my username and password inside my profile. I'll separate the identification object from the use profile.
In other words, I'll have to split up the object as much as possible to keep things isolated... On the plus side, I can add multiple authentication for one profile without messing with the profile itself. I can return profiles and anything necessary without returning any secret object.
It will complicate a bit the logic of insertion but it should be quite easy...
Get 1 id from couchdb using the uuid api "_uuids"
Insert password authentications (username, password, profile_id) using that uuid
If succeed, insert profile using the uuid that we got at 1
If anything wrong happen, rollback and tell the users what's wrong.
Also the nice thing about this method is that I can add access_token for oauth2 using the profile id and the logic will be almost the same as password, the auth type will differ but any auth type should work almost the same.
Yeah, extracting the secret stuff from the profile documents sounds like the way to go.

Codeigniter Authentication and Authorization libraries that works well coupled toghether

I need functionality for authentication handling and some basic role based authorization (just block some pages to a role and allow some pages on another).
I already read this question: What is the best Authentication and Authorization library for CodeIgniter?
However the question it's from 2009 so maybe there is a new technology that works better now.
Any suggestion, expecially if you have used the library, are appreciated
All of the Auth libraries I know of restrict you in some form or other out of the bag. Its usually a good idea to build your own auth library, break it down so you dont restrict yourself to using codeigniters native AR.
For role/permissions I usually just store a json object to my permissions column in say users. I prefer this over using a more complicated technique
In my main Controller(non-restrictive) I just create a permissions(array)var and loop through it inside my child controllers to implement a restriction.
example:
sql column
`permissions` varchar(200) NOT NULL DEFAULT '["r", "u", "d"]';
main controller
protected $permissions = array();
protected function _get_permissions()
{
return (array)json_encode($this->user->permissions);
//get permissions from user (array/object)
}
extended children
if(in_array('r', $this->permissions))
{
//user can read something
}
I like skittles answer so I post it here (he is not posting):
I'm pretty sure this is not what you wanted to hear, but I prefer to
roll my own classes. I'm not afraid to re-invent the wheel
I prefer to use a salted hash. What I will typically do is take their
plain text password and add a string to it derived from a $config item
I call $config['encryption_salt']. Then I run the newly built string
through php's sha1 function and store the result in the database.
As for authorization, I will typically build a permissions lookup
table in my db and assign users a permission_id value in their user
record. Then my site can be conditionalized allow or disallow
activities based on their permission_id
If Skittle will post answer I'll mark it

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