----- 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