On Fri, Mar 20, 2020 at 03:41:05PM -0400, Endi Sukma Dewata wrote: > ----- Original Message ----- > > > Let me backtrack a little bit. Is there a plan to modify Dogtag to > > > eventually support different serial number domains? If not, this is > > > not an issue for Dogtag. > > > > There is no plan to do so. It is not an issue for Dogtag. But > > still, I feel basing certificate ID on only serial number is not a > > robust approach in general. > > > > > If there is such plan, will the issuer DN > > > be unique across LWCAs? If issuer DN will be unique, it's something > > > to consider. If not, (issuer DN, serial number) will not be unique > > > either, so we need to use something else such as authority ID. > > > > > > Or is there another backend with multiple issuers that we want to > > > support in the future? The cert ID will have to be something like > > > (issuer ID, serial number) where the issuer ID is unique for the > > > backend. If the issuer DN is unique, it can be used as the issuer > > > ID. Otherwise, it needs to be a backend-specific unique ID similar > > > to authority ID in Dogtag. > > > > All certs must have unique (issuer,serial). This is implied by the > > requirement that all certs from a given issuer must have different > > serial numbers. > > > > > We need to consider these possibilities before changing the cert ID. > > > On the other hand, I'm still not sure it's actually necessary to > > > include these information into cert ID. > > > > > > Let's look at the code. For cert enrollment (ACMEFinalizeOrderService) > > > we convert the serial number that we get from ACMEBackend into cert ID: > > > > > > BigInteger serialNumber = backend.issueCertificate(csr); > > > String certID = > > > Base64.encodeBase64URLSafeString(serialNumber.toByteArray()); > > > > > > We can change it so ACMEBackend can generate the cert ID like this: > > > > > > String certID = backend.issueCertificate(csr); > > > > > > > I strongly agree with pushing the certID generation into the > > ACMEBackend. Stepping away from the whole (issuer,serial) > > discussion, say (for example) the only "handle" a backend has for > > accessing a cert is a UUID. Then storing the serial number is no > > good - you cannot derive the UUID handle from the serial number. > > > > So the backend must generate the (String) certID that is appropriate > > for that backend. > > > > > If the cert ID is (issuer DN, serial number), we can generate the > > > cert ID from the new cert. But does the backend return the new cert > > > or just the serial number? > > > > > Yeah, good question; of course you must be able to retrieve the > > cert (and therefore you can learn the Issuer DN) but this could mean > > another round-trip to Dogtag. Which is the next thing you said :) > > > > > If the serial number is not unique, the > > > backend might need to be changed to return the cert itself so we > > > can get the issuer DN. > > > > > > If the cert ID is (authority ID, serial number), how do we get the > > > authority ID since it's not included in the cert? The backend might > > > need to be changed to return the authority ID along with the new > > > cert, or to provide a way to look up the authority ID using a cert. > > > > > I am not suggesting to use the authority ID. But FWIW Dogtag does > > enforce that Issuer DN <-> Authority ID is a bijection. > > > > > > > > For cert retrieval (ACMECertificateService) we're passing the cert ID > > > to ACMEBackend: > > > > > > String certChain = backend.getCertificateChain(certID); > > > > > > The ACMEBackend can extract the issuer DN or authority ID from the > > > cert ID so it can retrieve the cert from the backend again. > > > > > > Since we get the cert during enrollment anyway, we can actually store > > > it into ACME database like this: > > > > > > String certChain = backend.issueCertificate(csr); > > > String certID = database.addCert(certChain, orderID, accountID, > > > expirationTime); > > > > > > Later we can simply retrieve it from the database instead of calling > > > the backend again: > > > > > > String certChain = database.getCertificateChain(certID); > > > > > As I said in previous email, I am opposed to storing the cert > > (chain) in the ACME database. If some backend requires it e.g. > > because the backend itself does not store the cert, then it can be > > optional. But we do not need that now. > > > > > Here the cert ID can simply be a unique ID generated by the database. > > > Unlike earlier, the backend doesn't need to know about cert ID at all. > > > > > > For cert revocation (ACMERevokeCertificateService) the client will > > > only provide the cert binaries. It doesn't provide the cert ID. > > > > > And the ACMEBackend implementation receives the cert, and must work > > out what to do with it. How it tells the backend system to revoke > > the certificate, and whether that process even involves a string > > CertID handle, or just a serial number, or the (issuer,serial) pair, > > or whatever, depends on the backend system. But I think that the > > current interface: > > > > public void revokeCert(ACMERevocation revocation) ... > > > > ... is suitable. > > > > > Currently the ACMEEngine.validateRevocation() will generate the > > > cert ID from the serial number so it can find the order that > > > generated the cert (so we can authorize the account): > > > > > > String certID = > > > Base64.encodeBase64URLSafeString(serialNumber.toByteArray()); > > > ACMEOrder order = database.getOrderByCertificate(certID); > > > > > > We can changed it so ACMEBackend can generate the cert ID like this: > > > > > > String certID = backend.getCertID(certBytes); > > > ACMEOrder order = database.getOrderByCertificate(certID); > > > > > > If the cert ID is (issuer DN, serial number), we can generate the > > > cert ID from the provided cert binaries. But if the cert ID is > > > (authority ID, serial number), how do we get the authority ID? Do > > > we call the lookup operation above again to get the authority ID? > > > > > > Instead of that we can do this: > > > > > > String certID = database.getCertID(certBytes); > > > ACMEOrder order = database.getOrderByCertificate(certID); > > > > > > which doesn't involve the backend at all. > > > > > > So backend-issued cert ID might work if we use a backend that > > > already provides the required functionality above. Otherwise we > > > may need to modify the backend, which is not always an option. > > > > > > The database-issued cert ID is a solution that doesn't require > > > modifications to the backend, so I think it should be the default > > > option. The certs stored in ACME database should be considered > > > a cache. The server can purge it so it doesn't grow too large if > > > that's a concern. > > > > > > Note that regardless of cert ID, the above revocation mechanism > > > relies on order, authorization, or cert records in ACME database, > > > which may not be available depending on the server's purging > > > policy. If someone needs to have a reliable revocation mechanism > > > they need to revoke using the private key. > > > > > Let us put aside the discussion about whether for the PKIBackend we > > use only (serial) as certID, or (issuer,serial) pair. I think we > > *should* switch to something derived from (issuer,serial), but we do > > not *need* to. So we can leave that discussion for now. > > > > The main change we need is for ACMEBackend.issuerCertificate to > > return String certID, i.e.: > > > > public String issuerCertificate(String csr) ... > > > > because BigInteger (i.e. serial) may not be an appropriate "handle" > > for all backends. Hence we should require each ACMEBackend > > implementation to produce the appropriate certIDs. > > > > Do you agree? > > > > Cheers, > > Fraser > > > > Hi Fraser, > > Please take a look at this PR: > https://github.com/dogtagpki/pki/pull/350 > > So the PKIBackend will continue to work like before, but > these changes should allow us to support: > - both single-authority and multi-authority backends > - both one-step and two-step enrollments > > One thing though, I think we discussed before about using UUID to > generate the serial number which has a very low chance of collision. > If a backend uses UUID for all of its certificate authorities, can > the serial number by itself be considered unique? > Practically speaking, I'd say yes.
As I already discussed at length, I'd prefer we rely on what X.509 *requires* to be unique (i.e. (issuer,serial)) where possible. But if we are confident a backend with multiple issuers has a single serial number domain (whether they are UUIDs or just a single sequential source like Dogtag), *and* that this property is unlikely to change, then I can live with it. I'll try to review PR 350 today. Cheers, Fraser _______________________________________________ Pki-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/pki-devel
