Skip to content
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

feat: add support for webrtc and certhash (#261) #262

Merged
merged 7 commits into from
Aug 30, 2022

Conversation

John-LittleBearLabs
Copy link
Contributor

@John-LittleBearLabs John-LittleBearLabs commented Aug 9, 2022

For use with the js implementation of the webrtc transport currently in development.

The most relevant point of info, from the draft spec:

The TLS certificate fingerprint in /certhash is a multibase encoded multihash.

src/convert.ts Outdated
@@ -148,6 +153,12 @@ function mh2bytes (hash: string) {
return uint8ArrayConcat([size, mh], size.length + mh.length)
}

function mb2bytes(mbstr: string) {
let mb = MB.decode(mbstr)
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to handle the case where decoding the multibase fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

decode would throw in some failure cases

https://multiformats.github.io/js-multibase/#decode
https://github.com/multiformats/js-multibase/blob/dde00682ed1a2539677c1e2b17dc6a3c112c8e3a/src/base.js#L40-L47

That said I don't think multibase is aware of what kind of data it's decoding, so it should not be able to detect things like the field being truncated. I don't think the existing analogous multihash functions do validation of this kind in all cases either, though.

https://github.com/multiformats/js-multiaddr/blob/master/src/convert.ts#L140-L142

function mb2bytes(mbstr: string) {
let mb = MB.decode(mbstr)
const size = Uint8Array.from(varint.encode(mb.length))
return uint8ArrayConcat([size, mb], size.length + mb.length)
Copy link
Contributor

Choose a reason for hiding this comment

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

is there any verification required that the decoded multibase contains a valid multihash?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure there's an easy way to verify that. The existing multihash function does one validation I did not replicate here,

https://github.com/multiformats/js-multiaddr/blob/master/src/convert.ts#L158-L160

That it reports a size that is correct. I could (maybe should) do that. But to go beyond that I think we'd have to be aware of all the supported encryption schemes, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@achingbrain - thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

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

I think this is fine, otherwise as you say it would have to know about all the available hash algorithms.

@John-LittleBearLabs

This comment was marked as outdated.

@John-LittleBearLabs John-LittleBearLabs marked this pull request as ready for review August 10, 2022 17:25
@achingbrain
Copy link
Member

Is there a known set of, or convention for the type of multibase encoding a given certhash will use? E.g. is it normally base58btc or base64 or something?

I ask because you've pulled in the deprecated multibase module - it's deprecated because it supports every multibase encoding under the sun when in most use cases one one or two are used so adds unnecessary bloat.

The approach taken elsewhere is to allow a codec argument to anything that turns a multibase string into bytes - it should default to whatever the conventional encoding is but allow the user to pass a different codec in when they know it's going to be something else.

@John-LittleBearLabs

This comment was marked as resolved.

@achingbrain
Copy link
Member

Not wrong at all, that sounds sensible.

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Unfortunately I am not much help on the JS multiformats stack.

Comment on lines 11 to 15
const encodings: {[prefix: string]: BaseDecoder} = {
'f': base16,
'u': base64url,
'z': base58btc,
};
Copy link
Member

Choose a reason for hiding this comment

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

I am not familiar with the JS multiformats stack. I am surprised that this mapping needs to be defined. I would expect this to be a general multihash and not a certhash specific mapping is.

Copy link
Member

Choose a reason for hiding this comment

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

You can compose a decoder from several other decoders, though the types are a little wonky.

I would expect this to be a general multihash

Do you mean not limited to the f, u or z prefixes? multiformats follows a pattern where you only include the codecs you need instead of the kitchen-sink approach.

You can, of course, compose your codec out of all available codecs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mxinden I believe my first pass supported all the encodings for a "general multihash", and I may have read too much into @achingbrain 's criticism of that (that the dependency I was using was too large because it supported too much). That's why I limited what I'm bringing in by default and provided the mechanism for the caller to dependency-inject a broader codec if wished.

Will look into using or to compose decoders. And to be clear, we're saying we want to support all of them, to take the draft spec as currently written literally, regardless of who is using this library? Except, perhaps, encodings with '/' in their alphabet?

Copy link
Member

Choose a reason for hiding this comment

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

I would expect this to be a general multihash

Do you mean not limited to the f, u or z prefixes? multiformats follows a pattern where you only include the codecs you need instead of the kitchen-sink approach.

I was not referring to supporting all multihash variants, but instead to the fact that the mapping between identifier (e.g. f) and its multihash variant (here base16) needs to be written by the user. That seems error prone to me. I might just be missing something.

And to be clear, we're saying we want to support all of them, to take the draft spec as currently written literally, regardless of who is using this library? Except, perhaps, encodings with '/' in their alphabet?

That is how we implement it in Rust multiformats/rust-multiaddr#59 and Golang multiformats/go-multiaddr#176. That said, both encode with Base64Url. Thus I think it is fine to support only a minimal set of bases for now.

We might require users to use sha256. In the same vein, we could as well require users to use Base64Url for now. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the mapping between identifier (e.g. f) and its multihash variant (here base16) needs to be written by the user.
It doesn't and if you see the new version of the code I dropped that.

Base64Url. Thus I think it is fine to support only a minimal set of bases for now.
I'll do whichever you like. Right now it's back to supporting "all" of them.

I put all in quotes because of the '/' issue. I didn't see an easy way to detect the alphabets from the dictionary provided by the multiformats library so I didn't filter them out. I would just guess that a base64-encoded certhash that happens to have a / in it, if placed in a Multiaddr, would cause problems at runtime.

Copy link
Member

Choose a reason for hiding this comment

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

For the record libp2p/specs@7009f94 specifies the requirement of supporting sha256 and base64url. I don't have an opinion on whether js-multiaddr should support any other algorithms / encodings beyond that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well-spotted. If the other side is only required to accept those two, then base58btc was a very poor choice of encoding for convertToString(). I'll fix that.

I think we can afford to leave the convertToBytes as supporting a bunch of 'em, since I'm not adding anything new to package.json to get it. But I'll certainly remove those others if advised to do so.

@mxinden mxinden linked an issue Aug 19, 2022 that may be closed by this pull request
@John-LittleBearLabs John-LittleBearLabs requested review from mxinden, achingbrain and ckousik and removed request for mxinden, achingbrain and ckousik August 19, 2022 16:10
Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

This looks good to me from a WebRTC perspective. @achingbrain could you give this another review from the JS perspective?

(Not going to approve, as I don't think my review should be given much weight. I am fine with this being merged.)

@achingbrain achingbrain changed the title fix: Add support for webrtc and certhash (#261) feat: add support for webrtc and certhash (#261) Aug 30, 2022
Copy link
Member

@achingbrain achingbrain left a comment

Choose a reason for hiding this comment

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

LGTM, just needs master merging into this branch and the linting errors fixing:

$ npm run lint -- --fix

let mb = 'f' + myCertFingerprint.value.replaceAll(':','');
let bytes = convert.convertToBytes('certhash',mb);
let outcome = convert.convertToString(466, bytes);
//Although I sent hex encoding in, base58btc always comes out
Copy link
Member

Choose a reason for hiding this comment

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

Is this comment valid? Looks like base64url has come out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. The comment is out-of-date.

@achingbrain achingbrain merged commit e5a8e27 into multiformats:master Aug 30, 2022
github-actions bot pushed a commit that referenced this pull request Aug 30, 2022
## [10.4.0](v10.3.5...v10.4.0) (2022-08-30)

### Features

* add support for webrtc and certhash ([#261](#261)) ([#262](#262)) ([e5a8e27](e5a8e27))
@github-actions
Copy link

🎉 This PR is included in version 10.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add /webrtc and /certhash
4 participants