Foros del Web » Programando para Internet » PHP »

XML Signature con PHP

Estas en el tema de XML Signature con PHP en el foro de PHP en Foros del Web. Hola a todos, Estoy haciendo un desarrollo donde necesito un consumir un servicio web que implementa WS-Security. Para garantizar la característica de Non-Repudiation (es decir, ...
  #1 (permalink)  
Antiguo 26/10/2011, 09:58
 
Fecha de Ingreso: julio-2008
Ubicación: Caldas, Antioquia, Colombia
Mensajes: 81
Antigüedad: 11 años, 4 meses
Puntos: 4
XML Signature con PHP

Hola a todos,

Estoy haciendo un desarrollo donde necesito un consumir un servicio web que implementa WS-Security.

Para garantizar la característica de Non-Repudiation (es decir, que quien envíe un mensaje no puede negar que lo ha hecho), se deben firmar digitalmente los mensajes XML a ser enviados al servicio web usando WS-Security, específicamente XML Signature.

Una persona que ya hizo pruebas de conexión al WS (con java) me envió un archivo keyStore que utilizó y le funcionó. Yo con una herramienta llamada portecle, extraje la clave privada y el certificado, y estoy usando una librería que encontré llamada soap-wsse.php (esta usa otra librería llamada xmlseclibs). Con esto ya he podido firmar el mensaje, sin embargo obtengo el siguiente mensaje:


Código:
WSDoAllReceiver: security processing failed (actions number mismatch)

Éste es el código que estoy utilizando.

Código PHP:
<?php
require_once('soap-wsse2.php');

class 
WSSoapClient extends SoapClient 
{
    
//Ruta del fichero de la clave privada
    
public $key_file="";
    
//Passphrase de la clave privada
    
public $passphrase="";
    
//Ruta del fichero del certificado
    
public $cert_file="";
    
//Mensaje SOAP enviado
    
public $soap_sent="";
    
    public 
$user "";
    
    public 
$password "";
    
    function 
__doRequest($request$location$saction$version)
    {
        
//return parent::__doRequest($request, $location, $action, $version);
        //Creamos un DOMDocument
        
$doc = new DOMDocument('1.0');
        
//Cargamos el XML pasado por parámetro
        
$doc->loadXML($request);
        
//Creamos una instancia de WSSESoap con el documento, sin "mustUnderstand" ni "actor"
        
$objWSSE = new WSSESoap($doc,false,false);
        
        
$objWSSE->addTimestamp(300); 
        
        
$objWSSE->addUserToken($this->user$this->password);
        
        
//Creamos una instacian de XMLSecurityKey con el RSA SHA1 y de tipo privado
        
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1,array ('type'=>'private'));
        
//Pasamos el valor de passphrase
        
$objKey->passphrase=$this->passphrase;
        
//Cargamos la clave privada con la ruta del fichero, que es fichero y que no es certificado
        
$objKey->loadKey($this->key_fileTRUE);
        
//Firmamos el mensaje
        
$objWSSE->signSoapDoc($objKey);
        
//Añadimos el BinarySecurityToken, pasamos el contenido del certificado, le decimos que es formato PEM
        
$token $objWSSE->addBinaryToken(file_get_contents($this->cert_file),TRUE);
        
//Añadimos el KeyInfo
        
$objWSSE->attachTokentoSig($token);

        
//Guardamos el XML enviado
        
$this->soap_sent=$objWSSE->saveXML();
        echo 
htmlentities($this->soap_sent);
        
//Llamamos al método __doRequest padre
        
return parent::__doRequest($this->soap_sent$location$saction$version);
    }
}

$auth_login 'YYYYYYYY';
$auth_password 'ZZZZZZ';

$opciones = array(
    
'proxy_host' => 'proxy',
    
'proxy_port' => '8080',
    
'proxy_login' => 'user',
    
'proxy_password' => 'xxxxxxxxxx',
    
'trace' => 1,
    
'cache_wsdl' => WSDL_CACHE_NONE,
    
'login' => $auth_login,
    
'password' => $auth_password
);

$url 'http://.../ConfrontaWebService?wsdl';

$pk_file 'keys/test_pk.pem';
$cert_file 'keys/test_cert.cer';
$pk_passphrase 'XXXXXXXXX';

$objParametrosDTO = new stdClass();
$objParametrosDTO->secuenciaCuestionario '10';
$objParametrosDTO->secuenciaEmpleado '12';
$objParametrosDTO->tipoIdentificacion '1';
$objParametrosDTO->numeroIdentificacion '12312';
$objParametrosDTO->telefono '1231';
$objParametrosDTO->departamento '1';
$objParametrosDTO->ciudad '1';
$objParametrosDTO->tipoEntidad '1';
$objParametrosDTO->codigoEntidad '1';
$objParametrosDTO->clave $auth_login;
$objParametrosDTO->password $auth_password;

$objParametrosConsulta = new stdClass();
$objParametrosConsulta->codigoInformacion '';
$objParametrosConsulta->motivoConsulta '';
$objParametrosConsulta->numeroIdentificacion '';
$objParametrosConsulta->tipoIdentificacion '';

try{
    
$sClient = new WSSoapClient($url$opciones);
    
//Cargamos la clave, passphrase y certificado
    
$sClient->key_file=$pk_file;
    
$sClient->cert_file=$cert_file;
    
$sClient->passphrase=$pk_passphrase;
    
$sClient->user $auth_login;
    
$sClient->password $auth_password;
    
    
//$result = $sClient->consultaPlano($objParametrosConsulta);
    
$result $sClient->obtenerCuestionario($objParametrosDTO);
    
var_dump($result);
}catch(
Exception $e){
    echo 
"<h2>Exception Error!</h2>"
    echo 
$e->getMessage(); 
    
//echo "<h2>Last Request!</h2>"; 
    //echo htmlentities($sClient->__getLastRequest());
}

?>
Agradezco cualquier ayuda que me puedan brindar,

Gracias de antemano.

Saludos.

Info adicional

Utilizando un programa llamado SoapUI, envié el XML que genera mi código, la respuesta del servidor fue distinta:

Código:
WSDoAllReceiver: security processing failed; nested exception is: 
org.apache.ws.security.WSSecurityException: The signature verification failed
Extraña cosa, cuando el mensaje es exactamente el mismo el mensaje es distinto. Espero que ésto sirva de algo.

Última edición por jasv; 26/10/2011 a las 10:57 Razón: Info adicional
  #2 (permalink)  
Antiguo 09/08/2012, 17:28
 
Fecha de Ingreso: agosto-2009
Mensajes: 9
Antigüedad: 10 años, 2 meses
Puntos: 0
Respuesta: XML Signature con PHP

Amigo, podrías decirme en que quedó el error, lo solucionaste?

Casualmente tengo inconvenientes similares y el webservice pertenece a la misma entidad a la cual debo conectarme.
  #3 (permalink)  
Antiguo 09/08/2012, 20:44
 
Fecha de Ingreso: julio-2008
Ubicación: Caldas, Antioquia, Colombia
Mensajes: 81
Antigüedad: 11 años, 4 meses
Puntos: 4
Respuesta: XML Signature con PHP

Hola,

Te dejo el código que me funcionó:

Código PHP:
Ver original
  1. <?php
  2.  
  3. require_once(dirname(__FILE__).'/soap-wsse.php');
  4.  
  5. class WSS_SoapClient extends SoapClient{
  6.     //Ruta del fichero de la clave privada
  7.     public $key_file="";
  8.     //Passphrase de la clave privada
  9.     public $passphrase="";
  10.     //Ruta del fichero del certificado
  11.     public $cert_file="";
  12.     //Mensaje SOAP enviado
  13.     public $soap_sent="";
  14.    
  15.     function __doRequest($request, $location, $action, $version, $one_way = null)
  16.     {
  17.         //Creamos un DOMDocument
  18.         $doc = new DOMDocument('1.0');
  19.         //Cargamos el XML pasado por parámetro
  20.         $doc->loadXML($request);
  21.        
  22.         //Creamos una instancia de WSSESoap con el documento, sin "mustUnderstand" ni "actor"
  23.         $objWSSE = new WSSESoap($doc,false,false);
  24.        
  25.         //Creamos una instacian de XMLSecurityKey con el RSA SHA1 y de tipo privado
  26.         $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1,array ('type'=>'private'));
  27.         //Pasamos el valor de passphrase
  28.         $objKey->passphrase=$this->passphrase;
  29.         //Cargamos la clave privada con la ruta del fichero, que es fichero y que no es certificado
  30.         $objKey->loadKey($this->key_file, TRUE);
  31.        
  32.         //Firmamos el mensaje
  33.         $objWSSE->signSoapDoc($objKey);
  34.        
  35.         //Añadimos el BinarySecurityToken, pasamos el contenido del certificado, le decimos que es formato PEM
  36.         $token = $objWSSE->addBinaryToken(file_get_contents($this->cert_file),TRUE);
  37.         //Añadimos el KeyInfo
  38.         $objWSSE->attachTokentoSig($token);
  39.        
  40.         //Añadimos el Timestamp
  41.         $objWSSE->addTimestamp(3600);
  42.        
  43.         //Guardamos el XML enviado
  44.         $this->soap_sent=$objWSSE->saveXML();
  45.         //echo htmlentities($this->soap_sent);exit();
  46.         //Llamamos al método __doRequest padre
  47.         return parent::__doRequest($this->soap_sent, $location, $saction, $version);
  48.     }
  49. }
  50.  
  51. $cliente = new WSS_SoapClient($wsdl,$opciones);
  52. $cliente->key_file = 'ruta/claveprivada.key;
  53. $cliente->passphrase = 'constraseñaclaveprivada';
  54. $cliente->cert_file = 'ruta/certificado.cert';

y así ya puedes utilizar las funciones del servicio normalmente.

Espero que te sirva.

Saludos.
  #4 (permalink)  
Antiguo 10/08/2012, 08:38
 
Fecha de Ingreso: agosto-2009
Mensajes: 9
Antigüedad: 10 años, 2 meses
Puntos: 0
Respuesta: XML Signature con PHP

Gracias por tu oportuna respuesta, tengo una pregunta, también debo incluir las librerías xmlseclibs ?
  #5 (permalink)  
Antiguo 10/08/2012, 14:04
 
Fecha de Ingreso: julio-2008
Ubicación: Caldas, Antioquia, Colombia
Mensajes: 81
Antigüedad: 11 años, 4 meses
Puntos: 4
Respuesta: XML Signature con PHP

Hola,

Sí, esa librería la utiliza soap-wsse.php.

Saludos.
  #6 (permalink)  
Antiguo 17/08/2012, 10:13
 
Fecha de Ingreso: agosto-2009
Mensajes: 9
Antigüedad: 10 años, 2 meses
Puntos: 0
Respuesta: XML Signature con PHP

No se porque no me funciona, no se que estaré haciendo mal :/


Mi certificado esta como archivo .cer y la clave privada como jks



Edito: Lo estoy haciendo con mi clave privada como archivo pem y ahora obtengo el siguiente error: Failure Signing Data: - 1



Edito: Los archivos .pem estaban malos, ya logré firmar el mensaje, sin embargo recibo error del servidor:
WSDoAllReceiver: security processing failed; nested exception is: org.apache.ws.security.WSSecurityException: The signature or decryption was invalid

y en ocaciones simplemente un:

Server error.

edito: Solucionado, eran un par de lineas que había metido de más, el código de Jasv Funciona perfectamente!! Muchas gracias!!!

Última edición por RootX7; 21/08/2012 a las 15:45
  #7 (permalink)  
Antiguo 28/08/2012, 11:12
 
Fecha de Ingreso: agosto-2009
Mensajes: 9
Antigüedad: 10 años, 2 meses
Puntos: 0
Respuesta: XML Signature con PHP

Saludos aquí yo de nuevo, compañero, tengo una duda, resulta que ya puedo acceder a casi todos los servicios normalmente, con excepción de http://.../ConfrontaWebService?wsdl

me genera el siguiente error:

SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://.../ConfrontaWebService?wsdl' : Extra content at the end of the document

de casualidad a vos te salió ese error? si es así, podrias por favor decirme como podría solucionarlo? he buscado en google pero no encuentro una solución que funcione.

También probé haciendo la conexion en NON WSDL MODE, sin embargo al hacerlo de esta manera se genera otro error al firmar el documento xml.

Gracias de Antemano





EDITO: Lo solucioné descargando el WSDL y llamandolo localmente.

Última edición por RootX7; 30/08/2012 a las 10:25
  #8 (permalink)  
Antiguo 23/07/2014, 10:51
 
Fecha de Ingreso: julio-2014
Mensajes: 2
Antigüedad: 5 años, 3 meses
Puntos: 0
Respuesta: XML Signature con PHP

Hola RootX7,

en la explicación se necesita los siguiente:

$cliente->key_file = 'ruta/claveprivada.key';
$cliente->passphrase = 'constraseñaclaveprivada';
$cliente->cert_file = 'ruta/certificado.cert';

en tu caso, no tenías los archivos claveprivada.key y certificado.cert sino el certificado.pem. En ese caso, como los haces, le agradezco su ayuda.


Te pregunto esto porque lo que quiero hacer es lo siguiente, tengo un xml localmente y necesito firmarlo y enviarlo via webservice.

gracias
  #9 (permalink)  
Antiguo 23/07/2014, 11:52
Avatar de bookmaster  
Fecha de Ingreso: febrero-2002
Ubicación: Toledo
Mensajes: 976
Antigüedad: 17 años, 8 meses
Puntos: 67
Respuesta: XML Signature con PHP

lrmilians fíjate que este es un tema de hace 2 años.
Por favor trata de no re abrirlos, si necesitas hacer algo parecido crea un tema nuevo exponiendo tu caso en particular.
__________________
Decir si te a funcionado la respuesta es ¡GRATIS!. Por favor indicarlo.
http://www.lohacemosweb.net
http://tutoriales.lohacemosweb.net

Etiquetas: signature, ws-security, xml
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 21:34.