How do you create a unique id which cannot be faked? - c#

I have a .NET client app and a PHP server web app.
At some point, the .NET app will have to be identified by a unique id and pass that data to the webserver by http post. The web server will respond with some data and store the unique id in a database.
Assume that I have a malicious user and I would like to ban him by the unique id. So in my opinion there are two important things about this unique id:
The unique id has to be really unique and always the same per computer
A user should not be able to trick the system (a banned user could generate a new id and post it manually to the web server to receive new data)
How can I make sure that the unique id cannot be (easily) generated by a user?
How can I make sure that the unique id can be verified on the server for validity?
What is the usual approach (algorithms, encryptions?) here?

Create UUIDs for all apps and store them into databases after verification and delete/ban/flag UUIDS so they cannot be used again
UUIDs in MYSQL :
http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_uuid
also available in postgres and other RDBMS storage
I have created 10 million lists with uuids multiple times and never once had a collision.

Okay so here I summarize:
Of course there is no perfect security system. Jeremy Miller
Dan's answer is not correct because a MySql UUID is not device dependant and so not fulfilling the condition "the id should be the same per computer"
I should generate an id (like UUID), store it somewhere on the computer in an encrypted form, include a seed in your code then transmit a hash of the id with the seed to your server, requiring every call to include that hash along with some other component which you also include in the hash to verify. Jeremy Miller
This approach is not fool proof because everything stored locally can be removed but at least it is hard to guess a valid generated hash

Related

Migrating users to Identity Server

I have a large subset of WordPress users in a MySQL database who I want to migrate to Identity Server 4/5.
While I could easily select the data and insert into the ASPNetUsers table, my concern is:
I'm bypassing the controlling application (Identity Server)
Also there appears to be, two cryptographic fields in ASPNetUsers table (SecurityStamp
and ConcurrencyStamp) which I don't know how to generate data for. Not populating them feels like it could lead to interesting side-effects.
What is the best practice in importing a large subset of users programmatically into Identity Server?
Those 2 values just need to be random and in the correct format and don't in themselves hold any meaning. They're just used to check if the DB record has changed since it was loaded.
The main thing to worry about is migration of password hashes. We solved this by having a back channel call to the source system to validate the password the first time the user signs in and then updated the local PasswordHash once we'd verified the provided password was valid.

Cross-Platform encryption for Database

Let's say I have a MySQL database into which users can enter some personal data like postal addresses via a php website. The users can NOT log into this site to later verify what they have entered. The enterprise they have entered their data for (voluntarily of course) then can use this data to maybe send the users actual mail (you know, postal services and such) or emails (of course the users agreed beforehand that they want to receive emails). The database serves merely as a store for the data and I want it to be a bit safe. If anyone breaks into the database, retrieving the email address and the actual first and last name (many email addresses contain both anyway) might not do much harm, but knowing where people live could be too much of a giveaway.
The enterprise is accessing the database via a C# front-end that targets stored procedures within the database to do stuff, including searching for users based on their email address.
From what I have gathered through searching I could think of the following procedure to handle the personal data in a more secure way (than saving them as plain text in the database)
before submitting the sensitive information to the stored procedures the plain text gets encrypted with a key while still in php, so all the MySQL server logs see is encrypted data
the front-end uses the same key to make the data humanly readable again when it is displayed to the enterprise's users (They need to access this private information and the user is comfortable with the enterprise doing so, that's the whole point of this scheme)
My line of thinking is: These are not passwords that are stored so I don't need all the password hashing trickery (As I understand it, when securely saving a password in a database, you use a one way algorithm, so you can never reverse engineer the password straight from the database but have to hash every password you want to try and test that against the desired database entry to see if you chose the right password) but can instead go for a simple encrypt/decrypt, because I don't want to brute force every address out of the database.
There are a few rough edges that raise concerns for me:
I need to somehow provide the key I want to encrypt by to php. Usually this is done via a library or external php document, like you provide the database connection information in a separate php file which resides in a folder on the server which is not accessible from the web (The server will say access denied if you try to access it) Is this a good practice and can I be sure that this key-file is really safe?
I need to provide the key to the front-end as well. This should be done separately in a (maybe encrypted?) config file for the front-end. Is it wise to have the key in two places, albeit for two different systems? The key must never change or else part of the data will be lost!
Somehow I have the feeling that if someone knows how to access the database he/she probably figured out where the connection data was and how that was to be accessed. Oh look, here is an encryption key, I wonder what that does. How likely is it that if the database access is breached the encryption key is in the open as well rendering all efforts to give a little extra of privacy to the users void?
If I wanted to add another bit of "extra security" and encrypted the email address as well I would have to encrypt every email address I want to search for from the php or the front-end, right?
Having searching procedures using ´RLIKE´ will break on encrypted fields, won't they? So to retain searching for parts of an email address I cannot encrypt the email entry, right?
I will have to change my database fields to binary to accommodate encrypted data or make them bigger and base64-encode them, won't I?
Is there an encryption/decryption algorithm ready to use in PHP 7.0.7 and C#? (I don't worry that much about C#) One that is reasonably secure while not bloating my tiny texts to massive chunks of binary? I don't know if that is of any consequence, but if I use for example a 256 bit key, that's 32 bytes. If the street part of the address is shorter that 32 characters, will the encryption work? Will there be cumbersome padding involved?
All in all I feel that the security gain is minute compared to the measures I have to take in my php files as well as in the code for the front-end. The perceived security gain might be bigger ("Woha! They are saving our data encrypted! They sure know what they are doing!"). Having strict and restrictive privileges for certain types of users (for example revoke ´SELECT´ commands) should in all be more helpful, shouldn't it?
Edit for #Luke Joshua Park:
Thank you for your detailed answer.
I suppose by API server you mean the webserver my php's reside on? This indeed should be separate from the database server. Both servers are hosted within a university's network but can be accessed from the internet.
I can follow the authentication path to the point where every user from within the enterprise (small-ish project at said university, maybe a bad choice of wording) has a database user with sensibly set grants. But users from outside using the php only send data to be stored in the database (ideally with a common but seperate database-user with grants set accordingly), and never retreive (their own) data. Using authentication would mean they first had to create an account (which is not needed) and how do they authenticate themselves for creating the unwanted account?
It is good that you're asking these questions before implementing a solution, cryptography is difficult to get right and a sound understanding is required before you start.
I'll answer your questions quickly first, but the more important part is what follows.
Not really. See below.
Yes, in most cases, keys should be kept on the device they are created on, wherever possible.
Provided your API server(s) doesn't also have the database on it, relatively unlikely.
Yes.
Yes.
Yes. But don't base64 them. Wasted space and processing power for no benefit.
You're asking the wrong questions. An algorithm isn't "for" a language. You just need to pick the right algorithm/block mode/padding depending on your needs.
For the most part the questions you are asking are irrelevant. Believe it or not, your issue is more to do with authentication than it is to do with encryption.
The first thing you need to understand is that a server breach is a server breach. Bad stuff is going to happen regardless of how much cryptography you throw at it. But we can minimize damage where possible.
Your database software should be running on a separate server/instance/whatever from your API server. Encryption/decryption should only take place on your API server. This has the benefit that both your API server and database server would have to be breached in order to decrypt the data (to access the keys). How you store the keys on your API server isn't all that important provided they aren't in your webroot or something silly like that.
Everything past this is authentication. You need a strong authentication system to determine who can send you information and who can retrieve information from you. Communication to and from your API server should obviously be encrypted with TLS at all times. You might consider TLS client authentication as a way to ensure the entity requesting data from you is who they say they are. Usually client authentication can't really be used on the web, but if you're interacting with "enterprises" in a more private way, then client authentication is an excellent choice.
In summary:
Separate your API server from your database server. Encryption keys should only ever be on the API server. See this repository for a collection of encryption examples from PHP to just about any other language.
Use TLS for all ingoing and outgoing communication.
Focus on authentication. TLS Client authentication is a good option.

Unique Client ID in C#

Situation:
I'm creating some kind of website that let users comment and like on posts. There are two types of users, users with user name and password (type 1) and guest (type 2).
For type 1, data will be stored with the keys are their login credentials. By this an user can't like a content multiple times (next time, loading the page, they will see the "Unlike" button)
Type 2, I'm using IP for differentiate between users. But, IP is changeable by time (since normally, IPs are dynamic).
Notes: Needed to be implementable with C#, ASP .Net.
I can't use session variable, because it will be destroyed after closing the browser.
About cookie, cookie is nowadays so easy to be deleted, this will be my worst way for implementing (in case there is no other).
Question:
Is there any ways to generate unique id for a client (a PC/smart device), so first time if you use a PC to view the post X on page, you like it, next time (even after you close your browser) page can identify you then change button to "Unlike".
There is no reliable way to do this. For example, what if a user opens the site on his laptop, then his mobile, then his tablet? You cannot prevent each of those devices being registered as a different guest. The only solution is to make people log in and only allow read access to anonymous guests.
There are two ways of handling this.A) Get the Unique Device Identifier (UDID) and store it on your server.
B) Generate a Universally Unique Identifier (UUID) and store it on both the device and your server.
With the first method, you don't store a UUID on the device, so you both save space (bytes worth of data, but still) an the user can't change the ID without reinstalling the OS. But, it would be highly platform dependent.
With the second method, you use the System.Guid.newGuid() method and save the resulting UUID to a cookie on the browser.
Then you either read the data off the cookie or get device UDID and compare it to your database.
But, this wouldn't keep the user from accessing the website from different devices. The best method would be to ask the user to sign in (But PLEASE be careful with password security as people generally use the same password across services).
Hope I helped :)

Windows Store Apps - Let user to remove trial mode via code

I have developed application which supports trial mode. But now I need let some users to get full via activation code. Scenario is user downloads trial application and he can enter activation code for the app and then user can use full features of the app.
Can anyone please suggest me a way to do this.
You need to think about how you will authenticate the code - I'm guessing that you don't want them to authenticate the code via the store so you will have to provide some backend service to do this.
The service will obviously require the activation code to be sent to it (you should store this in the remotesettings), and you might perhaps want a device unique ID sent to - you can use the unique id for this.
Your service should then validate how many times it has seen the code, and if it's happy it should hash the code, the device ID, and a secret shared with your application - this will need to be embedded inside your app code.
For additional privacy for the user I would advice hashing the device unique ID with the shared secret before sending it to the server.
You need to store the returned activation code inside your app - and there isn't a lot of choice - I would personally store this code in the LocalSettings area.
Now on startup you need to verify that the stored activation code is valid. If you have an internet connection then you can do this by asking the service if the code is valid, but you must make an arrangement for offline checking. This is simple enough as the activation code, plus the hashed device ID hashed against the shared secret should equal the stored activation code - depending on your type of application you might want to only allow 5 activations this way before requiring internet access (pick a high number as this could really annoy users)
Finally you need to consider users that have multiple devices - according to the store you can have 5 installs of the same application, for the same users, across different devices. To accommodate this we have stored the activation code in remotesettings, so on startup check if the code exists, and if it does automatically send the code and the device id to your service for activation.
The only other thing you need to consider is how on earth do you secure the shared secret in your application? Unfortunately there aren't many options for this. It really depends on how secure your app need to be. If you are totally paranoid then obfuscate your code, but this just buys time. If you need more than that then I suggest you send the device code, hashed with a cryptographically random nonce to your service, this will return back what you sent, but hashed with the secret. Unfortunately this will make offline validation of the activation token impossible, so you will have to build in a grace period where internet connection is not required.
Or you could use in app purchases.

Securely Upload files C#/PHP

So I have no code at the current time but I haven't quite started because of the following issue.
I want to have a website (written in PHP) that allows users to upload files but I'd also like to have a C# app that runs on a Windows desktop and can automatically upload the files. My question has to do with security.
Firstly, from the PHP perspective is simply hashing and salting with MD5 or something similar really safe for accounts on a website?
Furthermore, how can I safely STORE and preserve the credentials of the user LOCALLY within my C# application? Almost like cookies except I'd be managing it myself. I'm looking for a high level answer as well as what specific tools I should use (or what I should read about before fully pursuing this).
Thank you in advance for your time. :)
To answer both questions...
Firstly, hashing and salting with MD5 is no longer 100% secure as people can use a rainbow table to quickly hack the hashing. You might want to look into something that generates a longer hash to prevent rainbow tables attack.
If you want to safely store a authentication token on the client end (like a "remember me" check box), you can have a table in your server that stores a random string every time the user accesses the php page. To make it more secure, you can hash in a unique value of that PC, like the network card's MAC address.
What this does is...
1) When the user first logs in from the c# app, you will create a record that stores the user id, the MAC address, and a long random string in that table. You then return this random string to the c# app to store in the local file.
2) When the c# app access the web page again, it will pass to your PHP app, the MAC address and the random string stored there. If it matches a record, then we know the user id of the c# app.
3) The php side should then re-generate another random string and send it back to the c# app to overwrite the existing locally stored authentication token. This will ensure the token changes a lot and people cannot simply make a copy of the file storing the token, and be able to access the server.
Hope this is clear enough.
A salted sha256 hash will be fine. Salt it with something that isn't stored in the database. Having the data come from two different sources will make it even harder to brute force.
It depends on the C# app. If it's only going to have one user then transfer the files over SSH using your public key. If something goes awry you can always revoke the key.

Categories