• # c'est la fête avec OpenSSL sous Windows

    Posté par (site web personnel) . En réponse au journal Certificat expiré. Évalué à 10. Dernière modification le 01 octobre 2021 à 19:59.

    Sous Windows, le nouveau certificat racine ISRG Root X1 (celui qui remplace DST Root CA X3) est ajouté à la liste des certificats de l'OS de manière lazy la première fois qu'il est utilisé.

    Le soucis c'est que seul l'implémentation de TLS fourni par l'api Windows (cad CertVerifyCertificateChainPolicy ) déclenche cette récupération !

    Concrètement ça veut dire que si tu utilises uniquement Firefox (qui embarque ses propres certificats racine et n'utilise pas l'api windows pour faire du TLS), et bien il y a toutes les chances que ton PC n'ait pas ISRG Root X1.
    Et du coup quand tu utilises OpenSSL avec les certificats du système (c'est ce que fait Python par default) tu te retrouves avec une belle erreur SSL ! (Python récupèrant les certificats auprès du système avant de les charger dans OpenSSL)

    Le plus beau étant que pour résoudre ça il suffit d'ailleurs sur n'importe quel site utilisant Let's Encrypt depuis Edge/IE/Chrome (ce qui va déclencher la récupération de ISRG Root X1).

    plus d'info:
    https://community.letsencrypt.org/t/isrg-root-lazy-loading-problem-missing-from-random-updated-windows-10-versions/141550
    https://docs.certifytheweb.com/docs/kb/kb-202109-letsencrypt/
    https://github.com/psf/requests/issues/2966#issuecomment-636750327

    Et comme vous êtes gourmand, petit bonus:
    Tous les certificats fournis par Let's Encrypt son signés par le certificat intermédiaire S3 qui est disponible signé par DST Root CA X3 et ISRG Root X1.
    Si il se trouve que par hasard vous avez le certificat intermédiaire S3 signé par DST Root CA X3 sur votre machine, alors c'est celui-ci qui sera utilisé (d'ailleurs si vous avez une idée pourquoi je suis preneur ) et provoquera une erreur:

    $ python -c "from urllib.request import urlopen; print(urlopen('https://linuxfr.org').status)"
    Traceback (most recent call last):
    [...]
    urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1131)>
    

    La solution ? Faire comme Firefox et embarquer ses propres certificats racines dans son application (mais du coup 1) incompatible avec ces "passerelles de sécurité" à moins de permettre un mécanisme de chargement de certifs additionnels et 2) obligé de mettre à jour l'application quand les certificats changent :'( )