Implementing ARI / POST issue

So I've been trying to implement ARI for win-acme according to the RFC but I can't get the POST endpoint working.

The GET endpoint works fine so I'm pretty sure there is no problem with my calculation of certID, yet I always get the error "Certificate not found" on post. Reading the Boulder source, that's caused by this call failing:

metadata, err := wfe.sa.GetSerialMetadata(ctx, &sapb.Serial{Serial: serial})

Is it possible that something is not entirely deployed or implemented yet? Same thing happens both in test and prod, even on brand-new certificates.

Recent request payload on test:

{"certID":"MGgwDQYJYIZIAWUDBAIBBQAEIOpkIqHI_Ls_OhlCdhE04lJbuQeWAJOnNXYBVVd5McY8BCDSVL7W2ZsvDB2XvGCxFyqANyOEGpzMnWghk6IzVt0J4QITAPq2fJCRPuOPeIQPmgxgZpHUYw","replaced":true}

Any pointers would be appreciated :slight_smile:

2 Likes

Could you perhaps provide the entire JWS object causing the error?

4 Likes

Sure. So this is a simple test case where I order a new certificate and then immediately post the update request (on the test endpoint)

{"protected":"eyJhbGciOiJFUzI1NiIsInVybCI6Imh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2dldC9kcmFmdC1pZXRmLWFjbWUtYXJpLTAwL3JlbmV3YWxJbmZvLyIsIm5vbmNlIjoiOEYwNWtQUll6T2FDYThfYS1oSHBFMGtKOWFSaWpOQ0ZnQUFNSUk0YkRwdlEyWEEiLCJraWQiOiJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvOTM4NjY2MTQifQ","payload":"eyJjZXJ0SUQiOiJNR2d3RFFZSllJWklBV1VEQkFJQkJRQUVJT3BrSXFISV9Mc19PaGxDZGhFMDRsSmJ1UWVXQUpPbk5YWUJWVmQ1TWNZOEJDRFNWTDdXMlpzdkRCMlh2R0N4RnlxQU55T0VHcHpNbldnaGs2SXpWdDBKNFFJVEFQcTY3YTRvYnR3RGpWeXdrUjdDV1VfVmNBIiwicmVwbGFjZWQiOnRydWV9","signature":"ZieLUfE3NsSo107WK0IjK2L02amcEcDYpwUyXqGFl8dBY0b4c4VxSvoavw9Y8qhxGkfunQGJBoC_gNMcZduTFw"}

3 Likes

Your ASN.1 certid object doesn't look valid to me:

The example from draft-ietf-acme-ari-01 uses this payload:

MFswCwYJYIZIAWUDBAIBBCCeWLRusNLb++vmWOkxm34qDjTMWkc3utIhOMoMwKDqbgQg2iiKWySZrD+6c88HMZ6vhIHZPamChLlzGHeZ7pTS8jYCCD6jRWhlRB8c

which decodes to:

  0  91: SEQUENCE {
  2  11:   SEQUENCE {
  4   9:     OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
       :     }
 15  32:   OCTET STRING
       :     9E 58 B4 6E B0 D2 DB FB EB E6 58 E9 31 9B 7E 2A
       :     0E 34 CC 5A 47 37 BA D2 21 38 CA 0C C0 A0 EA 6E
 49  32:   OCTET STRING
       :     DA 28 8A 5B 24 99 AC 3F BA 73 CF 07 31 9E AF 84
       :     81 D9 3D A9 82 84 B9 73 18 77 99 EE 94 D2 F2 36
 83   8:   INTEGER 3E A3 45 68 65 44 1F 1C
       :   }

Your payload

MGgwDQYJYIZIAWUDBAIBBQAEIOpkIqHI/Ls/OhlCdhE04lJbuQeWAJOnNXYBVVd5McY8BCDSVL7W2ZsvDB2XvGCxFyqANyOEGpzMnWghk6IzVt0J4QITAPq2fJCRPuOPeIQPmgxgZpHUYw==

decodes to:



  0 104: SEQUENCE {
  2  13:   SEQUENCE {
  4   9:     OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
 15   0:     NULL
       :     }
 17  32:   OCTET STRING
       :     EA 64 22 A1 C8 FC BB 3F 3A 19 42 76 11 34 E2 52
       :     5B B9 07 96 00 93 A7 35 76 01 55 57 79 31 C6 3C
 51  32:   OCTET STRING
       :     D2 54 BE D6 D9 9B 2F 0C 1D 97 BC 60 B1 17 2A 80
       :     37 23 84 1A 9C CC 9D 68 21 93 A2 33 56 DD 09 E1
 85  19:   INTEGER 00 FA B6 7C 90 91 3E E3 8F 78 84 0F 9A 0C 60 66 91 D4 63
       :   }

Which looks like there's an extra null byte there.

10 Likes
83   8:   INTEGER 3E A3 45 68 65 44 1F 1C
85  19:   INTEGER 00 FA B6 7C 90 91 3E E3 8F 78 84 0F 9A 0C 60 66 91 D4 63

And are both Integer type?

7 Likes

Thanks for your feedback. Based on this and the source shared by @webprofusion I found two issues with my previous code which looked promising to be the "smoking guns", but unfortunately it's still not working.

  1. Changed certificateId.ToAsn1Object().GetEncoded(); to certificateId.ToAsn1Object().GetDerEncoded();
  2. I now use the leaf certificate as input to construct the certificateId, rather than the issuer of the leaf (the parameter naming in the BouncyCastle library threw me off)

Yet the behaviour remains the entirely the same. I can happily GET the renewalInfo but POSTing using the same identifier immediately afterwards (the id generator function is shared between the two) leads to the "Certificate not found" error.

Now the payload is:

{"protected":"eyJhbGciOiJFUzI1NiIsInVybCI6Imh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2dldC9kcmFmdC1pZXRmLWFjbWUtYXJpLTAwL3JlbmV3YWxJbmZvLyIsIm5vbmNlIjoiQjM3QzF6TnRVWk9HYWlQOTZ6eGhad18wVU5Eel9ud0pMSXdCMlRBMldiOTlza3MiLCJraWQiOiJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvOTM4NjY2MTQifQ","payload":"eyJjZXJ0SUQiOiJNR2d3RFFZSllJWklBV1VEQkFJQkJRQUVJSEMxQ01idDVodGlOXzM4VDVvcXA5Ny1VRDR6VkxmNWpOMWlLZ2RmdWt3dkJDQTdIY0FxOXBEUUV2d3h3NjlJVVZBUHFmTmlRX09GRXZlV0t5ZlpPM2MxUmdJVEFQcURiUG9qU1JQbW5id2owX1ZlcXNWVkFnIiwicmVwbGFjZWQiOnRydWV9","signature":"oefmcP-E0rhyxgOv1bAZzXEIBTbio9MiOJ7lMImEDBAe8N5jc0RC_kfUTUHd9caZWBtEjrsFmNJVSCH7cokJ-g"}

5 Likes

That's supposed to be the certs serial. I haven't looked at them in greater detail, but I guess the example uses 64 bit numbers and LE staging/prod uses 128 bit serials

7 Likes

There's actually a difference in how Boulder selects certificates on GET vs POST requests.

On GET requests, it basically boils down to:

On POST requests, it's:

So there appears to be a definite difference in behaviour, though I'm not sure why either relates to your problem. Your serials look correct to me, though you might want to post the full certificate here as well so that we can cross-check. Looking up staging certs from CT is painful.

The NULL in your ASN.1 is still there by the way, so that may still be the issue. Though the parsing code looks identical enough for both POST and GET.*

(Also: You are actually using an ECDSA account key, correct?)

*The OpenSSL OCSP tool also produces these NULL stop-byte in it's OCSP requests, so it seems valid to do that.

PPS: Your issuerKeyHash looks wrong (it doesn't match staging's R3 nor E1), but I don't think boulder cares much about these values at all.

8 Likes

Thanks for investigating, I did another run and captured the entire certificate chain as received from the staging endpoint. BouncyCastle reads the serial as 21790042814121155191743235894085329638597059.

Then I GET to https://acme-staging-v02.api.letsencrypt.org/get/draft-ietf-acme-ari-00/renewalInfo/MGgwDQYJYIZIAWUDBAIBBQAEINbwv9Ii7lJ7Rl4MK_UC8owq_M2InTeCZYXsMrnbPuPwBCDNzUtT3QwFEFhoaK3_FfGJEtnTw644tq24sfDn3seIAQITAPojLjqFA3zKfrlqpLFiaishww, which succeeds and suggests renewal between 2023-05-26 and 2023-05-28.

Then I POST to https://acme-staging-v02.api.letsencrypt.org/get/draft-ietf-acme-ari-00/renewalInfo/ with this as payload:

{"protected":"eyJhbGciOiJFUzI1NiIsInVybCI6Imh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2dldC9kcmFmdC1pZXRmLWFjbWUtYXJpLTAwL3JlbmV3YWxJbmZvLyIsIm5vbmNlIjoiQTI3MkExX1JnbHl0T25DWkhxSFpMNkRtNGs0d254aEhQdlBzSjM1eWZQckViREkiLCJraWQiOiJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvOTM4NjY2MTQifQ","payload":"eyJjZXJ0SUQiOiJNR2d3RFFZSllJWklBV1VEQkFJQkJRQUVJTmJ3djlJaTdsSjdSbDRNS19VQzhvd3FfTTJJblRlQ1pZWHNNcm5iUHVQd0JDRE56VXRUM1F3RkVGaG9hSzNfRmZHSkV0blR3NjQ0dHEyNHNmRG4zc2VJQVFJVEFQb2pManFGQTN6S2ZybHFwTEZpYWlzaHd3IiwicmVwbGFjZWQiOnRydWV9","signature":"bW1SR6uuG2dysdnLy6F_0MMim_sy4iGzDXG1dWWZUXipNcb6c7WVwztbp4oJlWs3NpX9nu17f5XB5B0_aI1zKA"}

Which boils down to:

{"certID":"MGgwDQYJYIZIAWUDBAIBBQAEINbwv9Ii7lJ7Rl4MK_UC8owq_M2InTeCZYXsMrnbPuPwBCDNzUtT3QwFEFhoaK3_FfGJEtnTw644tq24sfDn3seIAQITAPojLjqFA3zKfrlqpLFiaishww","replaced":true}

(note that the certID is identical between the POST payload and the GET url)
And the response looks like

 {
  "type": "urn:ietf:params:acme:error:malformed",
  "detail": "Certificate not found",
  "status": 404
}

Here is the full certificate chain for the certificate that I got for this run, straight from Boulder:

-----BEGIN CERTIFICATE-----
MIIF7TCCBNWgAwIBAgITAPojLjqFA3zKfrlqpLFiaishwzANBgkqhkiG9w0BAQsF
ADBZMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXKFNUQUdJTkcpIExldCdzIEVuY3J5
cHQxKDAmBgNVBAMTHyhTVEFHSU5HKSBBcnRpZmljaWFsIEFwcmljb3QgUjMwHhcN
MjMwMzI4MTYyODU1WhcNMjMwNjI2MTYyODU0WjAmMSQwIgYDVQQDExthbm90aGVy
LndvdXRlci50aW51cy5vbmxpbmUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
AoIBgQCCwZpKcBoVH86lyVvdUZGdL/mllPSU/OLvkCrp6w4Y8owF0tVttRBclhJK
nMvSoezOhRllnPKkfi8DjFbasMQqqwys/GLPXFBzvGsfLeZTn2/CheBR7lkjsWXg
ANhRz14qpMbo8163/+Yo/m+Zv59lec7dQ3+2GKIPjQA/mB7mS6ZNo3/zZXv8S3E3
EIXiUD4j3rhYd4uuD09B/EnI7fcOMtGM6Zn6jgDehr5wBBtUs/Lk7D/48OPqg0sL
7sZFr3ZWitH49lBMeLdJKQv1u5VKsDLrWRqr4i+d4g9acVv8AAtAnAOPiwoQ/ScZ
bMxhqKHyOIwtvMIlMKlrYqjqVmr03Z7AMBD2E+S5jwiFoceUFhTHeGFeyz+SI/4l
7hOD/OOfwpqBVO2Sj68oM3CayeXpNjgrL1ccKgNjjEHIjazDs7WiI6t5ZHiaLScV
GcRMW/NHmzoSNNMPda8s6VI6iUUq9QxDOqU+Pb89j7UZ2g1Xn9m5hOKldewG7Qoo
fwLbQKMCAwEAAaOCAl8wggJbMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr
BgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUkJ+oLUq1
ZdSb5dkEqd/sbQnmJZ8wHwYDVR0jBBgwFoAU3nJ6SN8xw6ZQ35+FI99XN0tdLmUw
XQYIKwYBBQUHAQEEUTBPMCUGCCsGAQUFBzABhhlodHRwOi8vc3RnLXIzLm8ubGVu
Y3Iub3JnMCYGCCsGAQUFBzAChhpodHRwOi8vc3RnLXIzLmkubGVuY3Iub3JnLzAm
BgNVHREEHzAdghthbm90aGVyLndvdXRlci50aW51cy5vbmxpbmUwTAYDVR0gBEUw
QzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDov
L2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEFBgorBgEEAdZ5AgQCBIH2BIHzAPEAdwDB
gyQL8aRQx2+7AHJp3Kw74ipIBdTb4Elmw8irxEewDAAAAYcpRAB5AAAEAwBIMEYC
IQCgO9EJzLrRnl6Qt/rkyQPdmpV/agl5Md4v2IKELXF8bAIhAOc9kwUHW6lQSH2J
ZIhPapaZk0jeLTr6px5WeuYEE62wAHYAsMyD5aX5fWuvfAnMKEkEhyrH6IsTLGNQ
t8b9JuFsbHcAAAGHKUQAcQAABAMARzBFAiEAx1+pZTYfSewsY0pj6mnOCrCsFHSk
X/ZdaIJKa89oCVUCIGV1D8TftEVrdVh2Z99D+pQDIcakkMkPJwfjfOuq8HgVMA0G
CSqGSIb3DQEBCwUAA4IBAQBg71Xt0MaLcwALeTgUDJ14pxHDstuMdpKPqNSVvEZN
26Ocx7cbE+klxUIaHh5UO/UwgRwPBshbgHGtbpKy3UG8qdChGmNHg8zhwbOpRQcw
G2NhNWQlFVGNeedKH6YZQeS+Edwk5rg4SEKTK2cDkBf5al8xTWyZYyPfoQnDlzvi
2/9/jh71qathgjsX07EOjtvpDg73tGCAwtZKpU0c5rhKPF/3CRWH2gDY5lXru8cl
X1jTz7cBDNs9SWRdIXdaWmHI8WTVzWL7jVa0yUz16tIlEN3u1l6hqrZpJzFjf5GX
QeXpxltgJd54R+NscRSixvs0bVK2vy80Q5PDUAuAEB0m
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIFWzCCA0OgAwIBAgIQTfQrldHumzpMLrM7jRBd1jANBgkqhkiG9w0BAQsFADBm
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
ZWFyIFgxMB4XDTIwMDkwNDAwMDAwMFoXDTI1MDkxNTE2MDAwMFowWTELMAkGA1UE
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSgwJgYDVQQD
Ex8oU1RBR0lORykgQXJ0aWZpY2lhbCBBcHJpY290IFIzMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAu6TR8+74b46mOE1FUwBrvxzEYLck3iasmKrcQkb+
gy/z9Jy7QNIAl0B9pVKp4YU76JwxF5DOZZhi7vK7SbCkK6FbHlyU5BiDYIxbbfvO
L/jVGqdsSjNaJQTg3C3XrJja/HA4WCFEMVoT2wDZm8ABC1N+IQe7Q6FEqc8NwmTS
nmmRQm4TQvr06DP+zgFK/MNubxWWDSbSKKTH5im5j2fZfg+j/tM1bGaczFWw8/lS
nukyn5J2L+NJYnclzkXoh9nMFnyPmVbfyDPOc4Y25aTzVoeBKXa/cZ5MM+WddjdL
biWvm19f1sYn1aRaAIrkppv7kkn83vcth8XCG39qC2ZvaQIDAQABo4IBEDCCAQww
DgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAS
BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTecnpI3zHDplDfn4Uj31c3S10u
ZTAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXDFDA2BggrBgEFBQcBAQQq
MCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5sZW5jci5vcmcvMCsGA1Ud
HwQkMCIwIKAeoByGGmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMCIGA1UdIAQb
MBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCN
DLam9yN0EFxxn/3p+ruWO6n/9goCAM5PT6cC6fkjMs4uas6UGXJjr5j7PoTQf3C1
vuxiIGRJC6qxV7yc6U0X+w0Mj85sHI5DnQVWN5+D1er7mp13JJA0xbAbHa3Rlczn
y2Q82XKui8WHuWra0gb2KLpfboYj1Ghgkhr3gau83pC/WQ8HfkwcvSwhIYqTqxoZ
Uq8HIf3M82qS9aKOZE0CEmSyR1zZqQxJUT7emOUapkUN9poJ9zGc+FgRZvdro0XB
yphWXDaqMYph0DxW/10ig5j4xmmNDjCRmqIKsKoWA52wBTKKXK1na2ty/lW5dhtA
xkz5rVZFd4sgS4J0O+zm6d5GRkWsNJ4knotGXl8vtS3X40KXeb3A5+/3p0qaD215
Xq8oSNORfB2oI1kQuyEAJ5xvPTdfwRlyRG3lFYodrRg6poUBD/8fNTXMtzydpRgy
zUQZh/18F6B/iW6cbiRN9r2Hkh05Om+q0/6w0DdZe+8YrNpfhSObr/1eVZbKGMIY
qKmyZbBNu5ysENIK5MPc14mUeKmFjpN840VR5zunoU52lqpLDua/qIM8idk86xGW
xx2ml43DO/Ya/tVZVok0mO0TUjzJIfPqyvr455IsIut4RlCR9Iq0EDTve2/ZwCuG
hSjpTUFGSiQrR2JK2Evp+o6AETUkBCO1aw0PpQBPDQ==
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIFVDCCBDygAwIBAgIRAO1dW8lt+99NPs1qSY3Rs8cwDQYJKoZIhvcNAQELBQAw
cTELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
cml0eSBSZXNlYXJjaCBHcm91cDEtMCsGA1UEAxMkKFNUQUdJTkcpIERvY3RvcmVk
IER1cmlhbiBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQw
M1owZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBT
ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRl
bmQgUGVhciBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALbagEdD
Ta1QgGBWSYkyMhscZXENOBaVRTMX1hceJENgsL0Ma49D3MilI4KS38mtkmdF6cPW
nL++fgehT0FbRHZgjOEr8UAN4jH6omjrbTD++VZneTsMVaGamQmDdFl5g1gYaigk
kmx8OiCO68a4QXg4wSyn6iDipKP8utsE+x1E28SA75HOYqpdrk4HGxuULvlr03wZ
GTIf/oRt2/c+dYmDoaJhge+GOrLAEQByO7+8+vzOwpNAPEx6LW+crEEZ7eBXih6V
P19sTGy3yfqK5tPtTdXXCOQMKAp+gCj/VByhmIr+0iNDC540gtvV303WpcbwnkkL
YC0Ft2cYUyHtkstOfRcRO+K2cZozoSwVPyB8/J9RpcRK3jgnX9lujfwA/pAbP0J2
UPQFxmWFRQnFjaq6rkqbNEBgLy+kFL1NEsRbvFbKrRi5bYy2lNms2NJPZvdNQbT/
2dBZKmJqxHkxCuOQFjhJQNeO+Njm1Z1iATS/3rts2yZlqXKsxQUzN6vNbD8KnXRM
EeOXUYvbV4lqfCf8mS14WEbSiMy87GB5S9ucSV1XUrlTG5UGcMSZOBcEUpisRPEm
QWUOTWIoDQ5FOia/GI+Ki523r2ruEmbmG37EBSBXdxIdndqrjy+QVAmCebyDx9eV
EGOIpn26bW5LKerumJxa/CFBaKi4bRvmdJRLAgMBAAGjgfEwge4wDgYDVR0PAQH/
BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLXzZfL+sAqSH/s8ffNE
oKxjJcMUMB8GA1UdIwQYMBaAFAhX2onHolN5DE/d4JCPdLriJ3NEMDgGCCsGAQUF
BwEBBCwwKjAoBggrBgEFBQcwAoYcaHR0cDovL3N0Zy1kc3QzLmkubGVuY3Iub3Jn
LzAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8vc3RnLWRzdDMuYy5sZW5jci5vcmcv
MCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEB
CwUAA4IBAQB7tR8B0eIQSS6MhP5kuvGth+dN02DsIhr0yJtk2ehIcPIqSxRRmHGl
4u2c3QlvEpeRDp2w7eQdRTlI/WnNhY4JOofpMf2zwABgBWtAu0VooQcZZTpQruig
F/z6xYkBk3UHkjeqxzMN3d1EqGusxJoqgdTouZ5X5QTTIee9nQ3LEhWnRSXDx7Y0
ttR1BGfcdqHopO4IBqAhbkKRjF5zj7OD8cG35omywUbZtOJnftiI0nFcRaxbXo0v
oDfLD0S6+AC2R3tKpqjkNX6/91hrRFglUakyMcZU/xleqbv6+Lr3YD8PsBTub6lI
oZ2lS38fL18Aon458fbc0BPHtenfhKj5
-----END CERTIFICATE-----

(Also: You are actually using an ECDSA account key, correct?)

Yes, that's the default for win-acme. The account used for this run was https://acme-staging-v02.api.letsencrypt.org/acme/acct/93866614, if that helps

3 Likes

Aha. So I guess my initial implementation was correct after all.

I'm using the BouncyCastle library to compute the certID bytes, and its constructor takes three parameters: hash algorithm identifier, a certificate, and a serial number. Originally as the "certificate" I used the intermediate (i.e. R3) because that's what made more sense to me, but then after reading the source for Certify The Web I noticed that they put the leaf there, and I thought that this may have been the reason why my POST was not working.

But after reading your comment, I guess my original intuition was right after all and it's a bug in Certify The Web. This probably doesn't get us closer to a solution for the POST, but fixing this might prevent future issues when Let's Encrypt or others tighten their validation.

I have here another certificate with serial 21817192943007918687248147744066584879172227

-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

Where I get the certID using the intermediate as "certificate" instead of the leaf:

MGgwDQYJYIZIAWUDBAIBBQAEIOpkIqHI_Ls_OhlCdhE04lJbuQeWAJOnNXYBVVd5McY8BCDSVL7W2ZsvDB2XvGCxFyqANyOEGpzMnWghk6IzVt0J4QITAPpy97ckKyhiDoYs0WtPaWIKgw

And all other symptoms are the same.

3 Likes

Yeah we don't do the POST to update ARI yet in Certify The Web , so I haven't tried it. I'll have a look at the certbot code because I assume that works.

@aarongable is the expert here I think!

4 Likes

Just as a follow up, posting with the same CertID for get fails for me too, which seems like a Boulder bug.

I'm not seeing an ARI implementation in certbot to prove that it works.

@mholt did you get your version working with POST or have you not tried that yet?

4 Likes

I also get HTTP 404 urn:ietf:params:acme:error:malformed - Certificate not found with POST to the renewalInfo endpoint.

GET (with the CertID sequence appended to the renewalInfo URI) works for the same cert.

Can it only be found if it's within the renewal window?

I was hoping to test with Pebble but it looks like it hasn't been implemented there yet, either.

2 Likes

Reading the source from https://github.com/letsencrypt/boulder/blob/main/wfe2/wfe.go#L2363 I don't think it's anything sophisticated like that. In fact it still very much a work in progress, seeing this comment:

// TODO(#6732): Write the replaced status to persistent storage.

Should we raise an issue in Github?

EDIT: commented at ARI: store whether a certificate has been marked as replaced · Issue #6732 · letsencrypt/boulder · GitHub

3 Likes

There is already this:

But I think a 404 is a separate bug. Opened an issue:

3 Likes

I've landed a change which should fix this. Thanks to all of you for helping report and investigate this! Assuming nothing untoward happens, expect the fix to be deployed a week from today.

9 Likes

Awesome! Thanks!

5 Likes

The fix is being deployed to staging now.

8 Likes

Thanks! Can confirm that posting the update to the endpoint works for me now (200 OK) using same CertID used for the query. I don't notice any other change tothe renewal info after posting but I imagine it remains static when checking the same certId, as a renewal will have a new certId. I noticed the endpoint used for the post is currently confusingly prefixed /get/ but I'm sure that's temporary anyway.

8 Likes

The fix was deployed to production yesterday

9 Likes