I've had some thoughts about the current signing situation, and I wanted to go ahead and write them down to solicit feedback.
Current Situation
libpkg today has two signing implementations ("providers"): pkgsign_ossl and pkgsign_ecc, the former supporting RSA keys and the latter supporting both EdDSA/ECDSA with libecc. Both implementations support signing directly with a provided key ("PUBKEY"), or farming the signing process out to an external command ("FINGERPRINTS").
The PUBKEY mechanism grants the implementation the freedom to sign whatever it sees fit, so the OSSL provider signs a SHA256 of the thing we're signing, while the ECC provider signs a BLAKE2 hash of it.
The FINGERPRINTS mechanism doesn't know what the external command will be signing with, so it provides a SHA256 that the external command will sign and the provider can't influence it at all.
Future
ECC Provider Work
The ECC provider is functional, but it already has a pretty bad oversight. I wrote it to accept any number of key types, but there's a design flaw that makes using !secp256k1 keys a little less valuable: libecc will hash the payload we feed it (again) and then sign that, and for ECDSA it's using SHA256 with all key types. Ideally secp384r1/secp521r1 would use SHA384 and SHA512 respectively, and similar with the brainpool* curves.
The ECC provider might still be young enough that we could just fix this without breaking anyone? If you generate an ecdsa key today (which you have to request specifically) you'll get a secp256k1 key and it won't really affect you- you would have to generate these other types with openssl or similar.
Otherwise, we fix it by giving the ecc provider an 'ecdsa2' alias that folks will migrate to that does the right thing.
Fingerprint work
It would be nice to get out from underneath SHA256 here, but it's hard to do so without breaking existing clients. The fingerprint mechanism today yields .pub and .sig files in the signed archive. If the ECC signer is used, we insert a $PKGSIGN:...$ prefix in the signature to describe the provider so that the client can fetch the right provider to handle it, rather than trying to guess based on what the signature looks like.
My proposal is that we do nothing on the signer-side today, but we teach the client-side to interpret the $PKGSIGN header with a little more flexibility. Specifically, I would propose we:
- Let it be semicolon delimited fields, and ignore (but complain) about parts of it that we don't understand -- PKGSIGN must be first so that we can feel confident that we're actually looking at a well-formed header and not a byte included in a signature.
- Add a HASH: field, whose value matches a _pkg_cksum_type->name. An example might then look like
$PKGSIGN:ecc;HASH:sha256_hex$ to describe how pkg(8) operates today with the ecc signer
If we make these changes today, then at some point we can decide how to make the repo creation side flexible enough to use something like blake2. I imagine the f.o cluster builds won't be able to move to something else for a long time, but at least they'd have an eventual path and private repositories could do what they want.
I've had some thoughts about the current signing situation, and I wanted to go ahead and write them down to solicit feedback.
Current Situation
libpkg today has two signing implementations ("providers"): pkgsign_ossl and pkgsign_ecc, the former supporting RSA keys and the latter supporting both EdDSA/ECDSA with libecc. Both implementations support signing directly with a provided key ("PUBKEY"), or farming the signing process out to an external command ("FINGERPRINTS").
The PUBKEY mechanism grants the implementation the freedom to sign whatever it sees fit, so the OSSL provider signs a SHA256 of the thing we're signing, while the ECC provider signs a BLAKE2 hash of it.
The FINGERPRINTS mechanism doesn't know what the external command will be signing with, so it provides a SHA256 that the external command will sign and the provider can't influence it at all.
Future
ECC Provider Work
The ECC provider is functional, but it already has a pretty bad oversight. I wrote it to accept any number of key types, but there's a design flaw that makes using !secp256k1 keys a little less valuable: libecc will hash the payload we feed it (again) and then sign that, and for ECDSA it's using SHA256 with all key types. Ideally secp384r1/secp521r1 would use SHA384 and SHA512 respectively, and similar with the brainpool* curves.
The ECC provider might still be young enough that we could just fix this without breaking anyone? If you generate an ecdsa key today (which you have to request specifically) you'll get a secp256k1 key and it won't really affect you- you would have to generate these other types with openssl or similar.
Otherwise, we fix it by giving the ecc provider an 'ecdsa2' alias that folks will migrate to that does the right thing.
Fingerprint work
It would be nice to get out from underneath SHA256 here, but it's hard to do so without breaking existing clients. The fingerprint mechanism today yields .pub and .sig files in the signed archive. If the ECC signer is used, we insert a
$PKGSIGN:...$prefix in the signature to describe the provider so that the client can fetch the right provider to handle it, rather than trying to guess based on what the signature looks like.My proposal is that we do nothing on the signer-side today, but we teach the client-side to interpret the $PKGSIGN header with a little more flexibility. Specifically, I would propose we:
$PKGSIGN:ecc;HASH:sha256_hex$to describe how pkg(8) operates today with the ecc signerIf we make these changes today, then at some point we can decide how to make the repo creation side flexible enough to use something like blake2. I imagine the f.o cluster builds won't be able to move to something else for a long time, but at least they'd have an eventual path and private repositories could do what they want.