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

Is this compatible with the elliptic package? #94

Closed
jackson-dean opened this issue Jan 27, 2023 · 4 comments
Closed

Is this compatible with the elliptic package? #94

jackson-dean opened this issue Jan 27, 2023 · 4 comments

Comments

@jackson-dean
Copy link

jackson-dean commented Jan 27, 2023

First off, thanks a lot for this lib. I was able to replace elliptic in one of our projects with this! However, we have some other projects that still use the elliptic package and need to be able to derive the same keys given the same seed in both systems. I made a little test to see if given the same seed this library and elliptic produce the same keys, but they don't seem to do so. I was just wondering if you know why the discrepancy exists and if there is anything I can do to make them compatible. Thank you in advance 🙏

Here is the little test script where I try generating keys with both libs from the same seed. https://github.com/jackson-dean/test-noble-secp256k1

Would appreciate any help understanding this issue or what I can do it about it.

@paulmillr
Copy link
Owner

Of course.

  1. hashToPrivateKey has no implementations in other libraries i'm aware of. It is exclusive to noble.
  2. caf797541983d115976714b8fb33720439e0790a6186106016d427c128b4e7e35e7f9dd8e2b0b8ccd08a50de574f9b6233e52fcec32a5bcd8e005e38f5dcd572 seems like invalid private key. secp private keys must be 256 bit, which is basically 32-byte uint8array, or 64-character hex string. Your test vector seems to have more chars. If elliptic can handle this private key, then elliptic is wrong and this is a bug.
  3. Pass random 64-char hex string to elliptic keyFromPrivate and to noble getPublicKey (as-is): you will see the same output.

1 similar comment
@paulmillr
Copy link
Owner

Of course.

  1. hashToPrivateKey has no implementations in other libraries i'm aware of. It is exclusive to noble.
  2. caf797541983d115976714b8fb33720439e0790a6186106016d427c128b4e7e35e7f9dd8e2b0b8ccd08a50de574f9b6233e52fcec32a5bcd8e005e38f5dcd572 seems like invalid private key. secp private keys must be 256 bit, which is basically 32-byte uint8array, or 64-character hex string. Your test vector seems to have more chars. If elliptic can handle this private key, then elliptic is wrong and this is a bug.
  3. Pass random 64-char hex string to elliptic keyFromPrivate and to noble getPublicKey (as-is): you will see the same output.

@paulmillr
Copy link
Owner

Yeah, elliptic basically divides the key by modulus. You could do utils.mod(0x caf797541983d115976714b8fb33720439e0790a6186106016d427c128b4e7e35e7f9dd8e2b0b8ccd08a50de574f9b6233e52fcec32a5bcd8e005e38f5dcd572n, CURVE.n) and you'll get proper private key.

@jackson-dean
Copy link
Author

jackson-dean commented Jan 27, 2023

Hey thanks for the quick response! Yea so I just got back around to playing with this again, and I was just misusing things. I am picking things up as I go, so bear with me if some of this is bone headed. In any case:

This works perfect.

const seedHex =
  "caf797541983d115976714b8fb33720439e0790a6186106016d427c128b4e7e3";

// elliptic key pair
const ec = new EC("secp256k1");
const ecKeys = ec.keyFromPrivate(seedHex);
const ecPublicKey = ecKeys.getPublic("hex");

const noblePublicKey = secp.getPublicKey(seedHex);

Also you're right about the too long hex string. This is how I actually ended up with that thing in my little testing script:

const mnemonic = bip39.generateMnemonic();
const seed = bip39.mnemonicToSeedSync(mnemonic); // produces 64 byte array (not 32)
const seedHex = secp.utils.bytesToHex(seed); // length 128

In such case where i've generated an invalid hex, you are also right, this does the trick. Though if I'm generating the seed hex properly in the first place its unnecessary:

secp.utils.mod(BigInt(`0x${seedHex}`), secp.CURVE.n)

Anyway, thanks again. Great lib. Life saver for crypto web/browser projects! I think this issue is sorted.

jackson-dean added a commit to deso-protocol/deso-workspace that referenced this issue Jan 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

No branches or pull requests

2 participants