SSL Pinning with AFNetworking - ios

In my app I'm using https and a self-signed SSL certificate to secure the connection between my client and the server.
I was trying to have the AFNetworking library do SSL Pinning on a copy of my certificate bundled in the app.
In the AFURLConnectionOperation header I defined both:
#define _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ =1
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_ =1
And before calling the start on my AFJSONRequestOperation I set the SSLPinningMode property to AFSSLPinningModeCertificate.
But when trying to perform a JSON request I keep getting the following error:
Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed.
(NSURLErrorDomain error -1012.)" UserInfo=0x758f120
{NSErrorFailingURLKey=https://mydomain.com,
NSErrorFailingURLStringKey=https://mydomain.com}
In the AFURLConnectionOperation header I read that the SSL Pinning works with .cer certificates but in my self-hosted OS X webserver I have a .crt certificate.
Is this the problem? Is there a way to make AFNetworking work with .crt?
On a windows box I converted my .crt to .cer and tried to bundle that into my app but I still get the same error. Should I try to switch the .crt file with the newly created .cer even on the server side?

I got it working.
I was in the situation where I had created a self-signed cert for to hit my own server API from my iOS App.
I created my cert with OpenSSL. When I was done creating it, I had several files, one of which was "server.crt". Initially, I tried just renaming it to "server.cer", and using "AFSSLPinningModeCertificate" for my AFURLConnectionOperation objects. That did not work, and I noticed the example uses "AFSSLPinningModePublicKey", so I tried that, still no luck.
So I compared my file (that was the renamed ".crt" file) to his.
I noticed that "server.crt" was base64-encoded, and like this:
-----BEGIN CERTIFICATE-----
394230AFDFD...
-----END CERTIFICATE-----
I noticed from Mattt's example in AFNetworking that the "adn.cer" file he uses is not base64-encoded. It is just raw bytes.
So, I did this:
$ base64 -D -i ./server.crt -o ./server.cer
I set my AFURLConnectionOperation to AFSSLPinningModePublicKey.
I put that back in the project and did a clean and build of my iOS project, and everything worked fine.
Hope this helps!!
Btw, you may notice that Xcode will display info for for your ".crt" or ".cer" key whether it is the base64 or the raw one, so don't let that confuse you. You should be able to see the certificate data in either case, it's just that AF will only accept the raw (non-base64) one.
UPDATE:
Anyone having trouble with base64, this what works for me on OS X using OpenSSL:
$ openssl base64 -d -in ./server.crt -out ./server.cer

If you're using AFNetworking 2.x, and you're using the correct .cer but still receiving error code -1012 on your calls, you should disable validatesCertificateChain:
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
securityPolicy.validatesCertificateChain = NO;
or you can pass it all in the entire certificate chain in pinnedCertificates.

Your certificate must have the extension cer not crt and should be in .der format. Add output file to your Xcode project.
You can use following command:
openssl x509 -in your.crt -out certificate_cer.cer -outform der

Related

Certificate ending on 28/06/21 how to update it?

I'm using mitm on ios to test some app, but since yesterday I can't log in any website, or even use google.
It seems that the certificate has expired on the 28/06.
I've tried to download a new one on mitm.it, but it's already expired.
Do someone have any idea how i can bypass that ?
You can force mitmproxy to generate a totally new root CA certificate by simply deleting the old one.
Mitmproxy stores the root CA certificate and it's key in the directory ~/.mitmproxy (mitmproxy config directory in your home directory on the computer running mitmproxy).
If you rename or delete that directory and restart mitmproxy a new root-CA certificate will be generated.
Then you can install this new certificate as usual via http://mitm.it

Retrieve file from keyvault instead of secure files in InstallAppleCertificate task on azure pipeline

According to the documentation of the InstallAppleCertificate task, there is a certSecureFile parameter that looks for the certificate in the "Secure Files":
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/install-apple-certificate?view=azure-devops
However in my organization I don't have the permission to upload secure files:
Any other way to select a certificate that isn't uploaded to "Secure Files" for this task?
They did gave me a separate keyvault which I can perfectly link to the pipeline build and get files/secrets from in bash scripts. Yet this InstallAppleCertificate task doesn't allow me to use those instead. I wouldn't even mind to put the certificate in my source repo (I know I shouldn't do this).
The certSecureFile field in InstallAppleCertificate task needs to use the .p12 file in secure file.
I am afraid that files that are not in the secure file cannot be used.
Based on my test, when I use the file from local machine, it will show the following error:
This means that before running the build, it will retrieve the files in the secure file. And the file needs to exist in secure file.
Since you could get the files/secrets , you could try to install the Apple Certificate(.p12 file) via script.
security import ./xxx.p12 -P secretPassword
Here is a thread about install .p12 or .cer in console macos.

OpenSSL::SSL::SSLError Handshake Failure with Homebrew OpenSSL

I'm trying to make an API request in a Ruby app, on MacOSX.
When I try something like this:
RestClient.get("https://api.foursquare.com/v2/venues/explore?near=NYC&query=McDonalds")
I get this (same when it's http):
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure
from /Users/sasha/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/net/http.rb:920:in `connect'
(If I try (open("https://...")), I get this:
OpenURI::HTTPError: 400 Bad Request
from /Users/sasha/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/open-uri.rb:353:in `open_http'
I took a look at some SO discussions about this, and in particular this one led me to believe it was an issue with my OpenSSL not finding the right cert.pem file. I'm using Homebrew, and my Homebrew OpenSSL is installed in /usr/local/bin. The original Mac version of OpenSSL is at /usr/bin, I think.
I followed the suggestions to set a global ENV variable SSL_CERT_FILE to the path to my cert.pem file as installed by Homebrew - /usr/local/etc/openssl/cert.pem, - and when I echo that variable, it is set correctly, but when I re-open a Ruby console and try again, I get the same error. Thoughts on what I'm doing wrong? I don't know much about OpenSSL, and I'm totally flummoxed by this one, given that it seems to be finding my certificate correctly.
EDIT
When I run which openssl, it shows the Mac version -- /usr/bin/openssl. This makes sense, given Homebrew's install notes:
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
/usr/local/etc/openssl/certs
and run
/usr/local/opt/openssl/bin/c_rehash
This formula is keg-only, which means it was not symlinked into /usr/local.
Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.
The OpenSSL provided by OS X is too old for some software.
Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:
LDFLAGS: -L/usr/local/opt/openssl/lib
CPPFLAGS: -I/usr/local/opt/openssl/include
Is that the problem? I'm including the wrong cert.pem file given my version of OpenSSL?
state=SSLv3 read server hello A: sslv3 alert handshake failure
That is usually not a problem of a bad or missing certificate, but that the server does not like what the client sends, like unsupported SSL version or no appropriate ciphers offered by the client.
I get this error with this host if I try to connect with SSL3.0 instead of TLS1.0 or higher, so please make sure that you don't use SSL3.0 anymore.
If this does not help make a packet capture of the traffic and post it to cloudshark.org so that one can have a look about the traffic details.

PKCS#7 data payload unpacking with NodeJS?

I'm working on an MDM NodeJS server for iOS. On the Apple docs, the following ruby code is given :
p7sign = OpenSSL::PKCS7::PKCS7.new(req.body)
store = OpenSSL::X509::Store.new
p7sign.verify(nil, store, nil, OpenSSL::PKCS7::NOVERIFY)
signers = p7sign.signers
What would be the equivalent in NodeJS?
The idea is to access p7sign.data that contains an xml plist.
Is this possible using either crypto or an external node lib (ursa, etc)?
A good option would be to use child_process to invoke openssl directly. I do that to validate iOS .mobileprovision files.
$ openssl smime -verify -in FILE -inform der
The openssl command needs to be the apple-provided (not from ports or homebrew) so that it can find signing certificates and CA's in the keychain.
I haven't tried this myself, but the node-forge library contains an implementation of many cryptographic algorithms.
https://npmjs.org/package/node-forge#pkcs7

making CSR certificates in Windows (7)

Closely related to How to generate CSR when IIS is not installed.
I also do not have this installed. I am developing a mobile application for iOS, and i am trying to obtain a provisioning file so i can test my app locally. In the process of acquiring this, i am asked for a .csr file, and it instructs me on how to build this on my Mac. Except i don't have a mac, i have a PC, and my company exclusively uses PCs. I need this certificate, without having access to a Mac.
i have seen and used this CSR generator, but it gives me the key and request in long strings of characters, and i need a .csr file to upload to Apple.
Pasting it in notepad and changing the extension to .csr didn't work either :/
Does anyone have any insights on this?
You can install OpenSSL for windows and generate CSR file with this command:
openssl req -nodes -newkey rsa:2048 -keyout private_key.key -out cer_sign_request.csr
You'll be asked for a few questions which are optional (press ENTER).
This will generate a private key (such in keychain access) and a certification signing request as csr file.
For those who want an easy to use graphical interface, Digicert has a "Digicert Utility" that is pretty solid. You can use it to create a CSR. It doesnt give you back a private key, so you need to import your self signed or CA certificate to complete the installation of the certificate. Once installed, you can export it as a pfx or crt/key bundle.
set OPENSSL_CONF=c:\OpenSSL\openssl.cnf
if saved in c:\openssl
You can download this example fileopenssl-dem-server-cert-thvs.cnf
rename openssl
ren cert-thvs.cnf openssl.cnf

Resources