Encryption of Database Id - mysql

I was working on developing a RESTful service where the Id of a particular table in the database needs to be returned to the client for future access to the particular entry in the database. I was advised against using auto increment and returning the id directly and hence I went for encrypting and sending the Id in the following manner instead -
SET #secretKey1 = "some key";
SET #secretKey2 = CONCAT("some other key", AccountNo);
SET #encryptedAccountNo = TO_BASE64(AES_ENCRYPT(AccountNo, #secretKey1));
SET #encryptedId = TO_BASE64(AES_ENCRYPT(Id, #secretKey));
RETURN CONCAT(#encryptedAccountNo, #encryptedId);
(Note: The Account Number is a sufficiently random field not exposed to the client)
Would using UUID as the primary key be more appropriate? If so, is using the UUID enough or should that be encrypted too?
Or would you use some other design entirely?
Also, do you have any tips for improving the security or performance aspects of the existing design?

I think you may have misunderstood that advice....
When you say "I was advised against using auto increment and returning the id directly".
You should certainly always CHECK the Id is correct to use server side, before using it;
(i.e. check that the document with that Id belongs to the user who is trying to edit it),
but encrypting the ID itself really serves no useful purpose as your API will have to deal with the encrypted one (unless you are encrypt/decrypt client side, which does nothing for security), so the (malicious) client can just send the encrypted version and have the exact same result...
We cannot comment of the security of your code from looking at a (small) piece of your database logic. If you want proper review you will have to post the code that actually does the interaction...

Related

Springboot + JPA: catch DataIntegrityViolationException vs check COUNT(field)

Good morning,
I am creating a new user, and it's email must be unique. I have declared it as so in the User entity.
I am wondering whether it is better (quicker/best practice) to catch a DataIntegrityViolationException when the user is being created in the DB or if it is better to check if the user exists: select count(*) from User u where u.email=? for example.
I am working in SpringBoot, using MySQL and JPA.
Thank you so much!!
The difference of performance might be very insignificant in that case.
What is the most important here, is to understand what happens by reading the code. You should have some code in your service layer that checks every rule defined is not violated before actually trying to proceeed in databaase. IT will be easier for new comers (and even for you in few weeks) to have a clear view of what is tested and how.
That part of code should then raise an exception with a dedicated code (for example, let's take the ID of the business rule defined by your business analysts) and in a properties, you should have a message corresponding to that rule (the message key could be the id of the rule for example).
Also, while inserting a row in this table, you could get DataIntegrityViolationException for different reasons. So, that is not a durable solution anyway.

Firebase Database: how to compare two values

In my Firebase database, I have a data structure similar to this:
The post ID (1a3b3c4d5e) is generated by the ChildByAutoId() function.
The user ID (fn394nf9u3) is the UID of the user.
In my app, I have a UILabel (author) and I would like to update it with the 'full name' of the user who created the post.
Since I have a reference to the post ID in the users part of the database, I assume there must be some code (if statement?) to check if the value exists and if so, update the label.
Can you help with that?
While it is possible to do the query (ref.child("Users").queryOrdered(byChild: "Posts/1a3b3c4d5e").queryEqual(toValue:true)), you will need to have an index on each specific user's posts to allow this query to run efficiently. This is not a feasible strategy.
As usual when working with NoSQL databases: if you need to do something that your current data model doesn't allow, change your data model to allow the use-case.
In this case that can either be adding the UID of the user to each post, or alternative add the user name to each post (as Andre suggests) and determining if/how you deal with user name changes.
Having such relational data in both directions to allow efficient lookups in both directions is very common in NoSQL database such as Firebase and Firestore. In fact I wrote a separate answer about dealing with many-to-many relations.
If you can change the structure then that is very good because I don't think you are maintaining proper structure for database.
You should take one more key name createdBy inside the Post node so actully structure would be
{description:"Thus the post is here", title:"Hello User", createdBy:"Javed Multani"}
Once you do this, It will dam easy to get detail of user.
OR
Unethical solution,
You can achieve this thing like while you are going to show Post from post node of firabase. Definitely you'll get the auto generated postid like:
1a3b3c4d5e
now first you should first get only posts then inside the successfully getting data and parsing you have to get users and find inside the user by putting the codition like postId == UserPostId if match found take fullname value from there.

Storing unconfirmed and confirmed data to a database

I am creating a web application using Strongloop using a MySQL database connector.
I want it to be possible, that a user can modify data in the application - but that this data will not be 'saved' until a user expressly chooses to save the data.
On the other hand, this is a web application and I don't want to keep the data in the user's session or local storage - I want this data to be immediately persisted so it can be recovered easily if the user loses their session.
To implement it I am thinking of doing the following, but I'm not sure if this is a good idea, or if there is a better way to be doing this.
This is one was I can implement it without doing too much customization on an existing relation:
add an new generated index as the primary key for the table
add a new generated index that represents the item in the row
this would be generated for new items, or set to an old item for edits
add a boolean attribute 'saved'
Data will be written as 'saved=false'. To 'save' the data, the row is marked saved and the old row is deleted. The old row can be looked up by it's key, the second attribute in the row.
The way I was thinking of implementing it is to create a base entity called Saveable. Then every Database entity that extends Saveable will also have the 'Saveable' property.
Saveable has:
A generated id number
A generated non id number - the key for the real object
A 'saved' attribute
I would then put a method in Savable.js to perform the save operation and expose it via the API, and a method to intercept new writes and store them as unsaved.
My question is - is this a reasonable way to achieve what I want?

Storing userID and other data and using it to query database

I am developing an app with PhoneGap and have been storing the user id and user level in local storage, for example:
window.localStorage["userid"] = "20";
This populates once the user has logged in to the app. This is then used in ajax requests to pull in their information and things related to their account (some of it quite private). The app is also been used in web browser as I am using the exact same code for the web. Is there a way this can be manipulated? For example user changes the value of it in order to get info back that isnt theirs?
If, for example another app in their browser stores the same key "userid" it will overwrite and then they will get someone elses data back in my app.
How can this be prevented?
Before go further attack vectors, storing these kind of sensitive data on client side is not good idea. Use token instead of that because every single data that stored in client side can be spoofed by attackers.
Your considers are right. Possible attack vector could be related to Insecure Direct Object Reference. Let me show one example.
You are storing userID client side which means you can not trust that data anymore.
window.localStorage["userid"] = "20";
Hackers can change that value to anything they want. Probably they will changed it to less value than 20. Because most common use cases shows that 20 is coming from column that configured as auto increment. Which means there should be valid user who have userid is 19, or 18 or less.
Let me assume that your application has a module for getting products by userid. Therefore backend query should be similar like following one.
SELECT * FROM products FROM owner_id = 20
When hackers changed that values to something else. They will managed to get data that belongs to someone else. Also they could have chance to remove/update data that belongs to someone else agains.
Possible malicious attack vectors are really depends on your application and features. As I said before you need to figure this out and do not expose sensitive data like userID.
Using token instead of userID is going solved that possible break attemps. Only things you need to do is create one more columns and named as "token" and use it instead of userid. ( Don't forget to generate long and unpredictable token values )
SELECT * FROM products FROM owner_id = iZB87RVLeWhNYNv7RV213LeWxuwiX7RVLeW12

Reverse hash lookup query

i have an web service and one of the parameter our clients needs to use is a custom key. this key is a hash of sha1
eg:
bce700635afccfd8690836f37e4b4e9cf46d9c08
then when the client call our web service i have to check few things:
is client active
is client can submit via webservice and service
now my problem is this:
i have a query:
$sql = "SELECT permission, is_active FROM clients WHERE sha1(concat(id,key)) = '" . mysql_real_escape_string($key) . "'";
Am i doing the right thing? or there's a better way?
thanks
This approach is expensive, since, every time you run this query, MySQL will have to examine every single record in clients and compute the SHA-1 hash of its id and key. (I'm assuming here that clients has more than a few rows, or at least, that you'd like to use an approach that supports the case where clients has more than a few rows.)
Why don't you add a new field called (say) id_key_sha1? You can use a trigger to keep the field populated, and add an index on it. This approach should perform much better.
Edited to add: You mention that the client, in addition to passing in this SHA-1 hash, also has to submit a username and password? I don't know what your table structure looks like, but I'm guessing that it would make more sense to find the client record based on the username first, and then comparing the SHA-1 hash for that specific record, rather than trying to find the record by the SHA-1 hash.
You should not applying function into your LHS column where doing filtering in mysql,
this make not possible for mysql to make use of index for comparison.
An example will allow make use on index :-
where key = SHA1(CONCAT(id, :key))
// where the :key = user submitted api key
// and in this case mysql able to fetch the matched rows via index