-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
serialize_der() regenerates the certificate #62
Comments
Thanks for filing a bug about this. I haven't come around to file an issue about it, but wanted to find solutions for it. Resolving this issue likely requires a breaking change, due to the In the meantime, you can do it like rsa-irc.rs and build the der from the pem using the pem crate |
For the record, I recently got bitten by this while tinkering with certificate generation for tests. I was trying to figure out why there was a difference between serializing a certificate to PEM and serializing to DER. It turns out my client was ending up with one certificate and the server was ending up with another -- just because I was accidentally regenerating it, not because I was mishandling the DER formatted cert. |
To expand on this, my proposal would be to remove |
I'm not sure about adding a third layer like that. I think the OP and I both agree on the idea that What about an API where:
|
I actually like your approach better (outside of naming and some details).
a function like that is needed for importing of existing certificates. We could for example rename it to |
Good point. Having |
I started working on the proposed API last night and I like the direction but wasn't able to implement the idea as described end-to-end.
One roadblock here: this isn't tenable with the IME it's more common to separate key generation and certificate generation. I think the Perhaps |
This sounds good to me (does |
The equivalent API today is I think that API is a little bit confusing because at face value you'd expect they would be serializing the CSR itself, not a certificate issued from the CSR. You serialize a CSR from a Certificate with |
Ahh, so the difference is in |
Here's where I'm at with the refactor so far in case there's interest for early review: https://github.com/cpu/rcgen/tree/cpu-api-refactor-wip Some warnings up front;
The last remaining change I wanted to do was try and harmonize the "from scratch" I'll try to push more on this branch soon, but it's something I've mostly been working on in evenings. I have more pressing rustls work to focus on during the day and updating all of the unit tests for each API change is somewhat time consuming. |
This ends up being fairly tricky if we want to support all of the existing use cases because |
Some ideas to impl |
I'm not going to have time to invest in continuing the API refactor beyond the certificate issuance API in the near future so I've cleaned up my WIP branch for review: #205 The certificate issuance API is the most important w.r.t to the user confusion we see and so I think it makes sense to fix that without blocking on improvements to If folks disagree I'm happy to cede my branch to someone that has more time to push the remaining parts forward. |
) Previously a `Certificate` was a container for `CertificateParams` and a `KeyPair`, most commonly created from a `CertificateParams` instance. Serializing the `Certificate` (either as self signed with `serialize_pem` or `serialize_der`, or signed by an issuer with `serialize_pem_with_signer` or `serialize_der_with_signer`) would issue a certificate and produce the serialized form in one operation. The net result is that if a user wanted both DER and PEM serializations they would likely call `serialize_der(_with_signer)` and then `serialize_pem(_with_signer)` and mistakenly end up with the encoding of two distinct certificates, not the PEM and DER encoding of the same cert. Since the `KeyPair` contains a private key this API design also meant that the `Certificate` type had to be handled with care, and `Zeroized`. This branch reworks the issuance API and `Certificate` type to better match user expectation: `Certificate` is only public material and represents an issued certificate that can be serialized in a stable manner in DER or PEM encoding. I recommend reviewing this commit-by-commit, but here is a summary of the most notable API changes: * `Certificate::from_params` and `Certificate::serialize_der` and `Certificate::serialize_pem` for issuing a self-signed certificate are replaced with `Certificate::generate_self_signed()` and calling `der` or `pem` on the result. * `Certificate::from_params` and `Certificate::serialize_der_with_signer` and `Certificate::serialize_pem_with_signer` for issuing a certificate signed by another certificate are replaced with `Certificate::generate()` and calling `der` or `pem` on the result. * `CertificateSigningRequest::serialize_der_with_signer` and `CertificateSigningRequest::serialize_pem_with_signer` for issuing a certificate from a CSR are replaced with `Certificate::from_request` and calling `der` or `pem` on the result. The `CertificateSigningRequest` type is renamed to `CertificateSigningRequestParams` to better emphasize its role and match the other `*Params` types that already exist. * Since we now calculate the DER encoding of the certificate at `Certificate` construction time, the `pem` and `der` fns are now infallible. * Since `Certificate` no longer holds `KeyPair`, the `generate` fns now expect a `&KeyPair` argument for the signer when issuing a certificate signed by another certificate. * The generation fns now return a `CertifiedKey` that contains both a `Certificate` and a `KeyPair`. For params that specify a compatible `KeyPair` it is passed through in the `CertifiedKey` as-is. For params without a `KeyPair` a newly generated `KeyPair` is used. In the future we should look at harmonizing the creation of `CertificateSigningRequest` and `CertificateRevocationList` to better match this updated API. Unfortunately I don't have time to handle that at the moment. Since this API surface is relatively niche compared to the `Certificate` issuance flow it felt valuable to resolve #62 without blocking on this future work. Resolves #62
I am using rcgen to generate a certificate, then I'm sharing the fingerprint of the certificate with a peer, and then I'm using a library to communicate with that peer. The library requires me to provide the certificate & private key in PEM format.
I've been debugging for a while why the fingerprint I generate, like this:
... does not match the fingerprint the peer expects to receive, nor the fingerprint OpenSSL reports when I supply it with the PEM-encoded certificate obtained with
serialize_pem()
.After reading the discussion in #28, and looking at the code, I think I understand what's going on —
serialize_der()
andserialize_pem()
are not actually just serializing; they are in fact generating the certificate each time they are called, so the random components are different between the DER serialization and the PEM serialization.Ideally the certificate would be generated when the
Certificate
struct is created, so that it can be repeatedly serialized — perhaps into different formats — without regenerating it each time.If that's not possible, the functions should either be renamed or at least the mis-naming documented clearly to save the time of anyone else who encounters this.
Right now,
from_params()
is documented as "Generates a new certificate" andserialize_der()
is documented as "Serializes the certificate to the binary DER format", when in realityfrom_params()
just stores the params (and does keygen if needed), andserialize_der()
etc actually do the certificate generation.The text was updated successfully, but these errors were encountered: