I am using Mifare Ultralight C to make a access control system.
The method I am using is based on the UID of the card.
I can read the UID by NFC Reader (SeeedStudio shield on Arduino UNO)
However, the UID is not reliable since there are writable UID card out there in the market. So I think that I should secure the connection by 3DES authentication and then block the reading from 0x00 which is from the first serial number byte.
Is it the correct way to implement access control?
You cannot block read access to the UID. The UID is an immanent part of the anticollision/tag enumeration phase of ISO 14443 so the tag will always reveal that information. Moreover, Ultralight C permits read/write protection only from page 3 to the end of the memory.
What you could do is the following:
Use the UID to identify the tag.
Derive a tag-specific key based on a master key and the tag's UID.
Ktag = fkey_derivation(UIDtag, Kmaster)
Use that key Ktag as 3DES key for the Ultralight C authentication.
Protect (read and write) the whole data memory of the tag.
Possibly store some additional authentication information on the tag (e.g. a signature over the UID). However, you should keep in mind that after authentication read operations are neither encrypted nor integrity protected. This means that an attacker could potentially retrieve the data stored on a tag by listening into the communication between a legit tag and a legit reader. Moreover, an attacker might be able to authenticate with a legit tag and then intercept any further read commands to return manipulated data. Basically this means that you should refrain from storing any non-integrity-protected permission information on such a tag.
And finally: MIFARE Ultralight C is certainly not meant to be used for access control!
Related
I'm building an app and I'm being very cautious about the user privacy on the app. I do not want to collect any data. Not even email IDs. Is there any way to do user authentication without email/phone number?
One idea for now is using biometrics on the phone itself. FaceID/TouchID etc. But that brings up challenges wrt syncing their data in case the user wants to use from a different phone. Any workarounds?
You can safely collect as much data as you like inside the app, so long as it stays there.
The problem is that you want to reliably identify a user account (though not any specific user data) without letting any of that data out. It's become quite common to use hashes (usually SHA256) of email addresses as identifiers, however, if everyone uses the same approach it's like a distributed rainbow table. You can however deploy the usual defence against such attacks by salting your hashes so that they are unique to your service.
If you encrypt the user's data on-device using a key that only they know, and only ever transmit and store encrypted data (i.e. to which you have no access), then they would be able to use the same local identifiers and their key to read the data from a different device. Because data is only ever encrypted and decrypted with the same key you can use symmetric encryption - look at using libsodium to do this.
You might want to consider some kind of 2FA to go with this as otherwise intercepting this identifier could allow unauthorised access.
Depending on the sensitivity of the traffic, you may want to try to hide meta-information such as connection dates, times, and volumes, so you could get the app to generate random data to hide the real data within.
Disclaimer - I Am Not A Cryptographer! I recommend you ask for more qualified responses on https://security.stackexchange.com.
I am struggling on thinking how to do an auth system which allows arbitrary clients that share the same source code but have random uuid based identifiers to authenticate. A requisite for that is that the clients must not need human interaction to login to that server, think of it kind of an automatic IoT device that needs to login to a central server but can't receive user input.
For my use case, I don't need it to be a very secure system. But at least it would be nice to have some kind of impediment to attackers.
My first approach is using the identifier uuid as a username, and a function that hashes the identifier with other dynamic values along with a secret, but that seems to me a bit hacky... The hash generated must be constant for each device.
The clients can't use non-simple hashing/encryption methods. Here's a list of things they can compute: MD5 hash, SHA1 hash, XORs between two base64 strings, SHA256 hash and ARCFOUR.
The server, however, can compute any encryption/hashing algorithm, and the identifier of the device is public and can be accessed by anyone. However, the source code is private and the communication is made with https.
Any ideas of how to achieve this with a better auth method? (Taking into account these restrictions)
You say the IoT device cannot receive user input. Can it display or communicate anything to the user? If so, you could consider the OAuth2 device flow.
Your IoT device would be polling the authorization server.
You can use the browser on your phone or computer to authorize the IoT device.
Let's say I have a program written in VB.Net with encryption code that relies on a key being set to encrypt and decrypt. How do I securely store the key in the program? If it's plain text in the code, it could be reverse engineered. If it's a setting, then it is stored as plain text in the x.exe.config file and even easier to find.
Can the x.exe.config file be set to encypt? If not, what's the safest way of hard coding the key into the program?
The method I've used is encrypted using a different method, then encode that (as it's non-ascii text) and store that in the settings, but that in turn could be decoded if the program is reverse engineered.
What do other people do in this situation?
You've set to an impossible task. The problem is that by hardcoding the key into the program, as you've noted, the user can still get the key by reverse engineering. If you put it in a file somewhere, the program needs to be able to read it, and therefore the user can also access it in the same way.
The fundamental problem you have is that the software needs to access the key, and for that, the key must be stored somewhere it's reachable by the user too. It can be within the binary or in the computer, but the binary can be analyzed and the file system can be inspected. Encrypting a file protects the key, but just recreates the problem with the new key.
This is also the very same problem that all DRM schemes face. They give users access to the the full software but want to limit it in some ways, but the user has everything in his computer to run the software. That's why it's always possible to pirate every desktop software, if enough effort is put towards it. You only can make it more difficult by obfuscating the key.
But what can you do then?
An alternative approach is to not have the user to have the DB credentials at all. Or make them useless for anything significant. I can think of two approaches here:
Have the system communicate with a webservice and never to the DB directly. This way, the user only knows the address of the server and the WS can request any authentication as needed, before going to the DB. The WS is then the only one to ever touch the DB. This is what all websites do in practice, the visitor doesn't ever sees the DB, but interacts with it though the web server.
Another option would be to give the user direct DB access, but those credentials only give permission to call some stored procedures (or access views without sensitive data) and those in turn request some sort of authentication before proceeding. This way the DB credential becomes not that sensitive as long as its permissions are kept to the bare minimum and privileged actions are properly validated before proceeding.
My application connects to many other application and so i need to store user names/passwords of other applications in my database.
I do not want to store them as plain text, but my application will need to send a plain text password for authentication to other.
Please suggest the best way to securely store the passwords.
Thanks.
Use a reversible encryption (AES, probably) on the sensitive data fields in the database, and have your app decrypt it every time it needs the value. You'll need to have the encryption key accessible to your application somehow, but that should probably be in a deployment-specific config file.
This will protect you if someone gets a dump of your database but not a dump of the filesystem where your app resides.
It's rarely necessary, if ever, to use a reversible encryption strategy to store passwords. The reason for storing a password is so the user can prove their identity to you (for some value of "prove") at some point in the future, and that can generally be done with a one-way hash like MD5 or SHA1.
Using a one-way hash to store your passwords does protect your users against an intruder getting access to your system, since there is no key that will allow them to obtain the plaintext from the encrypted passwords.
I have been following a couple of articles regarding RESTful web services with WCF and more specifically, how to go about authentication in these. The main article I have been referencing is Aaron Skonnard's RESTful Web Services with WCF 3.5. Another one that specifically deals with HMAC authentication is Itai Goldstiens article which is based on Skonnards article.
I am confused about the "User Key" that is referenced to in both articles. I have a client application that is going to require a user to have both a user name and password.
Does this then mean that the key I use to initialise the
System.Security.Cryptography.HMACMD5 class is simply the users
password?
Given the method used to create the Mac in Itai's article
(shown below), am I right is thinking that key is the users
password and text is the string we are using confirm that the
details are in fact correct?
public static string EncodeText(byte[] key, string text, Encoding encoding)
{
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = encoding.GetBytes(text);
byte[] encodedTextBytes =
hmacMD5.ComputeHash(textBytes);
string encodedText =
Convert.ToBase64String(encodedTextBytes);
return encodedText;
}
In my example, the text parameter would be a combination of request uri, a shared secret and timestamp (which will be available as a request header and used to prevent replay attacks).
Is this form of authentication decent? I've come across another thread here that suggests that the method defined in the articles above is "..a (sic) ugly hack." The author doesn't suggest why, but it is discouraging given that I've spent a few hours reading about this and getting it working. However, it's worth noting that the accepted answer on this question talks about a custom HMAC authorisation scheme so it is possible the ugly hack reference is simply the implementation of it rather than the use of HMAC algorithms themselves.
The diagram below if from the wikipedia article on Message Authentication Code. I feel like this should be a secure way to go, but I just want to make sure I understand it's use correctly and also make sure this isn't simply some dated mechanism that has been surpassed by something much better.
The key can be the user's password, but you absolutely should not do this.
First - the key has an optimal length equal to the size of the output hash, and a user's password will rarely be equal to that.
Second, there will never be enough randomness (entropy to use the technical term) in those bytes to be an adequate key.
Third, although you're preventing replay attacks, you're allowing anyone potentially to sign any kind of request, assuming they can also get hold of the shared secret (is that broadcast by the server at some point or is it derived only on the client and server? If broadcast, a man-in-the-middle attack can easily grab and store that - height of paranoia, yes, but I think you should think about it) unless the user changes their password.
Fourth - stop using HMACMD5 - use HMAC-SHA-256 as a minimum.
This key should at the very least be a series of bytes that are generated from the user's password - typically using something like PBKDF2 - however you should also include something transitory that is session-based and which, ideally, can't be known by an attacker.
That said, a lot of people might tell you that I'm being far too paranoid.
Personally I know I'm not an expert in authentication - it's a very delicate balancing act - so I rely on peer-reviewed and proven technologies. SSL (in this case authentication via client certificates), for example, might have it's weaknesses, but most people use it and if one of my systems gets exploited because of an SSL weakness, it's not going to be my fault. However if an exploit occurs because of some weakness that I wasn't clever enough to identify? I'd kick myself out of the front door.
Indidentally, for my rest services I now use SCRAM for authentication, using SHA512 and 512 bits of random salt for the stretching operation (many people will say that's excessive, but I won't have to change it for a while!), and then use a secure token (signed with an HMAC and encrypted with AES) derived from the authentication and other server-only-known information to persist an authenticated session. The token is stateless in the same way that Asp.Net forms authentication cookies are.
The password exchange works very well indeed, is secure even without SSL (in protecting the password) and has the added advantage of authenticating both client and server. The session persistence can be tuned based on the site and client - the token carries its own expiry and absolute expiry values within it, and these can be tuned easily. By encrypting client ID information into that token as well, it's possible to prevent duplication on to another machine by simply comparing the decrypted values from the client-supplied values. Only thing about that is watching out for IP address information, yes it can be spoofed but, primarily, you have to consider legitimate users on roaming networks.