PDA

View Full Version : Adding Client certificate for post using QNetworkAccessManager



sattu
30th October 2012, 13:55
Hi everyone,

I need to post some data to a https server. I already have used QNetworkAccessManager class for this purpose. But now I need to add a client certificate and establish a trust connection before I can post any data to the https server. I have already done it in C#.net whose code is as follows:- (Following code is in .net, not in Qt)



X509Certificate cert = X509Certificate.CreateFromCertFile("Path to my .cer file"); //****** name of cer file is "ServerTrial.cer" ******//
Uri authURL = new Uri("https://myServer/post");
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(authURL); //****** Here i add the server url ******//
authRequest.ClientCertificates.Add(cert); //****** Here i add the client certificate ******//
authRequest.Method = "POST"; //****** Here i specify the method which is "POST" ******//

byte[] postBytes = "Data to be posted";
authRequest.ContentLength = postBytes.Length;
Stream requestStream = authRequest.GetRequestStream();
// now send it
requestStream.Write(postBytes, 0, postBytes.Length); //****** Here I post the data to the Server ******//
requestStream.Close();

// grab the response
HttpWebResponse response = (HttpWebResponse)authRequest.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string responseStr = responseStream.ReadToEnd();


How do i achieve it's equivalent in Qt? Will i need any external library for achieving the above?

-With regards,
sattu

ChrisW67
31st October 2012, 01:55
QNetworkRequest::setSslConfiguration() and QSslConfiguration::setLocalCertificate()/QSslConfiguration::setPrivateKey()... approximately 30 seconds of search time in the documentation that comes with every copy of Qt.

Assuming you are working on Windows then you will need a suitable OpenSSL library.

sattu
31st October 2012, 05:19
QNetworkRequest::setSslConfiguration() and QSslConfiguration::setLocalCertificate()/QSslConfiguration::setPrivateKey()... approximately 30 seconds of search time in the documentation that comes with every copy of Qt.
Thanks Chris, I went through the documentation. It states that both the private key as well as the local certificate are required. But as you can see in my C# code, I just needed to add the client certificate that was provided to me by the server. I didn't require any key addition. So is it ok if i skip QSslConfiguration::setPrivateKey() ?
Moreover by local certificate it means the client certificate (.cer) which i have got, right?


Assuming you are working on Windows then you will need a suitable OpenSSL library.
I actually have got all the necessary header files and library files (libcrypto.a, libssl.a, libeay32.dll, libssl32.dll) of openSSL with me. So is it enough if i just mention them in my .pro file or i need to separately compile openSSL as a plugin?

ChrisW67
31st October 2012, 06:07
Local certificate means the client certificate on the client and the server certificate for a server. The extension on the file name is not reliable but you probably have a suitable file. It must be either a X.509 in PEM form (base64, plain text) or DER form (a binary). A PKCS#12 encoded bundle needs to be converted before use. http://serverfault.com/questions/9708/what-is-a-pem-file-and-how-does-it-differ-from-other-openssl-generated-key-file

To authenticate the client using PKI you must have the private key. The server uses the client certificate (issued by a CA it trusts) to verify that a token the client signs with their private key can be validated using the client public key from their certificate. This is the inverse of the process your client uses to authenticate the server and applies to C# a just as much as everyone else.

You do not need a client certificate or private key if the server is not authenticating the client. Public web servers rarely require a client authentication.


The OpenSSL DLLs must be in the run-time environment of the program and should be detected automatically by the default Windows Qt builds. Nothing extra to do in your PRO file other than use the Qt network module.

sattu
31st October 2012, 06:46
To authenticate the client using PKI you must have the private key. The server uses the client certificate (issued by a CA it trusts) to verify that a token the client signs with their private key can be validated using the client public key from their certificate.
Bingo, in that case I think I require only the certificate part. I checked in my code, my certificate has only the public key. So that means the server must be having the private key which it will use to check the validity of the certificate that I provide during the handshake.


You do not need a client certificate or private key if the server is not authenticating the client. Public web servers rarely require a client authentication.
In my C# code if i didn't provide the client certificate, then I was getting exception from the server. So i guess I will need the client certificate as server is authenticating my client.


The OpenSSL DLLs must be in the run-time environment of the program and should be detected automatically by the default Windows Qt builds. Nothing extra to do in your PRO file other than use the Qt network module.
Wow, that means I need not again compile the openSSL as a plugin. Thanks Chris, that saved my time. :)
One more thing Chris, all i understand by compiling a PACKAGE is that it produces some library files which I can directly reference in my code to use the functionalities of that PACKAGE. But when it comes to compiling it as a plugin, what extra steps does it indicate? I mean apart from the normal referencing to the library and header files what extra steps i need to go through to add it as a plugin in my Qt package? Or on the contrary I need not reference to any header or .lib files once I have added the package as a plugin, right?

ChrisW67
31st October 2012, 23:15
Bingo, in that case I think I require only the certificate part. I checked in my code, my certificate has only the public key. So that means the server must be having the private key which it will use to check the validity of the certificate that I provide during the handshake.

In my C# code if i didn't provide the client certificate, then I was getting exception from the server. So i guess I will need the client certificate as server is authenticating my client.

If you are not providing the client with a private key matching the client certificate then the server cannot be authenticating the client. If the server has the client's private key then security is broken anyway.

Are you sure the exception you got from the server was not to do with it using a self-signed certificate to authenticate the server to you?



One more thing Chris, all i understand by compiling a PACKAGE is that it produces some library files which I can directly reference in my code to use the functionalities of that PACKAGE. But when it comes to compiling it as a plugin, what extra steps does it indicate? I mean apart from the normal referencing to the library and header files what extra steps i need to go through to add it as a plugin in my Qt package? Or on the contrary I need not reference to any header or .lib files once I have added the package as a plugin, right?
The Lower-Level API: Extending Qt Applications
Code that uses the plugin has to use headers that define the interfaces the plugin provides, but you do not reference the compiled plugin during compile and link of the user application.

sattu
1st November 2012, 14:33
If you are not providing the client with a private key matching the client certificate then the server cannot be authenticating the client. If the server has the client's private key then security is broken anyway.
Actually Chris it's just the reverse. It's the server which is the CA, it generated the certificates containing the public key and other information and then provided those certificates to clients (mine is also a client). So, each and every time a client has to connect to it, it has to include the provided certificate during the handshake.


The Lower-Level API: Extending Qt Applications
Code that uses the plugin has to use headers that define the interfaces the plugin provides, but you do not reference the compiled plugin during compile and link of the user application.
Chris, I am getting certain undefined reference to ..... errors while I try to compile my program. The detailed scenario is that inside the debug folder of my program I did the following :-
1) I created a sub folder called lib which contained libcrypto.a, libeay32.a, libgdi32.a, libssl32.a and libssl.a.
2) I created another sub folder named openssl which had all the openssl header files.
3) I placed libeay32.dll, libssl32.dll, ssleay32.dll in the debug folder.
4) I added the following configurations to my .pro file:-
INCLUDEPATH += F:/EncryTrial/debug/openssl/ #EncryTrial is the name of my program

LIBS += F:/EncryTrial/debug/lib/libcrypto.a\
F:/EncryTrial/debug/lib/libssl.a\
F:/EncryTrial/debug/lib/libgdi32.a
5) To my mainwindow.h I added #include <QtNetwork/QSslSocket>.

After having done the above I added the below code to my mainwindow.cpp :-

QSslSocket socket;
socket.connectToHostEncrypted( "bugs.kde.org", 443 );
I am sure it's some library issue but just not able to figure it out.

ChrisW67
2nd November 2012, 03:27
The OpenSSL DLLs must be in the run-time environment of the program and should be detected automatically by the default Windows Qt builds. Nothing extra to do in your PRO file other than use the Qt network module.
Emphasis added. The QtNetwork module is built to dynamically load OpenSSL at run time if required and found, and fails the SSL related functions otherwise. Nothing to link.

sattu
2nd November 2012, 05:10
The QtNetwork module is built to dynamically load OpenSSL at run time if required and found, and fails the SSL related functions otherwise. Nothing to link.

But Chris, I am getting compile time error, not run time. If i comment off the QtNetwork part, then it builds fine.
Moreover, as i have said, I have placed all the required dlls in my debug and release folder. Also I found out that the openSSL dlls are present inside my Qt path i.e C:\QtSDK\Desktop\Qt\4.7.3\mingw\bin. Shouldn't this be enough for my application to detect them at run time?