Skip to content

spki: make AlgorithmIdentifier generic around Params #769

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

Merged
merged 1 commit into from
Dec 11, 2022

Conversation

tarcieri
Copy link
Member

NOTE: breaking change.

Previously AlgorithmIdentifier::parameters were always AnyRef. This commit changes them to a generic parameter Params.

An alias AlgorithmIdentifierRef provides a type identical to the original with AnyRef as its parameters, which is used in all of the other crates in this repo.

cc @baloo @lumag

@tarcieri tarcieri marked this pull request as draft November 25, 2022 22:11
@tarcieri tarcieri force-pushed the spki/generic-algorithm-identifier branch from efc5b1a to c98cbee Compare November 25, 2022 22:27
@@ -36,7 +39,7 @@ use der::pem::PemLabel;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct SubjectPublicKeyInfo<'a> {
/// X.509 [`AlgorithmIdentifier`] for the public key type
pub algorithm: AlgorithmIdentifier<'a>,
pub algorithm: AlgorithmIdentifierRef<'a>,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this would be a lot more useful if Params were also added to SubjectPublicKeyInfo, i.e. this were changed to AlgorithmIdentifier<Params>.

It should probably get tackled as part of this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise it should be changed on PrivateKeyInfo in the pkcs8 crate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be some type bound rather than generic <Params>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After trying to implement generic arguments to SPKI or to Certificate/TBSCertificate, I think that Params might need to be bound with something like Into<AnyRef>, or any other generic enough type, so that there would be no need to add type parameters to these structures. I might be wrong with the SPKI, but handling type parameters for Certificate looks like a complete mess.

Copy link
Member Author

@tarcieri tarcieri Nov 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow what you mean by "type bound" if not a generic parameter.

If you need additional bounds you can always specify them. But requiring one would be rather onerous I think, especially as the conversion for e.g. ObjectIdentifier only works for &ObjectIdentifier.

Certificate/TBSCertificate

...those should be using a concrete type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still playing here. I have the feeling that TBSCertitificate & company should not have generic parameters per se. Otherwise handling them easily becomes a mess. I'm still trying to fit SPKI / SPKIRef properly into my code. Maybe this will flow better once I update RSA crate to return specific SPKI rather than generic SPKIRef.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they should use a concrete type. The only things I think it makes sense parameterizing are AlgorithmIdentifier, SubjectPublicKeyInfo, and PrivateKeyInfo.

Copy link
Contributor

@lumag lumag Nov 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any easy way to perform the Into<AnyRef> or TryInto<AnyRef> conversion? The only way I have at this moment is to encode the AlgorithmIndeifier<Params> into DER format and then reparse it again into AlgorithmIndentifierRef.

Comment on lines +81 to 83
impl<'a> AlgorithmIdentifierRef<'a> {
/// Assert the `algorithm` OID is an expected value.
pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result<ObjectIdentifier> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the inherent methods unchanged for now, however it's now possible to use AlgorithmIdentifier<ObjectIdentifier> which eliminates the need for many of them, since the main thing they provide is type conversions to/from ObjectIdentifier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert_algorithm_oid should be implemented for the generic type, not for the AlgorithmIdentifierRef

@tarcieri tarcieri force-pushed the spki/generic-algorithm-identifier branch 2 times, most recently from b5c715d to 630514d Compare November 25, 2022 22:52
@tarcieri
Copy link
Member Author

This is a weird failure:

https://github.com/RustCrypto/formats/actions/runs/3551054810/jobs/5964957749

rstest is failing? But Cargo.lock didn't change

@@ -75,7 +75,7 @@ pub struct RevokedCert<'a> {
#[allow(missing_docs)]
pub struct TbsCertList<'a> {
pub version: Version,
pub signature: AlgorithmIdentifier<'a>,
pub signature: AlgorithmIdentifierRef<'a>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also allow AlgorithmIdentifier<...> (and in Certificate/CertificateList) too.
I can not come with the good enough argument at this moment.

@lumag
Copy link
Contributor

lumag commented Nov 26, 2022

@tarcieri please consider also merging https://pastebin.com/fNszVrjA

I tried generalizing SubjectPublicKeyInfo, but got stuck.

@tarcieri
Copy link
Member Author

@tarcieri please consider also merging https://pastebin.com/fNszVrjA

I think some of that looks good but would rather hold off on doing those sorts of updates in follow-up PRs. Maybe you can PR them separately after this is merged?

This PR isn't done yet and it's going to get more complex with changes to SubjectPublicKeyInfo and PrivateKeyInfo. And continuing to use AnyRef as Params should still be fine for now.

@baloo
Copy link
Member

baloo commented Nov 26, 2022

This is a weird failure:

https://github.com/RustCrypto/formats/actions/runs/3551054810/jobs/5964957749

rstest is failing? But Cargo.lock didn't change

#767 (comment)

This is a regression on nightly.

Temporary fix here:
RustCrypto/actions#20
demo:
https://github.com/RustCrypto/formats/actions/runs/3552592187/jobs/5967598693
#770

@lumag
Copy link
Contributor

lumag commented Nov 26, 2022

@tarcieri sure, I can update RsaPssParams afterwards. The last chunk (regarding assert_algorithm_oid) can probably be a part of this PR.
I'm looking forward to seeing how you'd update SPKI/PrivateKeyInfo.

@tarcieri
Copy link
Member Author

tarcieri commented Nov 26, 2022

@lumag b09ff11 makes SubjectPublicKeyInfo generic around Params, following much the same pattern as I used for AlgorithmIdentifier

Unfortunately this isn't enough to eliminate the lifetime and allow a fully owned form. That would require making the public key data generic around e.g. a Bits parameter.

@tarcieri tarcieri force-pushed the spki/generic-algorithm-identifier branch from ffb9092 to b09ff11 Compare November 26, 2022 19:09
@baloo baloo mentioned this pull request Nov 28, 2022
@baloo
Copy link
Member

baloo commented Nov 29, 2022

I've played a bit with the PR.
If I understand correctly the idea would be to get something like:

patch on `x509-cert/src/certificate.rs`
diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs
index ec607eb..28cc2d6 100644
--- a/x509-cert/src/certificate.rs
+++ b/x509-cert/src/certificate.rs
@@ -8,7 +8,7 @@ use core::cmp::Ordering;
 use const_oid::AssociatedOid;
 use der::asn1::BitString;
 use der::{Decode, Enumerated, Error, ErrorKind, Sequence, ValueOrd};
-use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfoRef};
+use spki::{AlgorithmIdentifier, SubjectPublicKeyInfoRef};

 #[cfg(feature = "pem")]
 use der::pem::PemLabel;
@@ -73,7 +73,7 @@ impl Default for Version {
 /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1
 #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
 #[allow(missing_docs)]
-pub struct TbsCertificate<'a> {
+pub struct TbsCertificate<'a, S, K> {
     /// The certificate version
     ///
     /// Note that this value defaults to Version 1 per the RFC. However,
@@ -84,11 +84,11 @@ pub struct TbsCertificate<'a> {
     pub version: Version,

     pub serial_number: SerialNumber,
-    pub signature: AlgorithmIdentifierRef<'a>,
+    pub signature: AlgorithmIdentifier<S>,
     pub issuer: Name,
     pub validity: Validity,
     pub subject: Name,
-    pub subject_public_key_info: SubjectPublicKeyInfoRef<'a>,
+    pub subject_public_key_info: SubjectPublicKeyInfo<'a, K>,

     #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
     pub issuer_unique_id: Option<BitString>,
@@ -100,7 +100,7 @@ pub struct TbsCertificate<'a> {
     pub extensions: Option<crate::ext::Extensions>,
 }

-impl<'a> TbsCertificate<'a> {
+impl<'a, S, K> TbsCertificate<'a, S, K> {
     /// Decodes a single extension
     ///
     /// Returns an error if multiple of these extensions is present. Returns
@@ -147,15 +147,15 @@ impl<'a> TbsCertificate<'a> {
 /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1
 #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
 #[allow(missing_docs)]
-pub struct Certificate<'a> {
-    pub tbs_certificate: TbsCertificate<'a>,
-    pub signature_algorithm: AlgorithmIdentifierRef<'a>,
+pub struct Certificate<'a, S, K> {
+    pub tbs_certificate: TbsCertificate<'a, S, K>,
+    pub signature_algorithm: AlgorithmIdentifier<S>,
     pub signature: BitString,
 }

 #[cfg(feature = "pem")]
 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
-impl PemLabel for Certificate<'_> {
+impl PemLabel for Certificate<'_, _, _> {
     const PEM_LABEL: &'static str = "CERTIFICATE";
 }

@@ -170,4 +170,4 @@ impl PemLabel for Certificate<'_> {
 /// ```
 ///
 /// [RFC 6066]: https://datatracker.ietf.org/doc/html/rfc6066#section-10.1
-pub type PkiPath<'a> = Vec<Certificate<'a>>;
+pub type PkiPath<'a, S, K> = Vec<Certificate<'a, S, K>>;

I'm not sure the Vec<Certificate<'a, S, K>> would make much sense as there is no obligation for a verification path to use the same signature or same key algorithm?

@tarcieri
Copy link
Member Author

@baloo I don't think it makes sense to parameterize Certificate around generic Params.

Instead they can use owned/allocating Any now, and runtime dispatch based on the provided AlgorithmIdentifier. That moves us one step closer to owned types.

@baloo
Copy link
Member

baloo commented Nov 29, 2022

Ha, right, I missed the intention of the Params completely.

@tarcieri
Copy link
Member Author

I think it allows for a number of cross-cutting concerns, including using a concrete type like ObjectIdentifier when it makes sense.

We're also trying to solve the problem of having AlgorithmIdentifier constants where the Params are e.g. a SEQUENCE.

Previously `AlgorithmIdentifier::parameters` were always `AnyRef`.
This commit changes them to a generic parameter `Params`.

An alias `AlgorithmIdentifierRef` provides a type identical to the
original with `AnyRef` as its `parameters`, which is used in all of the
other crates in this repo.
@tarcieri tarcieri force-pushed the spki/generic-algorithm-identifier branch from b09ff11 to d6741cb Compare December 11, 2022 15:03
@tarcieri tarcieri changed the title [WIP] spki: make AlgorithmIdentifier generic around Params spki: make AlgorithmIdentifier generic around Params Dec 11, 2022
@tarcieri tarcieri marked this pull request as ready for review December 11, 2022 16:08
@tarcieri tarcieri merged commit 855f787 into master Dec 11, 2022
@tarcieri tarcieri deleted the spki/generic-algorithm-identifier branch December 11, 2022 16:09
@tarcieri tarcieri mentioned this pull request Feb 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants