I want to get data from a server that accept only client authentication via smartcard and save them to my server. Since they are a lot of data, I want to create a connection between my server and this third party server, but I need the user's certificate in the smart card. It's impossible for me extract the private key from the smart card, of course, so I don't know if this is possible or not.

I enabled on my Apache server the client authentication in this way:

  SSLVerifyClient require
  SSLVerifyDepth 4
  SSLProtocol +TLSv1.1 +TLSv1.2
  SSLOptions +ExportCertData +StdEnvVars
  SSLCACertificateFile /usr/share/ca-certificates/ca-bundle.crt

After the user insert the PIN, with my PHP script I can get the certificate in this way:


Finally I try to use this certificate to sign the request via php cURL this way:

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://ext.processotelematico.giustizia.it/pda/pycons/GLMV/JPW_SICID",
  CURLOPT_SSLCERT => $certificate,
  CURLOPT_POSTFIELDS => "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>\r\n  <soapenv:Header>\r\n    <ws:InvocationDomain name=\"JPW\" role=\"AVV\" group=\"9876\" soapenv:mustUnderstand=\"1\" soapenv:actor=\"http://schemas.xmlsoap.org/soap/actor/next\" xmlns:ws=\"http://www.netserv.it/anag/security\" />\r\n  </soapenv:Header>\r\n  <soapenv:Body>\r\n    <sicc:execute xmlns:sicc=\"urn:CONS-ANONIMA-SICC-BE\">\r\n      <sicc:name>RicercaRuoloGenerale</sicc:name>\r\n      <sicc:valueSet>\r\n        <sicc:value name='idUfficio' type='string'>9876</sicc:value>\r\n        <sicc:value name='numero' type='integer'>1</sicc:value>\r\n        <sicc:value name='anno' type='string'>2017</sicc:value>\r\n      </sicc:valueSet>\r\n      <sicc:orderBy>\r\n        <sicc:entry mode='asc' property='IDFASCICOLO' />\r\n      </sicc:orderBy>\r\n    </sicc:execute>\r\n  </soapenv:Body>\r\n</soapenv:Envelope>",
    "cache-control: no-cache",
    "content-type: text/xml",
    "x-wasp-user: user-id"

$response = curl_exec($curl);
$err = curl_error($curl);


if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;

But I receive this error: "unable to set private key file: ". So, I suppose I have only the public part of the certificate. There is something I can do to login remotely? Or it is impossible? I know I should use client-side code, like Java Applet, but, like said, there are a lot of data and I want to avoid to download them on client and upload again on my server.

UPDATE: Just to make clear the use case:

  • The second server is a government server. The ministry provides citizens' data after the login. I cannot change nothing on this server, obviously.

  • The government releases the smartcards for authentication, via Trusted Certificate Authorities. I have on my server the CA certificates, so the CA are not an issue (I suppose)

  • My web app should download, manage and represent the citizen's data in a better way than the original server


It's impossible for me extract the private key from the smart card, of course, so I don't know if this is possible or not.

It is not possible, because the private key cannot be extracted from the smartcard.

So, I suppose I have only the public part of the certificate.

Yes that is exactly that. The certificate transmitted to the server by the SSL/TLS protocol does not contain the private key.

There is something I can do to login remotely?

The common way is that the first server signs the request with its own certificate (that will be controlled on second server) and passes the client certificate in a custom header. You build a trust chain that way:

  • client authenticates to first server with its certificate signed by a CA - first server trusts the CA and through it trusts the client certificate
  • first server authenticates to second server with a server certificate. The second server trusts the certificate and then trusts the client certificate passed in the request

After the edit, what you describe is a serious MITM attack: you want to manage the data exchanged on a secure connection. If you could do want you want, your server would be able to submit any request on behalf of the user, while the request would be authenticated with the user certificate said differently a strong authentication including non repudiation. That is exactly what smartcard certificates prevent! The best you can do is to contact the ministry to explain that you would like to provide a service above this data, and asking what they propose. If they agree they will be able to adapt the authentication system to allow value added providers, if they do not, I'm afraid that your project will not be possible. And even with client side code, you should considere the legal consequences.

  • But in that way I should authenticate with my (server) certificate, but I want to authenticate with the user certificate. – zuno Jul 5 '17 at 19:42
  • @That is trust delegation. The second server receives a copy of the user certificate and trusts it because it comes from a trusted server. Of course you might have to setup a custom authentication scheme on the second server to process a delegated certificate. Anyway the private key has never left (and will never leave) the smartcard... – Serge Ballesta Jul 6 '17 at 6:19
  • I updated the question to be more specific – zuno Jul 6 '17 at 7:37
  • understood. I imagined it was something like this, so I asked if it was possible. Thanks @Serge – zuno Jul 6 '17 at 10:31

You are missing the point of how SSLVerifyClient (and SSLVerifyDepth) works.

What these 2 configurations does is to trigger TLS Client Authentication, which requests for a public certificate and challenges the user to prove how he says he is by signing something by using his private certificate.

There is no need to the private key to leave the smartcard in order to sign anything. Commonly smartcards provide interfaces for cryptographic signatures (look at PKCS #11 and C_Sign)

The actual breakdown (simplified) is:

  • Server requests client public certificate;
  • Client sends public certificate;
  • Server issues challenge;
  • Client signs challenge;
  • Server verifies signature

When the signature is verified, this proves that the user has ownership of the private key for a certificate (without having to send the private key to the server). If the server trusts the certificate signer (or anyone in the CA sign chain up to SSLVerifyDepth) then the user can access the page.

As a test, try to use a different SSLCACertificateFile and see what happens when you try to access the page (or simply denies access to your smartcard when your browser request access to it). If you get a 40X page, then it means Apache is handing authentication as expected.

  • Thanks for clarifying. But how can I authenticate with the other server (not mine) with the smart card certificate? – zuno Jul 5 '17 at 19:43
  • Your client certificate is signed by a CA (certificate authority). The other server would have to trust this CA on order to authenticate you. – Filipe Rodrigues Jul 5 '17 at 20:00
  • Client auth in TLS (and SSL3, but that's broken) signs a transcript of the handshake, of which a tiny part is a server nonce that could be called a challenge, but which was sent before either CertReq or (Client)Cert. See the RFC(s) or our canonical (and 5-year-old) epic security.stackexchange.com/questions/20803/… . However this is never a very large amount of data as suggested by the Q; if you send data over a client-auth TLS connection, the PK signature is only on the handshake and the data is instead MACed with a shared key derived from the handshake. – dave_thompson_085 Jul 6 '17 at 3:41
  • I updated the question to be more specific – zuno Jul 6 '17 at 7:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.