Eloquent - combining User::where with Hash::check - laravel

I am using Lumen/Laravel Eloquent.
I have table users with column token which represents hashed token value created with Hash::make($fullToken).
Now I want to compare full token value which users sends from to server with hashed value saved into database.
I am not able to do this this way:
$hashedToken = Hash::make($userSentToken);
because each hashed value has salt part and I need to use Eloquent's Hash::check('plain-text', $hashedValue) function.
How can I combine this check() method with User::where() ?
I want unique way to convert that full token to hashed value and to select token column from database by that hashed value.

Why not Hash
Hash::make returns different output every call, but you need a deterministic function. Hash::make is not a simple deterministic function like md5 which returns constant output at every given input. So you can't query hash when using Hash facade the way you've described.
If you need to query a hashed value through a database, try to use smth like an md5 function instead of Hash::make.
Some variants to store
md5($userSentToken)
md5($userSentToken . $salt)
md5(md5($userSentToken))

Related

Is getting data back from Redis SETS faster or more performant than HSETS?

I currently have a scenario where we are using REDIS to store string field-value pairs within a hashed set HSET.
The original reasoning behind using hashed sets instead of just sets is ease of retrieving the records using HSCAN inside a GUI Search Bar as opposed to just SCAN because it's easier to get the length of a hash to use in the COUNT field.
I read in the Redis documentation that both GET and HGET commands execute with O(1) time complexity, but a member of my team thinks that if I store all the values inside a single key then it basically returns the entire hash during HGET instead of the singular field-value that I need.
So for a made up but similar example:
I have a Redis instance with a single Hashed Set called users.
The hashed set has 150,000 field:value pairs of username:email
If when I execute hget users coolguy, is the entire hash getting returned or just the email for user coolguy?
First of all, HSET is not a hash set, it creates a hash table. The mechanism behind the hash table and set (which is indeed a hash set) in redis is the same, the difference is mainly that the hash table has values.
To answer your question:
If when I execute hget users coolguy, is the entire hash getting returned or just the email for user coolguy?
Just the email for that user. You can also use HMGET to get the emails of multiple users at once. It's O(1) for each user you fetch, or O(n) for n users.

How to stop Doctrine from returning a primary key for every query

I am kind of annoyed at Doctrine for returning primary keys in each and every query even though I don't want it to. Is there anyway to stop this ? coz I don't really want those damn primary keys along with my doctrine query results.
A query for instance that I have is:
$getAllDatesForUserQuery = $this->createQuery('s')
->select('s.datename')
->where('s.userid = ?',3)
->setHydrationMode(Doctrine::HYDRATE_ARRAY) ;
In this situation, it retrieves all the datenames as it should, but also happily returns the primary key column value. I DON"T WANT IT.
Is it me? or is it Doctrine ?
In a case like this where you want a simple array and only have a single field being selected, the answer is the Single Scalar Hydration mode. Use it like this:
$q = $this->createQuery('s')
->select('s.datename')
->where('s.userid = ?',3)
->setHydrationMode(Doctrine::HYDRATE_SINGLE_SCALAR);
You should find that the query will return a simple one-dimensional array containing only the value(s) you wanted.

Index a column encrypted with pkg_crypto

I'm working on a project that uses pkg_crypto to protect users' personal information. There are several thousand rows (which is expected to grow to maybe several tens of thousands), and whenever I use a WHERE or ORDER BY clause in a query, the whole table is decrypted before the results are returned. This takes several seconds for a single query, which is usable for development but will probably not be very good for the release.
Is there a way to create an index that will work on the encrypted columns without compromising security?
The inserts and selects look something like this (with iBatis):
insert:
INSERT INTO "USER_TABLE"
(
"ID"
,"LOGIN"
,"PASSWORD"
,"NAME"
,"EMAIL"
)
VALUES
(
user_table_seq.nextval,
#login#
,#password#
,pkg_crypto.encrypt(#name#, 'key')
,pkg_crypto.encrypt(#email#, 'key')
)
select:
SELECT
"ID"
,"LOGIN"
,"PASSWORD"
,pkg_crypto.decrypt("NAME", 'key') NAME
,pkg_crypto.decrypt("EMAIL", 'key') EMAIL
FROM "USER_TABLE"
WHERE pkg_crypto.decrypt("NAME", 'key') LIKE #name# || '%'
AND pkg_crypto.decrypt("EMAIL", 'key') LIKE '%' || #email#
I'll preemptively put out there that the password is hashed by the servlet before being passed to the db.
Do you need to use PKG_CRYPTO to encrypt the data (which, I'm assuming, is something you wrote that calls either DBMS_CRYPTO or DBMS_OBFUSCATION_TOOLKIT? Oracle has a feature called transparent data encryption (TDE) (though this is an extra cost option) that would allow you to have Oracle transparently encrypt the data on disk, decrypt it when it's read from disk, and then use this sort of LIKE predicate on your data.
Substantially, the answer is No.
When each value is encrypted, it has a random IV (initialization vector) chosen to go with it. And this means that you cannot predict what is going into the index. If you re-encrypt the value (even with the same key), you will get a different result. Therefore, you cannot meaningfully use an index on the encrypted value because you cannot reproduce the encryption for the value you're searching for. The index would, in any case, only be useful for equality searches. The data would be in a random sequence.
You might do better with a hash value stored (as well as the encrypted value). If you hash the names with a known algorithm, then you can reproduce the hash value on demand and find the rows that match. But simply knowing the hash won't allow you (or an intruder) to determine the value that was hashed except through pre-computed 'rainbow tables'.
So, you cannot meaningfully index encrypted columns - not even for uniqueness (since the same value would be encrypted different ways by virtue of the random IV).

How to use Spring's StandardPasswordEncode?

StandardPasswordEncoder encoder = new StandardPasswordEncoder("secret");
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
This is all clear, but in database I just store a single VARCHAR password field storing hashed value concatenated by salt? Is it that simple?
In the Database you should store the return value of endocer.encode.
just store a single VARCHAR password field storing hashed value concatenated by salt?
That is wrong (or may only not correct written), correct is:
In the first step the Salt is added to the password,
In the second step the hash is calculated (from the salted password)
hash(password+salt)
But NOT the other way around hash(password)+salt!
People say not to store passwords as plain text , but hashed passwords are still plain abracadabra text
The people mean that you should not store the password as it is (plain) but of course you can store the hash in a text representation. -- The problem that the people talk about is, that if anybody has access to the database he should not bean able to read the passwords to use them. If you think that storing passwords as hash (for example md5) is not secure enough, because of well known md5--cleartext tables, then one add a salt before, and hope that password+salt is not in that tables.

Compare Two-Way Encription With Data in Database

I have a column named id_num in database and the column must has a unique true value.
Users have to enter their ID Num to register in my system.
To protect ID Num, I encript it using $this->encript->encode()
The encripted data will generate different code every time I enter the same data.
Example:
First registration:
I entered 12345, will be encripted to PVfuF8GDzE4yton9tNabJwG
Second registration:
I entered the same number 12345, will be encripted to different code M0wYZsDAdR1u0WlsDAdR1
So, I call checkExistIdNum() to check either the ID Num already exist or not to make sure the id_num column is unique.
function checkExistIdNum($enc_id_num=null) {
$this->db->select('COUNT(*) AS count');
$this->db->where("(id_num = '$enc_id_num' AND user_id != '".user_id()."')");
$query = $this->db->get('user_info');
$num = $query->row()->count;
if($num>0) return true;
else return false;
}
Both has the same true value, but how can I compare id_num = '$enc_id_num' while both encripted code are different?
I think you are confusing the concept of a cryptographic hash and two way encryption.
A hash is a one way, and it always has the same result, given identical input.
MD5 or SHA1 are one-way hash algorithms that are commonly used to mask passwords in databases, the main reason for this is that it is just that, one-way, if the hash is obtained it cannot be reverted to its original value.
Use the database's built-in encryption functions so that the database indexes the values, and can quickly match against an arbitrary value you enter. Otherwise you're just reinventing the wheel, and you'll either have to keep a separate index that you compare against every time (very slow), or decrypt and compare every row individually (EXTREMELY slow).
Built-in encryption solves all of this without the possibility of leaking sensitive data through the indices.
And yeah, maybe it would be a good idea to use a hash, but for trivial account strings, that could easily be reverse-engineered if someone dumped the database.
Since you don't identify your database or your PHP version I can't be more specific.

Resources