Right now the checkpoints table fields mtcaSignature and mirrorSignature hold ML-DSA-44 signatures over a CosignedMessage with timestamp and start both zero.
tlog-cosignature says timestamp can be zero (in general): https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-witness.md
timestamp is timestamped_signature.timestamp. These two values MAY be zero if the cosigner doesn't make any statement as to the tree being the largest observed at time of signing.
However, tlog-witness puts a different requirement specifically on add-checkpoint: https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-witness.md#add-checkpoint
The cosignature MUST NOT omit the timestamp, i.e. the timestamp MUST NOT be zero.
We will be using add-checkpoint from tlog-mirror, not tlog-witness, but tlog-mirror's add-entries incorporates tlog-witness's add-checkpoint behavior: https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-mirror.md#add-entries
The response body MUST be formatted as in a witness's successful add-checkpoint response.
So signature lines we get from mirrors will always have a nonzero timestamp. If we fetch mirror checkpoints instead, the mirror could technically choose to sign a checkpoint with a zero timestamp, but that seems unlikely. And is out of our control anyhow.
Since these fields need a way to carry a per-signature timestamp, we need to store something other than an ML-DSA-44 signature. That's because, in order to verify these signatures, we need to know the timestamp they were signed over. And that will certainly be different between the CA and the mirror signature. A couple options:
- Store the
timestamped_signature data type from tlog-cosignature, which is timestamp || signature
- Store the signed-note signature line format, which additionally incorporates a key name and key ID.
I think we should do (2), since the majority of operations we will do with these values are done in the signed-note format:
- In the MTCA, write a checkpoint file with the CA signature attached.
- In the publisher, send the checkpoint file with CA signature to a mirror.
- In the MTCA, verify a signature from any trusted mirror before sequencing a new checkpoint. Technically this doesn't have to be verified using the signed-note format; we could construct a CosignedMessage directly from the checkpoint state and a
timestamped_signature.
This also suggests a format divide: the checkpoints table, used for tlog operations, uses signed-note format. The checkpointSubtrees table, used for X.509 operations, uses ML-DSA signatures over CosignedMessages, since those go into MTCProofs directly (and implicitly have timestamp zero).
Right now the
checkpointstable fieldsmtcaSignatureandmirrorSignaturehold ML-DSA-44 signatures over a CosignedMessage withtimestampandstartboth zero.tlog-cosignature says
timestampcan be zero (in general): https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-witness.mdHowever, tlog-witness puts a different requirement specifically on add-checkpoint: https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-witness.md#add-checkpoint
We will be using add-checkpoint from tlog-mirror, not tlog-witness, but tlog-mirror's add-entries incorporates tlog-witness's add-checkpoint behavior: https://github.com/C2SP/C2SP/blob/f1ed4e2e25942390bf979939c89adea895175a41/tlog-mirror.md#add-entries
So signature lines we get from mirrors will always have a nonzero timestamp. If we fetch mirror checkpoints instead, the mirror could technically choose to sign a checkpoint with a zero timestamp, but that seems unlikely. And is out of our control anyhow.
Since these fields need a way to carry a per-signature timestamp, we need to store something other than an ML-DSA-44 signature. That's because, in order to verify these signatures, we need to know the timestamp they were signed over. And that will certainly be different between the CA and the mirror signature. A couple options:
timestamped_signaturedata type from tlog-cosignature, which istimestamp || signatureI think we should do (2), since the majority of operations we will do with these values are done in the signed-note format:
timestamped_signature.This also suggests a format divide: the
checkpointstable, used for tlog operations, uses signed-note format. ThecheckpointSubtreestable, used for X.509 operations, uses ML-DSA signatures over CosignedMessages, since those go into MTCProofs directly (and implicitly have timestamp zero).