Safely setup Sha256 keys in the keychain - iOS APP - ios

I would like to secure the communication from my APP to the server with Sha256.
For this I need some common keys on either side (APP/Server).
How do I get these keys into the keychain without setting them up as plaintext when storing them? No point in having them in the keychain if the APP can be decompiled and the keys are visible in plain text anyway.
The plan was also to have a password and username for communication verification. Both stored in the keychain, and the password as just the Sha256 key stored in the keychain and not the actual password.
I would still like to secure my Sha keys.

Related

What is difference between Keychain and Secure Enclave

I've been in searching where keychain stores either secure enclave or any other, I found many articles (one of this stackoverflow answer) which says following but I'm looking for some Authenticated like Apple statement
The keychain stores the keys (and other small data) encrypted and restricts access to that data. Additionally in recent iPhones (5S and later) the keychain is in a separate processor, the Secure Enclave which additionally restricts access. There is no more secure way to store keys in iOS.
So my queries on the basis of above statement.
Is Keychain Items store in secure Enclave
If yes then where Public key and Private key CFTypeRef Store
Why we use this kSecAttrTokenIDSecureEnclave while creating key pair. (example following code).
-(bool) generateKeyPairWithAccessControlObject:(SecAccessControlRef)accessControlRef
{
CFMutableDictionaryRef accessControlDict = newCFDict;;
CFDictionaryAddValue(accessControlDict, kSecAttrAccessControl, accessControlRef);
CFDictionaryAddValue(accessControlDict, kSecAttrIsPermanent, kCFBooleanTrue);
CFDictionaryAddValue(accessControlDict, kSecAttrLabel, kPrivateKeyName);
// create dict which actually saves key into keychain
CFMutableDictionaryRef generatePairRef = newCFDict;
CFDictionaryAddValue(generatePairRef, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);
CFDictionaryAddValue(generatePairRef, kSecAttrKeyType, kSecAttrKeyTypeEC);
CFDictionaryAddValue(generatePairRef, kSecAttrKeySizeInBits, (__bridge const void *)([NSNumber numberWithInt:256]));
CFDictionaryAddValue(generatePairRef, kSecPrivateKeyAttrs, accessControlDict);
OSStatus status = SecKeyGeneratePair(generatePairRef, &publicKeyRef, &privateKeyRef);
if (status != errSecSuccess)
return NO;
[self savePublicKeyFromRef:publicKeyRef];
return YES;
}
Looking for authenticated answer. Cheers
Take a look at Apple's iOS security whitepaper, it describes what Secure Enclave and Keychain are exactly.
A Secure Enclave is a coprocessor fabricated within the system on chip (SoC). It uses encrypted memory and includes a hardware random number generator. As for the Keychain, the iOS Keychain provides a secure
way to store these (passwords and other short but sensitive bits of data) items. [...] The Keychain is implemented as a SQLite database stored on the file
system..
Keychain is a piece of software that stores encrypted data (such as passwords) in a SQLite database. The key that encrypts this data is inside the Secure Enclave - it never leaves the SE, as per this paragraph
Keychain items are encrypted using two different AES-256-GCM keys, a
table key (metadata) and per-row key (secret-key). Keychain metadata
(all attributes other than kSecValue) is encrypted with the metadata key
to speed search while the secret value (kSecValueData) is encrypted
with the secret-key. The metadata key is protected by Secure Enclave
processor, but cached in the application processor to allow fast queries
of the keychain. The secret key always requires a round-trip through the
Secure Enclave processor.
To answer your question: are keychain items stored inside Secure Enclave, no, they are stored inside a SQLite database on disk, but the encryption key needed to decrypt this data is inside the Secure Enclave. As for kSecAttrTokenIDSecureEnclave that apperas to be a flag that indicates that the key should be generated inside the Secure Element.
Not all keychain items are stored in secure enclave
From Apple document
The only keychain items supported by the Secure Enclave are 256-bit elliptic curve private keys (those that have key type kSecAttrKeyTypeEC). Such keys must be generated directly on the Secure Enclave using the SecKeyGeneratePair(::_:) function with the kSecAttrTokenID key set to kSecAttrTokenIDSecureEnclave in the parameters dictionary. It is not possible to import pre-existing keys into the Secure Enclave.
The Keychain uses Secure Enclave, the Secure Enclave is implemented in hardware.
From what I understand:
By default asymmetric key-pairs are created and stored in the secure enclave. The private key is available only at creation time and can not be obtained later. Asymmetric operations that use the private key obtain it from the keychain without exposing it to user code.
There is an exception that allows access to the private key, the Keychain Access app.

Storing encryption key within iOS app?

I need to store an encryption key within my app, so that it can use the same key to encrypt and upload data, and download and decrypt data, from a public store. That way, the data can't be read by any other party in between.
What I'm concerned about is the potential for somebody to hijack my app. Once my app has been archived, would it be possible for someone to read a hardcoded encryption key held within the app?
If the key is in the app bundle there is a chance it can be discovered and doing this is not secure. As #Cristik states authenticate the user to the server and download the key at that point.
To secure the key the best you can do is to save the key in the Keychain.
Protecting against the owner of the device is very difficult and falls more under DRM.
Protecting against an non-owner depends on the owner having set a good passcode/password.
Protecting against data in transit (upload/download) is easy, use https, ensure the server is current (TLS 1.2 and Perfect Forward Secrecy) and pin the server certificate in the app.
Update:
In the ipa only the executable files are encrypted so other files can be accessed from the download. If a file is encrypted the attacker will need the encryption key and that can be strong: random bytes.
But the app needs the encryption key so the problem is how can the app know the key and not an attacker. Encryption does increase the work factor be the need to obtain the key.
There are disassemble tools so if the key is in the code it can be found by an experienced attacker.
If the key comes from a server it is not coded into the app so the work factor again increases. A MITM attack can be used to see the key in transit and pinning the certificate and using current https best practices can mitigate this attack vector.
Finally the key is in RAM memory at the time of decryption and can be found but again the work factor is increased.
In general what is necessary to protect data at the highest levels is complicated, requires special hardware and physical security.
Bottom line: determine the level of attacker you are defending against and the value of the data; code to that level. Do not underestimate the attacker.
Instead of storing the encryption key within the application bundle, you can request it from a server via a secure connection (HTTPS), and then save it in keychain for later retrieval.
You can add more security layers to the https connection by adding SSL pinning or/and other security measures.
Plus, you can generate different encryption keys every time the user logins, and if the store API supports it, you can invalidate all keys generated for a user if for example his phone is stolen.

Storing encrypted version of user's email password on my app's server

I'm working on an iOS app where I need to store user's credentials for a 3rd party service on my server. (For example, storing IMAP login/password so that when they sign into my app it fetches from their IMAP server, so my server doesn't store their email)
I am not considering OAuth since not every email service provides OAuth. To do this I was thinking about the following option:
User enters username/password to sign into MyApp (MyApp server implements standard security measures, meaning it stores hashed version of the password and not the raw password, so MyApp server does not know what a user's password is)
Once signed into MyApp, MyApp stores the raw password into local keychain.
User 'connects' their 3rd party email account by signing into the 3rd party email account.
When the 3rd party email account successfully signs in, MyApp encrypts the email's password using the MyApp password (which is stored in keychain from step 2)
The encrypted password is stored on MyApp's server as "emailPassword"
From then on, whenever user signs into MyApp, MyApp fetches the encrypted "emailPassword" from MyApp's server and decrypts it back to its original form using the MyApp password stored locally on the user's keychain (which was used to encrypt in step 4).
Using the raw password decrypted from step 6 MyApp fetches emails from the 3rd party email server.
I am new to encryption so not sure if this is a safe (or even possible) option. Could anyone help? Thank you.
[UPDATED] Updated to clarify concepts and changed "encoded" to "encrypted"
You should rather say "encrypt", not "encode". Encoding is a mechanism which translates data using some set of fixed rules (algorithm). Base64 is an encoding, so is urlencoding. Encoding doesn't provide ANY security.
Encryption, however translates cleartext to ciphertext using an algorithm that uses crypto keys. Without knowledge of the key, the reversion of the ciphertext is very hard. (never impossible)
Okay, regarding your example:
It is implementable, but even though there are some attacking chances.
At some point in runtime, MyApp knows the cleartext password. At the time it is decrypted. The plaintext password then lies in RAM and could possibly read out by malicious software with respective permissions (root malware e.g.)
Also you need to make sure to use suitable algorithms in the right mode. AES-256 in CBC is more secure than in ECB mode. Then you also have to think of how to convert the password into a crypto key. Would not be too secure if you just used the password. Then you should also use a trustworthy library, no library from an unknown guy or so
Well, these are just some thoughts. You should get a little background knowledge before struggling with encryption. There are many options and you should really know, what you do.

iOS Security: Web server and File system

I have gone through apple developer videos on Security they have mentioned to use ssl https certificates and keychain to deal with security.
My iOS app will be giving access to sensitive paid files. so hackers should not get access to these files. I will be using in app purchase, so that user can buy these file.
1) My first question is: Should i host my files on apple server (Hosted Contents) , is the apple to client communication secure enough or should i implement my own server code with certificates and ssl authentication.
2) i want to know or get idea on how to encrypt files using private key on my desktop machine and then upload it on my server. When asked for by my iOS app pass the public key and encrypted file and save the public key in Keychain for further use. I want this feature so as to save the file on disk without anyone getting access to it by jailbreaking or other hack.
3) What should be used as public and private keys and what type of encryption to use. Currently i have come across AES looks good enough but is there a better way? Can certificates itself used to encrypt data or pass keys?
4) Which certificate authority to contact for most secure certificates.
Thanks in advance...
EDIT:
Main purpose to achieve is to download pdf and that pdf should not be accessible to user outside the app.
1) I have decided to use root certificates from CA and https to transfer content, to avoid MINM.
2) On app side i will generate public private key pair.
3) Save Private key in keychain.
4) Send Public key to server.
5) Server will encrypt pdf using MAIN-AES-Key.
6) MAIN-AES-Key will be encrypted using Public key sent by app.
7) Encrypted-pdf and Encrypted-MAIN-AES-Key will be sent to app.
8) Encrypted-pdf will saved to disk with secure write options just incase.
9) Encrypted-MAIN-AES-Key will be saved in keychain.
10) To decrypt pdf: Private key generated by app will be used to decrypt Encrypted MAIN-AES-Key and MAIN-AES-KEY will be used to decrypt pdf.
11) Finally will be trusting Apple-KeyChain to keep Private-Key secure.
The solution is unnecessarily complicated. The more complicated, the less secure due to more potential errors/over-sights.
Do use https with a CA signed certificate
To avoid MITM pin the certificate on the app side
There is no need to further encrypt the data being sent over https
Encrypt the file on the device and save:
Create an encryption from random bytes
Save the key in the Keychain
Create an iv from random bytes
Add the iv to the beginning of the encryption buffer
Encrypt the data with AES, CBC mode and PKS7 padding into the buffer following the iv
Save the data into a file the the app file area, possibly under the Documents or Library directory
Decrypt the file on the device and use:
Get the key from the Keychain
Read the encrypted data file
Get the iv from the beginning of the data
Decrypt the data starting just past the iv
Do not ignore the server
Use two factor authentication.
Properly hash with a salt any passwords
Use good user authentication
For the app data encryption consider using RNCryptor instead of writing the encryption portion yourself.

Recover signing certificate without p12 password?

I've been handed an iOS app codebase, which I'd like to distribute via the existing Enterprise certificate used by the prior developer.
After importing the provided .mobileprovision file, I'm (not unsurprisingly) getting the "Valid signing identity not found" error. Specifically when building:
The identity '[name]' doesn't match any valid, non-expired certificate/private key pair in your keychains
I was given the original CertificateSigningRequest.certSigningRequest file, a .p12 file, and the .cer file. I was not given the password to the .p12 file.
Is it possible to rebuild what I need from the CertificateSigningRequest.certSigningRequest without the .p12 file's password? I can likely get the .p12 password, but not in a timely manner.
Thanks!
I recognize that you've solved your issue by getting the password for the .p12 file, but I thought I'd shine a little light on what lives in each of those files you mentioned for the benefit of anyone running across the question in the future.
To answer the main question in this question: Can I rebuild what I need from the CertificateSigningRequest.certSigningRequest file?
Regrettably the answer is a very solid 'No'. The root cause of this is the very heart of Public Key Infrastructure (PKI), a set of management technologies, people, and practices dealing with the creation, verification, use, and revocation of digital certificates. Central to PKI is the notion of a public-private key pair. The 'Public' key is the one you share widely, anyone may have a copy of it and anyone wishing to validate messages signed by a digital certificate will require access to this key. The 'Private' key is the linked key that only you (or more accurately, your machine) knows and uses when signing messages. It is this signature that is verified via use of the 'Public' key that is shared widely authenticating that the message is in fact authentic.
When we are constructing development or distribution certificates, we are inherently asking Keychain Access, openssl, or your preferred SSL toolchain to create a public-private key pair. The public key goes into the CertificateSigningRequest file along with the other 'Subject' fields like name and email address and we ship this file off to Apple. That file primarily tells Apple what Public Key they can use to validate your app signature -- it does not give them a copy of your Private Key after all, if others had your private key they'd be able to codesign as you effectively destroying the notion of accountability on the iOS platform (ex. This App's signature checks out as valid, but I still don't know if it was actually signed by a developer I trust...). At no point in time, is your Private Key transmitted to Apple or the Developer Portal; it resides quite happily in your Keychain until such a time as 1) The certificate expires, 2) you actively revoke the certificate from the Developer Portal, or 3) you accidentally (or intentionally) delete the keypair from Keychain.
So what lives in each of these files?
CertificateSigningRequest.certSigningRequest - This contains a copy of the Public Key from the Public-Private keypair you generated locally, plus some additional required subject information required by the Certificate Signing Request format. Apple disregards this additional information and uses the name and email address they have on file for your Developer Account when constructing your certificate.
.p12 - This is a PKCS#12 formatted file containing a copy of the Apple-issued Certificate (which itself contains the Public Key) and a copy of the linked Private Key. This data is encrypted to prevent unauthenticated access and thus requires a password to decrypt.
.cer - This is the Apple-issued Certificate that contains the Public key portion of the key pair. This certificate is used by Apple to validate that Apps you submit are not tampered with while in transit to the App Store review team:
You sign your app using the Private key that only you know and upload the signed binary to Apple.
Apple then validate the signature using the public key that you've already shared with them.
If the math works out, then the App hasn't been tampered with and you are good to go.
If the math doesn't work out, either the app was tampered with, or (much more likely) the certificate was revoked or regenerated and the app was signed with an old or incorrect key pair.
As you can see, the only places the Private Key resides is in the original developer's keychain as well as the encrypted .p12 file. Consistent with both your comment and flup's comment, you either have to get the password to that .p12 file or look into breaking through the encryption.
Regardless, good to hear that you were able to get the password from the original developer. Let me know if you have any followup questions.

Resources