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

Support Cardano key derivation according to CIP3-Icarus #158

Merged

Conversation

PeterBenc
Copy link
Contributor

What is the current state of things and why does it need to change?

  • currently, this lib supports secp256k1 and ed25519
  • while developing a Snap for Cardano, we realized that keys derived by snap, using (getBip32Entropy) are different from keys that would standard Cardano wallet give, for the same mnemonic
  • this inconsistency could lead to confusion and interoperability issues
  • currently developed Cardano snap, relies on these changes, and is blocked by this. (note that changes need to be made also to metamask-snaps and metamask-extension repos, which are ready, awaiting feedback on this)

What is the solution your changes offer and how does it work?

  • by supporting derivation which is consistent with Cardano standard, we enable current Cardano users to use their existing mnemonics in Metamask and get the same wallet they used until now.
  • similarily, we would enable current Metamask users to use their mnemonic in standard Cardano wallets and retrieve same addresses as they would through Cardano-Metamask snap.

For this reasons

  • we add a new derivation curve, called ed25519Bip32, this curve implements a slight modification of how standard ed25519 is used in SLIP10.

  • we add a new deriver, called cip3Icarus which derives keys according to CIP3 (which is the standard for Cardano)

  • from the interface point of view, these changes allow us to call

    await deriveKeyFromPath({
       path: ["cip3Icarus:1852'", "cip3Icarus: 1815'"],
       curve: 'ed25519Bip32',
    })

    which returns keys consistent with Cardano derivation standard

A longer explanation, also present in the code

CIP-3 defines standards for deriving keys on Cardano.

Key attributes

Are there any issues or other links reviewers should consult to understand this pull request better? For instance:

All sources are referenced in the code, and explained quite extensively, namely

Reference implementations

@PeterBenc PeterBenc requested a review from a team as a code owner December 6, 2023 16:04
Copy link
Contributor Author

@PeterBenc PeterBenc left a comment

Choose a reason for hiding this comment

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

Please review by commits, thank you 🙏

export const isValidPrivateKey = (_privateKey: Uint8Array | string | bigint) =>
true;

export const deriveUnhardenedKeys = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that that the important difference of the bip32 version ed25519 is that it allows unhardened key derivation

@@ -24,7 +25,16 @@ export type Curve = {
publicAdd: (publicKey: Uint8Array, tweak: Uint8Array) => Uint8Array;
compressPublicKey: (publicKey: Uint8Array) => Uint8Array;
decompressPublicKey: (publicKey: Uint8Array) => Uint8Array;
};
} & (
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 motivation for this change, was to have place which decides whether the master node should be derived from seed (already implemented) or the new cip3Icarus way, from entropy, as defined in entropyToCip3IcarusMasterNode.

Tying masterNodeGenerationSpec to curve, seemed as the way which would require minimal changes to existing logic.

src/utils.ts Outdated Show resolved Hide resolved
* @returns The `Uint8Array` corresponding to the `bigint` value.
*/
export function numberToUint32(value: number) {
export function numberToUint32(value: number, littleEndian = false) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Needed later, to encode keyindex, for Cardano, the values are littleEndian

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please note that there are no deletions in this file, just additions. Only new cip3Icarus were generated.

@PeterBenc PeterBenc changed the title Support cardano key derivation cip3 icarus Support Cardano key derivation according to CIP3-Icarus Dec 6, 2023
src/derivers/cip3Icarus.ts Outdated Show resolved Hide resolved
@Mrtenz
Copy link
Member

Mrtenz commented Feb 9, 2024

At first glance this looks great. I will be doing a proper review next week, thanks for your patience!

Copy link
Member

@Mrtenz Mrtenz left a comment

Choose a reason for hiding this comment

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

I didn't get through everything yet, but here's some initial comments for you. I'm not familiar with CIP-3, so I will take some time to read more about it to properly review the algorithms added here.

Some nits related to the code style we use. Sorry for that!

src/curves/curve.ts Outdated Show resolved Hide resolved
src/curves/ed25519Bip32.test.ts Outdated Show resolved Hide resolved
src/curves/ed25519Bip32.test.ts Outdated Show resolved Hide resolved
src/curves/ed25519Bip32.test.ts Outdated Show resolved Hide resolved
src/curves/ed25519Bip32.ts Outdated Show resolved Hide resolved
src/derivers/cip3Icarus.test.ts Outdated Show resolved Hide resolved
src/derivers/cip3Icarus.test.ts Outdated Show resolved Hide resolved
src/derivers/cip3Icarus.test.ts Outdated Show resolved Hide resolved
src/derivers/cip3Icarus.test.ts Outdated Show resolved Hide resolved
src/derivers/cip3Icarus.ts Outdated Show resolved Hide resolved
Copy link
Contributor Author

@PeterBenc PeterBenc left a comment

Choose a reason for hiding this comment

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

@Mrtenz I was initially waiting for your full review, but then thought that you might be waiting for the cip3Icarus => cip3 refactor, so I did it. Your review came literally one second after I pushed :D. Sorry for that, please check these 3 commits too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did this in separate commit so I can squash it easier

curve,
);
switch (curve.masterNodeGenerationSpec) {
case 'slip10':
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You haven't asked for this, but, I noticed it now, the switch is IMO safer

@PeterBenc
Copy link
Contributor Author

@Mrtenz have you had time to look into cip3?
PS: all relevant links are in the PR description :)

@Mrtenz
Copy link
Member

Mrtenz commented Mar 4, 2024

@Mrtenz have you had time to look into cip3? PS: all relevant links are in the PR description :)

Not yet, sorry about that. Will make time to look into this more this week!

Copy link
Member

@Mrtenz Mrtenz left a comment

Choose a reason for hiding this comment

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

I reviewed the cryptography to the best of my ability and it looks good. Just a few more minor nits, and some code is missing coverage. Once that's fixed I will approve!

src/curves/ed25519Bip32.ts Outdated Show resolved Hide resolved
src/derivers/cip3.ts Show resolved Hide resolved
src/derivers/cip3.ts Outdated Show resolved Hide resolved
src/utils.ts Outdated Show resolved Hide resolved
@Mrtenz
Copy link
Member

Mrtenz commented Mar 6, 2024

Can you rebase your branch?

@PeterBenc PeterBenc force-pushed the support-cardano-key-derivation-cip3-icarus branch from 4da9f3a to e6b759a Compare March 6, 2024 20:07
@PeterBenc
Copy link
Contributor Author

@Mrtenz the last couple of issues should be resolved. Should I squash the commits or do you want to do it yourself?

@Mrtenz
Copy link
Member

Mrtenz commented Mar 6, 2024

src/index.ts is missing coverage(?), and you need to run yarn lint:fix. Looks good to me other than that!

@PeterBenc
Copy link
Contributor Author

Should be fixed

Should I squash the commits into some reasonable chunks, would that be relevant for audit too? do you want to do it yourself? Let me know :)

@Mrtenz
Copy link
Member

Mrtenz commented Mar 7, 2024

No need to. We want to do an audit for some other smaller changes since the last audit anyway, so I will just squash when merging this PR.

@Mrtenz Mrtenz merged commit bfa679e into MetaMask:main Mar 7, 2024
17 checks passed
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.

2 participants