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

Add concept of feed types for new signature / verification algorithms #61

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

christianbundy
Copy link
Contributor

Breaking change.

This replaces the concept of "tag" and "curve" with "feed type", which enables the use of experimental feed types other than Ed25519.

Decision: What sort of compatibility should this module provide with loading older code that uses { curve }? For example, it seems like when we read ~/.ssb/secret we should maybe do some auto-detection to understand the previous property.

Super open to suggestions. 🚀

@christianbundy christianbundy self-assigned this Aug 1, 2019
@christianbundy christianbundy changed the title Use feed types Add concept of feed types for new signature / verification algorithms Aug 1, 2019
@staltz
Copy link
Member

staltz commented Aug 2, 2019

Is the rename curve => feedType the only breaking change? Could we first just release this as a non-breaking change, preserving the name curve, but just adding the new API ssbKeys.use()? That would enable us to use these new feed types without causing a breaking change. Then, later we could deprecate curve and demand feedType, and only in another version actually drop curve as a breaking change. (This is to say: let's not do breaking changes that quickly, instead, let's do it gradually and only if the change proves itself worthy when used in other modules)

@christianbundy
Copy link
Contributor Author

Yeah, and getTag() renamed to getFeedType(). I'm currently working on hacking through a bunch of modules and I think it would be great to use the feedType semantic rather than writing new code with soon-to-be-deprecated references.

Would you be open to having { feedType, curve } as sibling properties to remain backward-compatibility, maybe with some deprecation notice? This would keep everything backward-compatible without forcing new code to use curve for new feed types. My previous prototype used the curve property and Dominic suggested that I remove it:

I think it should just be @<integer>.<feedType> not .<curve>.<feedType>.

You're absolutely right though, it would be nice to avoid breaking things.

@christianbundy
Copy link
Contributor Author

😓

Alright, I think this is ready for another pair of eyes on it. It should be 100% compatible with the previous version, adding a feedType property as a sibling to curve. Would love to hear any and all thoughts.

@christianbundy
Copy link
Contributor Author

(Alternative branch with more consistent style, if that's easier to review: standardify.)

@@ -40,6 +40,7 @@ in the below methods, `keys` is an object of the following form:

``` js
{
"feedType": "ed25519"
Copy link
Member

Choose a reason for hiding this comment

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

I've been thinking about this recently with binary encoding of ids.

What I don't like about this is that ed25519 is a cryptographic curve thing... but that doesn't tell us anything about the feed type... like are the messages in this feed encoded as JSON, or are they some binary format? what's the spec for verifying this feedType?

I calling this feedType "classic", which happens to be ed25519 curve connection + signing, sha256 hashing, JSON encoding. "gabby" is another feedType which uses ed25519 but has some other stuff going on I gather

Copy link
Member

Choose a reason for hiding this comment

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

yup, exactly. Same is true for the hash function.

In the protocol meetup last may we therefore renamed the SHA to „scuttlebutt happend anyway“.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was also going to comment about the feedType and I might be a little late, but I think this is specifically referring to the type of encryption used in the message.

So, isn't something like encryption a possible better name for this property?

@@ -22,57 +19,85 @@ var hmac = sodium.crypto_auth

exports.hash = u.hash

exports.getTag = u.getTag
exports.getFeedType = u.getFeedType
exports.getTag = u.getFeedType // deprecated
Copy link
Member

Choose a reason for hiding this comment

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

maybe add that annoying console.log warning ?

const warnings = [
  'please no',
  'naughty developer',
  'I ask you to stop',
  'I will stop working',
  'I warn you'
]
var patience = warnings.length

exports.getTag = function () {
  if (patience === 0) throw new Error('ssb-keys quits')
  console.log(warnings[--patience])
  
  return u.getFeedType()
}

var curve = keys.curve
function getFeedType(keys) {
let { feedType } = keys
feedType = feedType || keys.curve
Copy link
Member

@mixmix mixmix Feb 7, 2020

Choose a reason for hiding this comment

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

<style> If you're using es6 tools do this instead:

const {
  feedType = keys.curve
} = keys

actually this is a mess (it works well for destructuring multiple opts with defaults)
This is clearer surely

const feedType = keys.feedType || keys.curve

}

//this should return a key pair:
// {curve: curve, public: Buffer, private: Buffer}
// { feedType: string, curve: string, public: Buffer, private: Buffer}
Copy link
Member

Choose a reason for hiding this comment

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

If this is a known requirement, then why don't you check this is what the generate does when you register a new type with the use() method?

exports.load = storage.load
exports.loadSync = storage.loadSync
exports.create = storage.create
exports.createSync = storage.createSync
Copy link
Member

Choose a reason for hiding this comment

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

❤️

u.toBuffer(keys.public || keys),
u.toBuffer(sig),
isBuffer(msg) ? msg : new Buffer(msg)
isBuffer(msg) ? msg : Buffer.from(msg)
Copy link
Member

Choose a reason for hiding this comment

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

<non-expert> I think it might be a good idea to explicitly declare the encoding with Buffer.from

i.e.

Buffer.from(msg, 'base64')
Buffer.from(msg, 'utf8') // I think this is the default

@@ -51,7 +51,7 @@ module.exports = function (generate) {

function reconstructKeys(keyfile) {
var privateKey = keyfile
.replace(/\s*\#[^\n]*/g, '')
.replace(/\s*#[^\n]*/g, '')
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 honestly not fuck with the regex (unless you wrote tight tests).
This is outside the scope of this PR and could just be tidying which has side-effects

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, just tidying -- unused backslashes are a footgun IMO but I could make this change in another PR. Good call. I think we had a similar discussion about removing unused backslashes a little while ago too: ssbc/ssb-schema-definitions#3 (review)

Copy link
Member

Choose a reason for hiding this comment

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

true I didn't see the followup till just now.
Yeah think a different PR would be good. It's probably fine, but this is just in the class of things it's quite easy to make mistakes on.

@@ -63,7 +63,7 @@ module.exports = function (generate) {
}

exports.load = function(filename, cb) {
filename = toFile(filename, 'secret')
filename = toFile(filename)
Copy link
Member

Choose a reason for hiding this comment

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

🔥 Haven't reviewed what this change does / if is safe

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed because toFile() only accepts one argument:

function toFile (filename) {

@mixmix
Copy link
Member

mixmix commented Feb 7, 2020

I've reviewed the logic of this @christianbundy and I think it's good.

My main recommendation is that if possible we don't use ed25519 as a "feedType".

@arj03
Copy link
Member

arj03 commented May 26, 2020

This is a juicy one @christianbundy. I'll try and give it a look, can you rebase so there are no conflicts?

@arj03
Copy link
Member

arj03 commented May 26, 2020

This is a quite readable change. Nice work!

One little thing, why is the ed25519.test feedType needed?

@christianbundy
Copy link
Contributor Author

I'll try and give it a look, can you rebase so there are no conflicts?

Sure!

One little thing, why is the ed25519.test feedType needed?

I think I was using that during testing to figure out which parts of the stack had hardcoded ed25519. Basically I was looking for a synonym with the same behavior so that we could trace down any breakage.

@mixmix
Copy link
Member

mixmix commented Aug 17, 2020 via email

@arj03
Copy link
Member

arj03 commented Aug 17, 2020

I'm leaning towards SHA. It will be easier to see where stuff breaks then as well.

@davegomez
Copy link
Contributor

Don't you think SHA might be confusing if you are thinking in terms of cryptography?

Since this won't be a legacy type but maybe the first kind of type, wouldn't it be good to choose a name that works in conjunction with other names?

What I try to say is: a name like "classic" leaves very few options for the other names, like "new" or "modern". We should look for a name that describes not only what it holds but also how it is structured, characteristics that allow us to differentiate it from the rest.

Sadly I can't come up with a name right now, and my knowledge of the protocol is still minimal to propose something.

I also want to say that I always thought "curve" refers to the algorithm used to encrypt the message, but if this is not the case, I think even "ed25519" is very misleading.

@christianbundy
Copy link
Contributor Author

The test feed isn't a critical aspect of this branch, I think the best move is to remove it from this PR. 💯

@christianbundy christianbundy changed the base branch from master to main August 25, 2020 20:26
@staltz staltz marked this pull request as draft January 15, 2021 13:49
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.

6 participants