I want to create an RSA private key which is not exportable (even by the developer of app) inside iOS keychain.
Is there any way to do that?
Not possible with RSA.
You can create keys which can't be exported, but only in the Secure Enclave, and it only supports p256 key pairs. You can't import existing keys into the Secure Enclave. While it is possible to export a key from it, the key is encrypted such that only that exact Secure Enclave can import it again later.
Related
I'm building a service using MTLS for authentication with AWS ACM PCA as private Certificate Authority.
The certificate is stored in a password protected PKCS#12 file together with the private key in.
The private key is also used for signing data.
At the moment I'm creating key pairs programatically but want to switch into using KMS.
However, it seem like it's not possible to get the private key from KMS.
How am I supposed to allow for both client authentication and signing if I can't add the private key to the PKCS#12 key store?
You can use kms.generateDataKeyPair to create and export a public key and private key which can then be used locally.
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.
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.
I would like to make HTTPS request with a server require client-certificate authentication. I looked into this Creating a SecCertificateRef for NSURLConnection Authentication Challenge. It worked as expected.
However, it needs to prepare the p12 file which includes the private key. It would be secured as it needs a password to import the p12 file using SecPKCS12Import().
However, there could be other option. That is the iOS-client should make a certificate signing request(.CSR) and let a third party (the server) sign it.
For my search, I see that I can use SecKeyGeneratePair() for generating a key pair. But I don't see any API that generate a CSR.
Do I really need OpenSSL to achieve this?
Also, a bit off topic, once the iOS-client somehow receives the signed certificate. I can use SecCertificateCreateWithData() to retrieve an SecCertificateRef(). However, to fill in a NSURLCredential. I also need the SecIdentityRef which come from p12 file using SecPKCS12Import(). How can I retrieve a SecIdentityRef without SecPKCS12Import() but just a certificate file like crt or der?
There is no explicit support for CSR in Security Framework in iOS. However, it is not that difficult to build CSR 'manually' - it is just ASN.1 DER block of data that are available at iOS runtime.
Here is pseudo code of that:
Use SecKeyGeneratePair() from Security Framework to create fresh public/private key
Implement getPublicKeyBits method to retrieve NSData-form of fresh public key (see https://developer.apple.com/library/ios/samplecode/CryptoExercise/Introduction/Intro.html )
Implement getPrivateKey method to retrieve SecKeyRef from Keychain
Follow http://www.ietf.org/rfc/rfc2986.txt to construct ASN.1 DER of CSR in NSMutableData
Use CC_SHA1_* to create signature hash of Certification Request Info (part of CSR)
Use SecKeyRawSign and private key to sign CSR
This will create proper CSR (in form of NSData) that can be sent to CA for approval.
My implementation is available on GitHub: http://github.com/ateska/ios-csr .
To anyone who comes across this in the future, I encountered outfoxx's Shield library which makes it super easy to create CSRs via Swift.
If I had a private certificate file and a string on the iPhone, how do I use them to generate a signed string that can be verified by a server with the matching public key? What library should I use on the iPhone?
I would take a look at Certificate, Key, and Trust Services Reference on Apple's website. You can import the PKCS #12–formatted blob with SecPKCS12Import and sign the data with SecKeyRawSign.