Store & access x509 certificate in iPhone's keychain - iphone

Can 3rd party application access iPhone's keychain in order to add X509 certificate to it? If yes, how can it be done?
If not, can it access keychain just to read certificates from it?
Basically, what I need is:
1) my application needs to access https site which uses certificate not signed by any trusted CA. when trying to connect via https, I get an exception.
2) it would be great If I could programmatically add the root's certificate to the keychain; it would be sufficient if the user could access the site via Safari, accept its certificate, and then access the site using my application.
So far, I've been using the following interface to surpass https:
#interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
#end
but this is not exactly what I want.
Any suggestions?

This Apple document should document enough stuff to permit adding self-signed certificate (or a self-signed certificate authority) into the keychain, and make it trusted. I didn't test it, though. Source
See also the top answer on this question. It, however, doesn't seem to actually verify the validity of the certificate. Cocoanetics has also documented how to use NSURLConnection with self-signed certificates, and similarly also doesn't seem to verify the validity.
So, you almost certainly want to follow Apple's instructions. The "Extracting and Evaluating an Identity From a *.P12 file" section appears to contain a complete example on how to import a certificate, even one protected with a passphrase.
Combine that with "AdvancedURLConnections" sample code and the ServerTrustChallengeHandler class and you should be good to go.
Here's also a more complete example by Vanja Komadinović.

Related

Requesting Client Certificate Dynamically

Web Servers have settings by which you request client certificates - for eg. SSLVerifyClient require in Apache, a different setting in IIS etc. If this is set, then the browser throws up a dialog asking you to chose a certificate.
Is it possible to ask for a certificate dynamically? i.e. I am really not interested in 2 way SSL - however, I want to ask the user to register his certificate with my application which will be used in a different context. So I need to let the user chose one of the certs registered in his browser and access the cert in my application. How do I do this?
Is this possible at all?
I have figured out one way to do this - I have a upload link in my application - this points to a Virtual Directory which has Client Side Authentication required property. So when the user clicks on the link - it triggers a SSL Renegotiation. The browser throws a dialog which lets the user chose from the registered certs. Once he chosen the certificate, SSL renegotiation happens and the I can access the cert in the application. The SSL renegotiation ensures that the user has the private key corresponding to the Cert.
If there any problems with this method or if there is a better way to do this, I am most certainly interested in doing it.
Also, I am currently doing this in IIS - but I think something like this should be possible in most other webservers also.

Signed PDF showing message "The validity of the document is unknown", iText

I am using iText to apply digital signatures in PDF. The digitally signed PDF is showing message like "the validity of the document certification is unknown. The author could not be verified.At least one signature has problems." at the top.
When I add the certificate to my trust identities which is used to create signed PDF, then the generated signed PDF shows "Signed and all signatures are valid".
Is it possible to fix this by without adding certificate to trusted identities?
Thanks in advance.
There are two reasons for the message to be displayed.
First, it's that you used self-signed certificate or other certificate, whose certificate chain doesn't end with the root certificate, trusted by validating application.
Second is when the signature parameters are not set right and Reader doesn't know that it needs to look for certificates in Windows certificate store. I don't know how to specify what I mean in iText - in our SecureBlackbox there's a property for this.
Please read https://itextpdf.com/book/digitalsignatures
Section 3.4 is named "How to get a green check mark."
The short version: if you want a PDF that shows a green check mark without having to install a root certificate manually, you need at least a private key that is stored on a physical device such as a Hardware Security Module, a USB token or a smart card.
Do you have such a key? Did you ask your CA for CDS or AATL certificate?
Re: Is it possible to fix this by without adding certificate to trusted identities?
Answer: no, unless you switch to a digital signature cert that was granted by a Certificate Authority trusted by Adobe.
This is an on-going issue with Adobe since Adobe Reader doesn't trust the CA's in the operating system. -- Instead, Adobe has their own list.
So either:
You get a personal cert from one of the companies on the Adobe list.
You publish your organization's root certificate on your website and provide instructions to recipients on how to tell Adobe to trust you. (Your organization can have just one member if you wish.) See below for more on this.
You tell your recipients how to click on the Adobe signature toolbar to inspect the details of the signing cert (and ignore the scary default warnings from Adobe).
In the wet-signature world, there are cases where you simply sign something, and other cases where you need to provide a copy of your government issued identity document. Unfortunately, in the current digital signature world, it's as if every signature needs to be accompanied by a copy of your driver's license. And that is simply not reality.
A common and successful answer is to publish your organization's root cert for all of the organization's signers. See Apple and Wells Fargo examples.
You can publish your root cert on an SSL-protected page with a cert from a trusted CA. That will enable a business partner to feel secure about trusting that your org's root cert is really from your org.

How can I access identity profiles and certificates with iPhone SDK?

I am trying to verify the user identity on my application using a certificate / identity that the user has stored by opening a .cer / .p12 attached to an email. The certificate appears on the settings app of the phone under the group "Configuration Profiles".
Is there any way of accessing the certificate using the iphone SDK (I have tried to use the Security Framework, but it seems that it is only possible to access certificates stored in the application keychain or other keychains from its group)?
You talked about the Security framework already, but did you try the following functions in the doc?
I personally never tried/had to do this myself, but anyway it seems that there are some functions like SecCertificateCreateWithData in the framework, so you should be able to build a SecCertificateRef from some NSData/CFDataRef… data which is the content of your mail attachment.
From there you may use it as any other certificate using the other functions (like you would do for a certificate extracted from the Keychain)
Well this is only a guess after simply reading the documentation but let's give it a try as the doc seems to indicate it is the way to go.

How to securely communicate with server?

I'm building a solution consisting of an app and a server. Server provides some methods (json) and the app uses them. My aim is to make those API methods inaccessible to other clients. What is the best way to do so?
Should I take a look at certificates (to sign every outgoing request)? If yes, where do I start and what is the performance impact of doing so?
What are alternatives?
Put another way, you need a way to distinguish a valid client's request from an invalid client's request. That means the client needs to present credentials that demonstrate the request comes from a valid source.
SSL certificates are an excellent way to assert identity that can be validated. The validity of an SSL certificate can be confirmed if the certificate contains a valid signature created by another certificate known to be secure, a root cert. As noted in other answers an embedded certificate won't do the job because that certificate can be compromised by dissecting the app. Once it is compromised, you can't accept any requests presenting it, locking out all your users.
Instead of one embedded app cert, you need to issue a separate certificate to each valid user. To do that, you need to set up (or outsource to) a Certificate Authority and issue individual, signed certificates to valid clients. Some of these certificate will be compromised by the user -- either because they were hacked, careless or intentionally trying to defraud your service. You'll need to watch for these stolen certificates, place them on a certificate revocation list (CRL) and refuse service to these compromised certificates. Any web server is able to refuse a connection based on a CRL.
This doesn't solve the security issues, it just moves them out of the app. It is still possible for someone to create what appears to be a valid certificate through social engineering or by stealing your root certificate and manufacturing new signed certificates. (These are problems all PKI providers face.)
There will be a performance hit. How much of a hit depends on the number of requests from the app. The iPhone NSURLConnection class provides support for SSL client certificates and client certificates can be installed in the phone from an e-mail or authenticated web request. Managing the infrastructure to support the client certs will require more effort than coding it into the app.
Incidentally, voting down any answer you don't like creates a chilling effect in the community. You're not nearly as likely to get advice -- good or bad -- if you're going to take a whack at everyone's reputation score.
I will now freely admit that it's an interesting question, but I have no idea how it could be done.
Original answer:
Interesting question. Assuming people can't reverse-engineer the iPhone app, the only solution that comes to mind would be to sign requests with a public key, or some other secret known only to the application. By that, I mean adding an extra argument to every API call that is a hash of the destination URL and other arguments combined with a secret known only to your server and application.
To expand upon this: suppose your API call has arguments foo, bar and qux. I would add a signature argument, the value of which could be something as simple as sorting the other arguments by name, concatenating them with their values, adding a secret, and hashing the lot. Then on the server side, I would do the same thing (excepting the signature argument) and check that the hash matches the one we were given in the request.
Consider authenticated HTTP.
For a cheaper alternative, there's shared secret/hash scheme. The client and the server have a shared secret string of text. Upon request, the client hashes together (using MD5, or SHA1, or SHA something else - you choose) the request fields and the secret. The hash value is attached to the request - say, as another POST field.
The server does the same operation with the request and with its copy of the secret, then compares the hash values. If they don't match - service denied.
For added security, you may encrypt the hash with a RSA public key. The client has the public key, the server keeps the private key. The server decrypts the hash with the private key, then the same. I did that with a C++ WinMobile client and a PHP-based service - works like a charm. No experience with crypto on iPhone, though.
UPDATE: now that I think of it, if we assume that the attacker has complete control over the client (ahem jailbroken iPhone and a debugger), the problem, as formulated above, is not solvable in theory. After all, the attacker might use your bits to access the service. Reverse-engineer the executable, find the relevant functions and call them with desired data. Build some global state, if necessary. Alternatively, they can automate your UI, screen scraper style. Such is the sad state of affairs.

Add custom certificate for iphone HTTP API

Is there any way to bundle a certificate in my application - and then use that to perform HTTP GET/POST using a NSURLRequest?
I.e. the certificate should not be used for other HTTP traffic on the device, only by my application.
Cheers
I don't believe so, but since all applications are sandboxed any special authentication measures you may have within your application cannot be accessed by other applications.
Best (in my opinion) you put the private key and certificate that you want to use on the keychain (or keychains of other 3rd party apps that share the same provisioning certificate).
As for the actual loading of the p12 we do use openssl (we did write a obj-c wrapper around it) to decode the .p12 that we send to the app (you can always use .DER or .PEM to ship the p12 with your app)