Extraiga el certificado de tarjeta inteligente para la autenticación de servidor a servidor

0

Quiero obtener datos de un servidor que acepte solo la autenticación del cliente mediante una tarjeta inteligente y los guarde en mi servidor. Dado que son muchos datos, quiero crear una conexión entre mi servidor y este servidor de terceros, pero necesito el certificado del usuario en la tarjeta inteligente. Es imposible para mí extraer la clave privada de la tarjeta inteligente, por supuesto, así que no sé si esto es posible o no.

He habilitado en mi servidor Apache la autenticación del cliente de esta manera:

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

Después de que el usuario inserte el PIN, con mi script PHP puedo obtener el certificado de esta manera:

$_SERVER["SSL_CLIENT_CERT"];

Finalmente, trato de usar este certificado para firmar la solicitud a través de php cURL de esta manera:

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://ext.processotelematico.giustizia.it/pda/pycons/GLMV/JPW_SICID",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_SSL_VERIFYPEER => true,
  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>",
  CURLOPT_HTTPHEADER => array(
    "cache-control: no-cache",
    "content-type: text/xml",
    "x-wasp-user: user-id"
  ),
));

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

curl_close($curl);

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

Pero recibo este error: "no se puede establecer el archivo de clave privada:". Entonces, supongo que solo tengo la parte pública del certificado. ¿Hay algo que pueda hacer para iniciar sesión de forma remota? ¿O es imposible? Sé que debo usar el código del lado del cliente, como Java Applet, pero, como he dicho, hay muchos datos y quiero evitar descargarlos en el cliente y cargarlos nuevamente en mi servidor.

ACTUALIZACIÓN: Solo para aclarar el caso de uso:

  • El segundo servidor es un servidor de gobierno. El ministerio proporciona datos de los ciudadanos después del inicio de sesión. No puedo cambiar nada en este servidor, obviamente.

  • El gobierno libera las tarjetas inteligentes para la autenticación, a través de Autoridades de Certificación Confiables. Tengo en mi servidor los certificados de CA, por lo que la CA no es un problema (supongo)

  • Mi aplicación web debe descargar, administrar y representar los datos de los ciudadanos de una manera mejor que el servidor original

pregunta zuno 05.07.2017 - 16:43
fuente

2 respuestas

0
  

Es imposible para mí extraer la clave privada de la tarjeta inteligente, por supuesto, así que no sé si esto es posible o no.

No es posible, porque la clave privada no se puede extraer de la tarjeta inteligente.

  

Entonces, supongo que solo tengo la parte pública del certificado.

Sí, eso es exactamente eso. El certificado transmitido al servidor por el protocolo SSL / TLS no contiene la clave privada.

  

¿Hay algo que pueda hacer para iniciar sesión de forma remota?

La forma habitual es que el primer servidor firme la solicitud con su propio certificado (que se controlará en el segundo servidor) y pasa el certificado del cliente en un encabezado personalizado. Así construyes una cadena de confianza:

  • el cliente se autentica en el primer servidor con su certificado firmado por una CA: el primer servidor confía en la CA y, a través de él, confía en el certificado del cliente
  • el primer servidor se autentica al segundo servidor con un certificado de servidor. El segundo servidor confía en el certificado y luego confía en el certificado del cliente pasado en la solicitud

Después de la edición, lo que describe es un grave ataque MITM: desea administrar los datos intercambiados en una conexión segura. Si pudiera hacer lo que quisiera, su servidor podría enviar cualquier solicitud en nombre del usuario, mientras que la solicitud se autenticaría con el certificado de usuario, lo que significa una autenticación sólida que incluye la no repudio. ¡Eso es exactamente lo que evitan los certificados de tarjeta inteligente! Lo mejor que puede hacer es ponerse en contacto con el ministerio para explicarle que le gustaría brindar un servicio por encima de estos datos y preguntar qué proponen. Si están de acuerdo, podrán adaptar el sistema de autenticación para permitir que los proveedores de valor agregado, si no lo hacen, me temo que su proyecto no será posible. E incluso con el código del lado del cliente, debe considerar las consecuencias legales.

    
respondido por el Serge Ballesta 05.07.2017 - 18:52
fuente
0

Le falta el punto de cómo funciona SSLVerifyClient (y SSLVerifyDepth ).

Lo que hacen estas 2 configuraciones es activar Autenticación de cliente TLS , que solicita un certificado público y desafía al usuario a demostrar cómo dice que está firmando algo utilizando su certificado privado.

No es necesario que la clave privada deje la tarjeta inteligente para firmar nada. Por lo general, las tarjetas inteligentes proporcionan interfaces para firmas criptográficas (vea PKCS # 11 y C_Sign)

El desglose real (simplificado) es:

  • El servidor solicita el certificado público del cliente;
  • El cliente envía un certificado público;
  • Desafío de problemas del servidor;
  • El cliente firma el desafío;
  • El servidor verifica la firma

Cuando se verifica la firma, esto prueba que el usuario tiene la propiedad de la clave privada para un certificado (sin tener que enviar la clave privada al servidor). Si el servidor confía en el firmante del certificado (o cualquier persona en la CA firma la cadena a SSLVerifyDepth), entonces el usuario puede acceder a la página.

Como prueba, intente utilizar un SSLCACertificateFile diferente y vea qué sucede cuando intenta acceder a la página (o simplemente niega el acceso a su tarjeta inteligente cuando su navegador lo solicita). Si obtiene una página de 40X, significa que Apache está entregando la autenticación como se esperaba.

    
respondido por el Filipe Rodrigues 05.07.2017 - 20:43
fuente

Lea otras preguntas en las etiquetas