New issuer for letsencrypt staging

We are making use of letsencrypt staging certificates for internal dev use and it looks like after the maintenance performed on Feb 18th (today) the issuer has changed from "Fake LE Intermediate X1" to "(STAGING) Artificial Apricot R3" and the staging X1 certificates available on Staging Environment - Let's Encrypt - Free SSL/TLS Certificates are no longer valid.

Is there a workaround available for this?

5 Likes

Hi @supericy,

You can fetch the new staging root from http://stg-dst3.i.lencr.org/ (note! do not add to trust stores). The intermediates are served via ACME. Thanks for the reminder about the documentation page. We'll get that updated. :slight_smile:

6 Likes

Thank you @jsha , but the new root cert (STAGING) Doctored Durian Root CA X3 is expired on 30 Jan 2021, is this by purpose?

4 Likes

@jsha The root cert " CN=(STAGING) Doctored Durian Root CA X3" has expired on Jan 30.

1 Like

@jsha For testing purpose we use the staging cert for ssl-verify some of the URLs . All our testcases are failing as the staging root CA is an expired cert. Please confirm if this is is bug in letsencrypt or intentional ?r
equests.exceptions.SSLError (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1091)')))al

1 Like

Here is how to get to the Doctored Durian Root CA X3 in PEM format.

Download in DER format:

$ curl http://stg-dst3.i.lencr.org/ > le-staging-root-durian.der

Show detail:

$ openssl x509 -inform der -in le-staging-root-durian.der -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ba:8c:66:24:4d:69:11:78:10:66:52:f6:ea:e5:8f:ed
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = (STAGING) Internet Security Research Group, CN = (STAGING) Doctored Durian Root CA X3
        Validity
            Not Before: Sep 30 21:12:19 2000 GMT
            Not After : Jan 30 14:01:15 2021 GMT
        Subject: C = US, O = (STAGING) Internet Security Research Group, CN = (STAGING) Doctored Durian Root CA X3
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:a9:46:63:a1:16:e3:81:77:9c:3d:6c:57:90:60:
...

Show as PEM:

$ openssl x509 -inform der -in le-staging-root-durian.der -out le-staging-root-durian.pem

PEM version of this cert:

$ cat le-staging-root-durian.pem 
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIRALqMZiRNaRF4EGZS9urlj+0wDQYJKoZIhvcNAQELBQAw
cTELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
cml0eSBSZXNlYXJjaCBHcm91cDEtMCsGA1UEAxMkKFNUQUdJTkcpIERvY3RvcmVk
IER1cmlhbiBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDEzMDE0MDEx
NVowcTELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBT
ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEtMCsGA1UEAxMkKFNUQUdJTkcpIERvY3Rv
cmVkIER1cmlhbiBSb290IENBIFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAqUZjoRbjgXecPWxXkGCUEXcNrupL7dkbwc0jUTLFEDvcyfD1gYekY5uL
D19uzYTl0pKZzzDXHJPnJY5EEp27nACFOm8XzX9sORAangP0OnGUkXJZDHM+8cX2
EHJbfj0lg1JirRF3w2u1/KRuFEvIlWg3FdXdsSFHBF5z1Ij7MLn7Ska5c/5fKsDW
EYzOMB6EBW1T9RDkVk/Q965EwDT4bR6BOXakasgfKrH9m1f6l9MmA0VnXdw9rZ+s
TvMHG1yWBqNMSqCKe3jG6caWgN7llEbj5YsCWs32bz2dMftGkXBPcy1fNWvpeT7G
Dz2Z0QWTlHkyXA2kGw32fdoXLHWOEwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYw
DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCFfaiceiU3kMT93gkI90uuInc0Qw
DQYJKoZIhvcNAQELBQADggEBAF7lEtHuSN4j+xFQsM/ujaVKcn57VbrbTecnspmJ
JA7Hrn6OErshGNO0p1/u14c7tGHKjtF1tEFFSVhbNXlKw9O99AfhmlFgdGcJKEHn
ZctBB8bhNO387vbiCYIHdU/nSba9MCDYw2/UCtobZ6ao+KJA3IKmPixctAbn2Ikr
EN9X0SXNP1gnqQP4VhZJIh6cd7rg9MimzoLlMI3m2z11dSGYbh8OWSdvA7aLbSGo
gDO5H4WD8fgqEG0reSBO89eeH+we+BZxQtBiU3b9VMV0drc+7zC2NbXqeQwu6QTl
fbJ8ytqcqUy0g5XSE6WCzPOL3H9r0j9G64dfotGlBA5tG6w=
-----END CERTIFICATE-----
2 Likes

@jsha I figured the expiry of the root CA cert deserves its own thread -- I have created (STAGING) Doctored Durian Root CA X3 is expired (breaks test environment).

2 Likes

FWIW, if anyone needs to do this without OpenSSL, PEM is just DER encoded into base64 with text-wrapping and a header/footer.

In Python the conversions between the two formats are:

import textwrap
import base64


def convert_der_to_pem(der_data=None, header_object="CERTIFICATE"):
    """
    :param der_data: string of DER formatted certificate.
    :param header_object: string. see function for valid options
    """
    _valid_header_objects = (
        "CERTIFICATE",
        "RSA PRIVATE KEY",
        "PRIVATE KEY",
        "CERTIFICATE REQUEST",
    )
    if header_object not in _valid_header_objects:
        raise ValueError("invalid header object")
    as_pem = """-----BEGIN {0}-----\n{1}\n-----END {2}-----\n""".format(
        header_object,
        "\n".join(textwrap.wrap(base64.b64encode(der_data).decode("utf8"), 64)),
        header_object,
    )
    return as_pem


def convert_pem_to_der(pem_data=None):
    lines = [l.strip() for l in pem_data.strip().split("\n")]
    # remove the BEGIN header
    if (
        ("BEGIN CERTIFICATE" in lines[0])
        or ("BEGIN RSA PRIVATE KEY" in lines[0])
        or ("BEGIN PRIVATE KEY" in lines[0])
        or ("BEGIN CERTIFICATE REQUEST" in lines[0])
    ):
        lines = lines[1:]
    # remove the END header
    if (
        ("END CERTIFICATE" in lines[-1])
        or ("END RSA PRIVATE KEY" in lines[-1])
        or ("END PRIVATE KEY" in lines[-1])
        or ("END CERTIFICATE REQUEST" in lines[-1])
    ):
        lines = lines[:-1]
    lines = "".join(lines)
    result = base64.b64decode(lines)
    return result
2 Likes

To supplement @jvanasco's excellent contribution, I've written a small bit of PHP that transforms an ECDSA CSR in PEM format to the Base64 DER format expected by the ACME protocol as the payload of order finalization. You can copy it from here then try it out at:

https://extendsclass.com/php.html

<?php

$configargs = [
  "private_key_type" => OPENSSL_KEYTYPE_EC,
  "curve_name" => "prime256v1",
  "digest_alg" => "sha256"
];

$privateKeyObject = openssl_pkey_new($configargs);

openssl_pkey_export($privateKeyObject, $privateKey);

$dn = [
  "commonName" => "mywebsite.com"
];

$configargs = [
  "digest_alg" => "sha256"
];

$csrObject = openssl_csr_new($dn, $privateKey, $configargs);

openssl_csr_export($csrObject, $csr);

$regex = "~^-----BEGIN CERTIFICATE REQUEST-----([A-Za-z0-9+/]+=?=?)-----END CERTIFICATE REQUEST-----$~";

$csrACME = str_replace("\n", "", $csr);

preg_match($regex, $csrACME, $matches);

$csrACME = strtr(rtrim($matches[1], '='), '+/', '-_');

echo "<pre>\n";
echo print_r(openssl_pkey_get_details($privateKeyObject));
echo "\n\n";
echo print_r($privateKey);
echo "\n\n";
echo print_r(openssl_csr_get_subject($csrObject));
echo "\n\n";
echo print_r($csr);
echo "\n\n";
echo print_r($csrACME);
echo "\n</pre>";

?>
2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.