I have a project, where I make a request to a server (https). The server has only a self-signed certificate, so I get an error: 'The certificate for this server is invalid. You might be connecting to a server that is pretending to be ...'. The problem is, that I have no access to the NSURLConnectionDataDelegate, because it is in a framework (I cannot even see the header of the class that implements the protocol).
I have the pem certificate of the server. Is there a way to add it somehow to my project, and the server to be considered safe? For now, I need it to work only in simulator, so if I could add it only to the simulator, that would also be great. Thanks in advance
Better you start to check out the MKNetworkKit. As far as I know support pem. It is released under attribution license, or you can pay it. Here is the link MKNetworkKit
Related
TL;DR version: Is there any way to pass a Server certificate to an iOS client that doesn't involve also passing along the Server's private key?
I have written an iOS client app that communicates with my macOS server app (so I have control over both ends). I have implemented certificate pinning using a self-signed certificate to make things more secure. To accomplish this during development, I hardcoded the Server cert into the iOS client app and told the client to only connect to a server that gives you that exact cert during the TLS handshake. Everything is working great.
However in the real world I am selling this system as a set (1 Server, multiple clients to each customer), so I cannot hardcode a Server cert into the iOS client. My plan is to instead deliver the Server cert out of band (via email) to the iOS client like mentioned here: Making Certificates and Keys Available To Your App:
Apps can only access keychain items in their own keychain access groups.
To use digital identities in your own apps, you will need to write code to import them. This typically means reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import
One way to provision an identity is via email. When you provision a device, send the associated user an email with their client identity attached as a PKCS#12 file.
My problem is that a .p12 file contains the certificate and the private key of the server - this seems very wrong to pass the private key along as well.
Is there any other way to pass the Server certificate to the iOS client that doesn't involve also passing along the Server's private key?
Thanks!!!
I was overthinking things here, the solution is actually pretty simple.
I just needed to email the Server's public certificate out of band to the client device with a custom extension like cert.myCustomExt1234. This is because the .crt extension is already claimed by iOS so you have to register your app to handle custom extensions (see apple docs here). Then in my app I can do all the logic of cert pinning using that out of band delivered Server public cert.
The key was changing the file extension to something not already claimed by iOS.
I've written a utility app for loading data into shopify through the rest API.
Having a strange error where the api only works when I'm running Fiddler.
Any idea what's going on? I'm sure it's a configuration issue rather than a code issue.
When Fiddler is running web access is through a proxy on 127.0.01:8888.
I'm not advanced enough on SSL to figure this one out. Do you need a self signed certificate to connect to an SSL API.
I found a few posts suggesting setting ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls but that didn't fix it!
>> Do you need a self-signed certificate to connect to an SSL API.
We faced similar issue with our application. If API has any certificate errors (In our case, we are using self-signed certificate), Browser will not allow you to interact with API.
Solution : Install your root Certificate, so that browser will start honoring your self-signed certificate.
>> Having a strange error where the api only works when I'm running Fiddler. Any idea what's going on? I'm sure it's a configuration issue rather than a code issue.
Whenever you enable HTTPs traffic decryption in fiddler (see below image for enabling this setting in fiddler), below things will happen.
Fiddler will automatically install its root certificate
"DO_NOT_TRUST_FiddlerRoot" to Browser's CA list.
Fiddler will use your API's self-signed certificate to decrypt HTTP traffic.
Again fiddler will encrypt same HTTP traffic using fiddler signed
certificate, i.e, for all your API calls will have fiddler signed
certificate
As fiddler signed certificates are trusted by user browser (due to step#a), you will not see any certificate errors.
Hope this information helps you!
Turns out I was setting SSL type to SSL3.
i.e. I had this code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
and shopify doesn't use SSL3 any more.
Turns out it was nothing to do with installing certificates.
My app uses AFNetworking.
What type of certificate extension does AFNetworking look for?
I was given a .crt file by GeoTrust but I have read here that AFNetworking specifically looks for .cer files.
I ask because my https in a browser works fine with my new certificate chain, and using a tool called SSLDetective I can see that the whole chain is trusted, but for some reason my app no longer accepts the bundle for a trusted handshake. Any other time I had issues, SSLDetective showed me that a part of the chain was not trusted. In this case, I can't seem to find anything wrong. Not much changed in my ssl certificate configuration other than overwriting the old key and crt files with the new files with the exact same name. Help is appreciated. Thanks!
EDIT:
I now know for sure that AFNetworking does use and automatically detects .cer files in the app bundle. I also know that the certificate attached in the bundle must match the same public key as the certificate on my web server. With public key pinning, AFNetworking simply extracts the public key from the local certificate and compares it to the one on the server. If the one on the server matches, it uses the server's certificate.
In my case, in the beginning, the keys did not match, but now I made sure that they do. The chain is still trusted and good according to SSLDetective. I downloaded a .cer version of the certificate from the server using SSLDetective and attached it to my app bundle. However, now that I know for sure the public keys match as well, I still can't seem to get a secure handshake. This question is somewhat related to the question asked here.
How can I disable the certificate validation when I make request with RKObjectManager ?
Because I'm getting this error :
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “the web service address” which could put your confidential information at risk."
Thank you !
Duplicate question :
I want to allow invalid SSL certificates with AFNetworking
If you are simply doing some tests against some server with the certificate misconfigured you can compile with the preprocessor macro _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ defined, and the request will bypass the certificate check.
I do not recommend that approach for a production server. If a production server has a misconfigured SSL certificate, you should try to fix it (if you can) or inform the owners of the server to fix it.
if you are using RestKit using
client.allowsInvalidSSLCertificate = YES;
won't work, instead do this:
if you added rest kit manually to your project, click on RestKit.xcodeproj go to project > Build Settings > Preprocessor Macros
and add _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_=1
thats finished.
I have this setup:
A tomcat server configured to use ssl client certificate authentication (clientAuth=true)
An ipad with a valid client certificate installed on it (emailed as a .p12 file and visible under profiles)
When browsing via ios safari, the ipad uses the client cert and authenticates against the server fine.
However in code, using a NSURLConnection, it won't connect. Debugging on the server shows the client isnt sending and cert at all.
On the client I get an error like this:
Request(https://192.168.1.5:8443/device/security/policy>, 0, 0)) didFailWithError:Error Domain=NSURLErrorDomain Code=-1205 "The server “192.168.1.5” did not accept the certificate." UserInfo=0xe2eae30
{NSErrorFailingURLStringKey=https://192.168.1.5:8443/device/security/policy>, NSErrorFailingURLKey=https://192.168.1.5:8443/device/security/policy>, NSLocalizedDescription=The server “192.168.1.5” did not accept the certificate.,
NSUnderlyingError=0xe2eb250 "The server “192.168.1.5” did not accept the certificate.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0xe6ab010>}
I understand I can implement the delegate method for the challenge for the NSURLAuthenticationMethodClientCertificate protection space, but if I do that I dont have the certificate to send, its installed on the device and that isnt accessible via code (is it??)
I tried calling [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge] but that appeared to have no effect.
I was expecting that NSURLConnection would behave as per safari and access the installed certificate, but it appears not. I dont want to have to install the certificate into my app somehow - thats what the built in certificate management is for!
Or am I missing something? Any help appreciated.
Fundamentally you can't get at globally installed certificates from within an app in iOS (as of iOS 8), and the operating system won't help you out by sending them with an NSURLConnection. Safari has special rights to access the certificates. So the only way to use them from within an app is to install them into the app somehow, which makes the whole thing difficult.