Coder Social home page Coder Social logo

Implement `FromStr` for `Cwt` about dgc HOT 11 OPEN

rust-italia avatar rust-italia commented on May 26, 2024
Implement `FromStr` for `Cwt`

from dgc.

Comments (11)

lmammino avatar lmammino commented on May 26, 2024 1

This one will make @allevo proud! 😇

from dgc.

lmammino avatar lmammino commented on May 26, 2024 1

So literally something like this:

impl FromStr for Cwt {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // remove prefix
        let data = remove_prefix(data)?;

        // base45 decode
        let decoded = decode_base45(data)?;

        // decompress the data
        let decompressed = decompress(decoded)?;

        // parse cose payload
        let cwt = parse_cwt_payload(decompressed)?;

        Ok(cwt)
    }
}

from dgc.

allevo avatar allevo commented on May 26, 2024

Any idea how to implement it? just convert it to &[u8] and convert into Cwt ? or the string has a completely different implementation?

from dgc.

nappa85 avatar nappa85 commented on May 26, 2024

If the parse is made by ciborium, just use a ciborium::de::from_reader into it, from_reader takes anything that impl trait Read, and Read is implemented for &[u8], a String becomes &[u8] with the method as_bytes

from dgc.

lmammino avatar lmammino commented on May 26, 2024

My idea was to just be an alternative to calling this function directly: https://github.com/rust-italia/dgc/blob/main/src/parse.rs#L173

from dgc.

lmammino avatar lmammino commented on May 26, 2024

I only have one doubt in terms of ergonomics:

  • decode returns the payload of the cwt (DgcContainer)
  • from_str returns the cwt object (Cwt)

I am not really sure if it will be more ergonomic and consistent to always return a Cwt...

One of the advantages of having a CWT is that you have access to more data (headers, signature, etc). But at the same time you don't care about this data unless you want to verify the signature (which is the reason why decode returns directly the paylod, it is a use case that assumes you don't care about the signature, otherwise you'd use validate()).

Thoughts?

from dgc.

allevo avatar allevo commented on May 26, 2024

I tried to reverse the logic: implement the parse into Cwt and DgcContainer validate invokes it. So in this way, the decode* public APIs are implemented in this way:

pub fn decode_cwt(data: &str) -> Result<Cwt, CwtParseError> {
    data.parse()
}

pub fn decode(data: &str) -> Result<DgcCertContainer, CwtParseError> {
    let cwt = decode_cwt(data)?;
    Ok(cwt.payload)
}

As you can see, i changed the errortype reversing the inclusion (CwtParseError has a variant called ParseError). Is it make sense? Which differences are between the 2 errors?

from dgc.

lmammino avatar lmammino commented on May 26, 2024

@allevo, i like the idea of decode_cwt and decode. I think it will save us from a bit of code duplication.

With that being said, I am starting to think that maybe we shouldn't leak the CWT at all. At the end of the day, it is a little bit of an implementation detail. What really matter is not the encoding format (CWT) but the DgcCertContainer which contains all the "user facing" data.

CWT makes sense only in the context of validating the signature but that's something we are covering with validate()...

What about implementing FromStr only for DgcCertContainer (and not exposing decode_cwt publicly?

I know this is a bit philosophical, but it's probably better to keep the api surface small and simple...

Regarding the 2 errors. I think i was implementing CWT as a standalone lib initially, that's maybe why i came up with 2 different error sets (one for CWT decoding and one for the whole parsing). Let's definitely revisit this decision if it does not make too much sense to you...

from dgc.

Rimpampa avatar Rimpampa commented on May 26, 2024

Removing Cwt from the public interface would make the problem of having to return the tuple in the result - because one might want to read the data even if it's not valid - rather difficult to solve.

To hide the implementation details there are other options, like we could make Cwt have all its fields private and make it impl Deref<Target=DgcCertContainer>. But even then, I don't see why someone shouldn't be able to access the key id, the algorithm, and the signature.

Regarding the FromStr proposal I don't quite like it because rustdoc hides doc comments on trait method implementations. So one can't know for sure what data the parse method parses, and implementing it for DgcCertContainer would be even more confusing. It could be written in the documentation but from the method itself it's difficult to do understand it.

To give an example, in the docs will be written "DgcCertContainer::parse Parses a string s to return a value of this type." and someone may understand that it parases the JSON object of the greenpass, someone else might think that it parses the CBOR of the HCERT, another one may think that it parses the raw COSE data, etc.

What I agree on is merging the ParseError types in one.


Some things I want to add that I also referenced in the other issue:

I think that those functions (decode_cwt, and validate) should be methods of the Cwt struct and that the Cwt struct should be renamed to a more specific name as we are not parsing a generic CWT but one defined by the European Commission that contains an HCERT and that is signed.

validate might even be a method of the TrustList but in my mind, one should be able to write

Cwt::decode(data)?.verify(trust_list) == SignatureValidity::Valid

from dgc.

lmammino avatar lmammino commented on May 26, 2024

You raise some very good points, @Rimpampa!

I am sold on the fact that it might make sense to expose the CWT (even though right now some important fields are private, maybe we should revisit that).

On the FromStr in am not highly opinionated, so I am more than ok not adding this feature and closing this issue if we don't see a strong benefit to it! It's definitely not a priority (it does not add any new feature and it does not solve any bug).

Regarding API ergonomics I think the validation is the one that seems to be raising more skepticism, so there are probably many opportunities to revisit that.

I like your suggestions to make validate a method of Cwt (which gives us one more reason to keep Cwt publicly accessible), but again, I would like to consider validation in a more comprehensive way as being discussed in #21.

If we can figure out a decent API that will allow us in the future to do "all types" of validation easily that would be awesome.

Should we close this issue then and continue the API conversation in #21?

from dgc.

lmammino avatar lmammino commented on May 26, 2024

I forgot to mention that i did some renaming in #29 and also added a diagram that should help with understanding how the data is laid out across the various containers/structs.

from dgc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.