CRLibre / API_Hacienda

API libre para Factura Electrónica en Costa Rica, interfaz para integrar sistemas con el Ministerio de Hacienda para la Facturación Electrónica
https://crlibre.org/factura-electronica/
GNU Affero General Public License v3.0
164 stars 119 forks source link

Fix non-integer `X509SerialNumber` since OpenSSL 1.1.x #155

Closed fdelapena closed 1 year ago

fdelapena commented 2 years ago

fixes the 'La firma del documento no tiene el Policy Id' validator error message

This happens with BCCR-SINPE certificates, their serial numbers are too long, so they trigger this issue: https://bugs.php.net/bug.php?id=77411

Since PHP 7.x exists serialNumberHex, not affected by this issue, but preferred to keep backwards compatibility for old setups.

Because the number is too long for hexadecimal to decimal conversion (hexdec), added a convenient function not requiring php-bcmath or php-gmp extensions being installed.

fdelapena commented 2 years ago

Para testar este PR:

Existe un certificado de una jerarquía de prueba para sello electrónico con un número de serie suficientemente largo para reproducir el problema:

63 00 00 09 F1 4B D4 1A 06 E9 80 1F F4 00 01 00 00 09 F1

Este certificado de prueba está disponible en el siguiente ZIP:

https://www.firmadigital.go.cr/repositorio/CertificadosDePruebaSHA2-PersonaJuridica.zip

En el LEAME del zip viene la contraseña de los p12/pfx (pjsha2).

El certificado sugerido para probar es el de Certificados/Válidos/EmpresaValida-AgenteElectronico.pfx (válido en el sentido de que se trata de un certificado no revocado y no expirado, pero es una jerarquía de CA para pruebas y por tanto no confiada).

Al firmar, si PHP agrega un 0x en el número de serie, haciendo que no sea un valor entero válido según el xsd de XMLDsig, se reproduce el error. Con este PR se resuelve el problema y genera un valor decimal.

El xsd se puede consultar en https://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd

En él se puede observar la restricción del campo:

<complexType name="X509IssuerSerialType">
  <sequence>
    <element name="X509IssuerName" type="string"/>
    <element name="X509SerialNumber" type="integer"/>
  </sequence>
</complexType>

Al contener el 0x, además los caracteres de la A a la F, que no son del 0 al 9, no se consideraría Integer sino String, lo que hace fallar al validador.

cc @JeanCarlosChavarriaHughes

Nota: he borrado el repositorio del pull request, quien quiera aplicarlo he subido el parche a un issue.