----- 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? -- Endi S. Dewata _______________________________________________ Pki-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/pki-devel
