Thank you for taking the time to read this, I am a young developer, with some professional experience in web projects and server-side coding, but I am now building my first mobile application and after an in-depth research online I have not been able to clarify some questions I had about securing the data transfers from a mobile application.
Here is what I think I understand correctly : By implementing an SSL certificate (and optionally SSL-pinning on the client) you prevent to a large extent the sniffing of user information on open networks, and the impersonification of other users (Man-in-the-middle etc). Any further layer of security is designed to protect the server and prevent someone from gaining insights on your transaction structure and details. Further layers of security include message authentication (HMAC for example) to authenticate a message before processing it, and encryption to "hide" the content of the message.
I would like to implement an Encrypt-then-HMAC process to secure further the transactions and this is my question regarding this process : How do you store the key/secret on the client? I realize this will vary depending on the specifics of the application, and the degree of security it wishes to achieve. For this reason I am including some specifics : there is no highly sensitive information about the user being stored or transferred (SSN, banking etc), but the app does handle payments, and therefore high costs could be incurred if someone started messing with the server and payment system. I am therefore looking to implement a secure transfer between the client and the server, without doing something out of the ordinary or disproportionate in effort.
I have read a lot about the subject and from what I could gather, no matter which way you derive the key or secret, at some point it will be presented in plaintext to the encryption/hashing logic, and therefore someone will be able to debug the app, breakpoint that step and compromise the key/secret. How do you get around that (and can you)? What would be considered "appropriate" (hardcoding? deriving from table structure or other elements? other?).
This question is really meant to be high-level and conceptual, so I don't think it matters which platform I am discussing, but anyway at the moment I am coding the iOS application, and the backend is .NET
Thank you very much for your time, any help or insight would be greatly appreciated. If I can clarify any aspect of the application I would be happy to do it. Best, Michel
You have done a good job of identifying that handling the key is in fact the hard part.
There is one error, it is possible to have a system that never exposes the keys and that is what the banking industry does. That is because the encryption/decryption is done at each stage by hardware. The hardware has the key internally in such a way that it can not be extracted from the device. One simple example are smart cards as found in cell phones and credit/debit cards in Europe. Another is in HSMs (hardware security modules) used by banks and other financial entities in the communications chain. Even the PIN pads on ATMs perform the encryption in hardware in the keypad itself. I mention all this because you state the application is involved in monetary transactions.
If the client is an iOS device you can store the key in the
keychain
, it is a cryptographically secure part of the hardware that is a TPM (Trusted Platform Module) equivalent. It is protected by the PIN the device PIN, note that the PIN can be set to have more than the default four digits. On-device attacks, even on jail broken phones, must use the keychain and attempts have a minimum time per attempt (by design) thus ensuring a minimum average attack time based on the PIN complexity. Off the device the only attack available is brute force which is infeasible.The weak point is that the key will be in the clear during encryption and decryption. If the key is ever in a Foundation object (ex: NSString/NSData) there is a potential that it will survive after it's use, it is best to stay with "c" char arrays and clear them after use.
OK, the practical solution: Hire a crypto domain expert if you really want security. At a minimum hire one to advise and vet the design and implementation, I do. Look for someone with a CISSP certification and experience in the area of encryption. The CISSP requires a minimum of five years working 100% in the field under direct supervision, a six hour test and generally about 160 hours of test study time and 40 hours of continuing education per year.