Wow, SSL authentication is overwhelming!
I am using a NodeMCU device (ESP8266) device to connect to a Microsoft Azure IoT Hub securely using the MQTT protocol.
Microsoft offer the ability to authorise clients using self-signed X.509 certificates.
This is explained in detail here: Using X.509 Certificates with IoT Hub
I have followed the example that Microsoft Azure give, using OpenSSL to generate my self-signed X.509 certificates.
I try the example Python script to test the connection as a client, using my new certs and this works very well. So I know that the process has been a success, as it is tested and working and I am able to publish and subscribe to my IoT Hub.
In order to get the NodeMCU device connecting as a client to the IoT Hub, I need to load a certificate for authentication. NodeMCU provides the facility to load a single CA Certificate (in PEM format) into the operating system.
This is documented here: NodeMCU TLS Documentation
The question is, which certificate should I use?
I have tried a handful of combinations from the OpenSSL output, but none appear to result in a successful handshake. I am poking and hoping at this stage and could do with some input from someone who knows their stuff.
The encouraging news is that NodeMCU recognises the certificates as X.509 certs but fails on the verification. So this leads me to believe that I have the incorrect cert loaded...
-0x2700 MBEDTLS_ERR_X509_CERT_VERIFY_FAILED
Certificate verification failed, e.g. CRL, CA or signature check failed.
You need to use RSA Client Side Certificate & Private Key on NodeMCU end to authenticate client using X.509 authentication.
You can place PEM formatted certificate and private key in NodeMCU flash and load them in SRAM. It is a good idea to enclose the certificate and private key in "EOF(" ")EOF" tags.
Hopefully you are using Arduino core for ESP8266, you can them make use of BearSSL to format certificate files for transport layer and associate with WiFiClientSecure object as follows:
BearSSL::WiFiClientSecure espClient;
BearSSL::X509List serverCertList(getCertificate());
BearSSL::PrivateKey serverPrivKey(getPrivateKey());
espClient.setClientRSACert(&serverCertList, &serverPrivKey);
where, getCertificate() & getPrivateKey() methods you should define to read certificate from flash (or pass character array containing PEM formatted Certificate and Private Key here instead). After this, you will be able to authenticate the client with the server if your certificate and private key belongs to valid chain.
Related
When using Azure API Management Gateway its possible to implement client certification authentication to secure access to APIs. You can validate incoming request certs using policy expressions such as thumb checks etc.
When using client cert authentication method, what's the recommended process for certificate generation/management?
Cert responsibility?
Should I/gateway owner be generating the .pfx file (either self signed or by trusted CA), importing it to the gateway service and providing external clients with the .cer to install locally and auth with?
Should I/gateway owner be generating the .pfx file (either self signed or by trusted CA), importing the .pfx to the API Management gateway service (normally I'd imagine importing the .cer on a server/gateway but doesn't seem possible in Azure) and providing external clients with the .pfx to install locally and auth with?
Should the external client be responsible for generating their public/private key pair in their Org, signing it with a CA, installing it locally and providing me/gateway owner with a .cer file to import to the gateway (as above, not sure its possible to import .cer, I read only .pfx accepted in import process) or provide thumb for me to store/validate in policy?
Does anyone have any advice whether to issue clients requiring access to the same API the same (shared) cert or generate a new cert per client? They would all be using the cert to access the same API (+ additional auth methods, cert is just an extra step).
I've ready online tutorials describing all above bullets and where client-specific or single cert-per-API have been implemented so a little confused which is recommended approach?
The easiest way would be to have a single issuing CA certificate, you'd only need to upload its public key to APIM as that is all that's needed for APIM to validate incoming certificate. Then you'll be responsible to generate client certificates and distribute them to clients. In APIM you can setup a policy that would require certificate, check its issuer and validate, that should be enough to ensure that certificate is valid and issued by you.
Relying on self-signed certificates will be a hassle as you'd have to somehow let APIM know of each new certificate, having common issuing CA frees you of that worry.
Same goes for allowing remote clients to generate certificate - they would have to let you know of certificate and you'd need to list it in APIM one way or another.
You're free to decide how exactly to distribute certificates, a few things to consider:
Likely certificate will be your main way to tell clients apart. If that is important you may want to have different clients have different certificates.
If you want to deny access to a particular client you'll "revoke" that certificate, you need to make sure that other legitimate clients won't be affected.
What I understand so far:
The CA(Certificate authority) has a key and builds a certificate using that key
The server has a key and builds a csr(Certificate Signing Request) with that key
Then using both the CA crt and key as well as the server csr the CA builds a server certificate
To authenticate a server the client uses the CA (its certificate) like this:
4.1. The client receives the server certificate
4.2. The client verifies that this certificate is authenticated by the certificate of the CA that it has (using the public key of the CA), it also verifies that the serial number of this certificate is not in the CRL (certificate revocation list)
4.3. The client generates a symmetric key and encrypts it using the public key giving by the server and sends it to the server
4.4. All communication starting from now is then encrypted using this symmetric key
Here is where I am still a bit confused:
The client uses the CA public key to verify the server certificate in step 4.2 but how does a match occur since the client only has the certificate of the CA? I mean unless the server csr passed to the CA has the same information verified by the client as the crt of the CA that the client has, how can a match occur?
Since anyone can have the server certificate I am assuming the only step that insures that only the server can communicate with the client is step 4.3 where only the server can have the symmetric key because only the server has the private key so only it can decrypt this encrypted symmetric key. Is this correct?
I am also not sure of all the steps or if I missed any steps.
I found an answer (How are ssl certificates verified?) that responds to the first part of my question then luckily someone posted a link in the comments that answers the rest: http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html
I currently develop a small system consisting of an embedded server (including a small display) and some mobile devices (at the moment just Android phones).
These mobile devices should be able to talk to the embedded server over a secure channel. For this purpose, the server generates a self-signed SSL certificate during the very first boot process.
If a new mobile device should be connected to the server, the server displays a QR code consisting of:
Server IP
SSL certificate fingerprint
Random device ID
The user scans this QR code using his mobile device. The mobile device connects to the server and checks whether the SSL certificate fingerprint matches the one scanned before.
Is this considered secure? If not, how would you solve this problem?
An alternative approach:
On the very-first boot, the server generates a certificate request and sends it to a central CA server which signs the certificate. The client devices has installed the CA certficate and verifies the server certificate against it.
However, everyone could send a certificate request to the CA server and would get a signed certificate. (One could propably implement some authentication for the CA server using a "master key" but once that is extracted from a system image, the whole authentication becomes useless). In addition this setup requires a central server which I like to avoid since the product may be used in a "offline" environment.
Yes, this is considered secure because the fingerprint of the server's certificate is transferred to the client via a trusted mechanism (being physically next to the server to receive the fingerprint via a difficult to tamper with transport mechanism). If a MITM attack were to be attempted after the initial setup, even though server name would be the same, different keys would have been generated so the fingerprint would be different and the client would detect this and can appropriately reject the communication.
It could also be argued that this method is more secure because the client does not need to trust a 3rd party to verify the authenticity of the certificate. CAs do occasionally issue fraudulent certificates.
We have a backend server that services a multi-platform app that will be launched on iOS, Windows 8, Windows Phone 8 and Android. We'd like to use in production as few certificates as possible (preferably just one) to attain the following purposes:
secure communication (HTTPS) with the client application
authentication to the Windows Phone Push Notifications Service
authentication to the Apple Push Notifications Service
Besides taking care that the certificate is issued by a common trusted root authority, are there any other impediments that could prevent a single certificate from being used simultaneously for all these? Is it a viable possibility or is it instead necessary to resort to one certificate for each of the above purposes?
Gabriel I guess there is a problem. Main one is that HTTPS certificate private key cannot be coded by a secret this kind of certificate contain *.crt and *.key file which are not secured. When You want authenticate yourself or server in some Service for example Windows phone push like you have listed there is need to create hash for your private key with secret aka pin or password. What make You use at least two different certificates.
Second thing is that purpose of using certificates is to validate the issuer and to authenticate user/service provider. HTTPS ssl certificate issued by a trusted CA show to the user Hey this is trusted website You should not be afraid passing sensitive data through the service, and the certificates which are used to authenticate are just saying Hey its me I am authorized to use this application Purpose of those certificates and different so certificates them self should be different. Using the same cert for actions like You have listed cause necessaries vulnerabilities and is highly NOT RECOMMENDED
I am new to PKCS#11 and Common Access Cards but as I understand it, on the card you have the certificates(s) that can be extracted and the private key(s) that can't. I am trying to write an app that communicates with a web server that requires certificates for authentication. The PKCS library provided from the hardware vendor is pretty thin. I can essentially access the certificate object or sign data using the on-card private key.
What I am unsure of how I handle the handshake and such when connecting to the webserver. Am I supposed to provide the certificate along with something else signed by the private key? If so, what is it that I sign with the private key? I have Googled this but have been unable find some kind of explanation for this process.
If you are using an RSA key on the common access card for authentication, you'll need to send a CertificateVerify message in the handshake, which contains digital signatures over the handshake records to that point. You'll also need to send the client certificate, of course. See §7.4.8 of the TLS specification for details.
Hopefully, your TLS library supports the use of a PKCS #11 cryptographic module. If not, you might have to switch. Implementing TLS yourself when you aren't familiar with the specification is unreasonable.
I think you just need to retrieve your client certificate from your PKCS#11 device and then use it along the request you are making to web server. You don't need to implement SSL if you use existing libraries. They should contain all you need.