@talismn/crypto 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -326,9 +326,38 @@ const deriveEd25519 = (seed, derivationPath) => {
326
326
  };
327
327
  };
328
328
  const getPublicKeyEd25519 = secretKey => {
329
+ // When importing ed25519 polkadot-js accounts via json, which we do inside of `packages/extension-core/src/domains/keyring/getSecretKeyFromPjsJson.ts`,
330
+ // the secretKey we produce is 64 bytes in length.
331
+ //
332
+ // When using the ed25519 curve to derive a publicKey for this 64 bytes privateKey, we should only take the first 32 bytes:
333
+ // - https://github.com/paulmillr/noble-curves/issues/53#issuecomment-1577362759
334
+ // - https://github.com/paulmillr/noble-curves/discussions/33#discussioncomment-5685971
335
+ // - https://github.com/paulmillr/noble-curves/pull/54
336
+ // - https://github.com/paulmillr/noble-curves/issues/88
337
+ //
338
+ // When you compare the ed25519 publicKey of a given account produced by this function to the publicKey produced by
339
+ // polkadot-js, you will find that they are the same as eachother.
340
+ if (secretKey.length === 64) {
341
+ const [privateComponent, publicComponent] = [secretKey.slice(0, 32), secretKey.slice(32)];
342
+ const publicKey = ed25519.ed25519.getPublicKey(privateComponent);
343
+
344
+ // NOTE: We only accept a 64 byte secretKey when the first 32 bytes successfully produce a public key which equals the second 32 bytes of the secretKey.
345
+ //
346
+ // In this scenario, we assume the creator of the secretKey has given us an array of bytes which equals `[...privateKey, ...publicKey]`.
347
+ //
348
+ // However, if the second 32 bytes **don't** match the publicKey produced by the first 32 bytes, we no longer know what's going on.
349
+ //
350
+ // In that case we pass the 64 bytes directly through to `@noble/curves/ed25519`, which we expect will throw the error: `private key of length 32 expected, got 64`.
351
+ // But if there's some 64 byte key format for ed25519 we don't know about, or one is added in the future, `@noble/curves/ed25519` can handle that for us instead of throwing.
352
+ if (!isUint8ArrayEq(publicComponent, publicKey)) return ed25519.ed25519.getPublicKey(secretKey);
353
+ return publicKey;
354
+ }
329
355
  return ed25519.ed25519.getPublicKey(secretKey);
330
356
  };
331
357
 
358
+ /** If a is identical to b, this function returns true, otherwise it returns false */
359
+ const isUint8ArrayEq = (a, b) => a.length !== b.length || a.some((v, i) => v !== b[i]) ? false : true;
360
+
332
361
  const deriveEthereum = (seed, derivationPath) => {
333
362
  const hdkey = bip32.HDKey.fromMasterSeed(seed);
334
363
  const childKey = hdkey.derive(derivationPath);
@@ -326,9 +326,38 @@ const deriveEd25519 = (seed, derivationPath) => {
326
326
  };
327
327
  };
328
328
  const getPublicKeyEd25519 = secretKey => {
329
+ // When importing ed25519 polkadot-js accounts via json, which we do inside of `packages/extension-core/src/domains/keyring/getSecretKeyFromPjsJson.ts`,
330
+ // the secretKey we produce is 64 bytes in length.
331
+ //
332
+ // When using the ed25519 curve to derive a publicKey for this 64 bytes privateKey, we should only take the first 32 bytes:
333
+ // - https://github.com/paulmillr/noble-curves/issues/53#issuecomment-1577362759
334
+ // - https://github.com/paulmillr/noble-curves/discussions/33#discussioncomment-5685971
335
+ // - https://github.com/paulmillr/noble-curves/pull/54
336
+ // - https://github.com/paulmillr/noble-curves/issues/88
337
+ //
338
+ // When you compare the ed25519 publicKey of a given account produced by this function to the publicKey produced by
339
+ // polkadot-js, you will find that they are the same as eachother.
340
+ if (secretKey.length === 64) {
341
+ const [privateComponent, publicComponent] = [secretKey.slice(0, 32), secretKey.slice(32)];
342
+ const publicKey = ed25519.ed25519.getPublicKey(privateComponent);
343
+
344
+ // NOTE: We only accept a 64 byte secretKey when the first 32 bytes successfully produce a public key which equals the second 32 bytes of the secretKey.
345
+ //
346
+ // In this scenario, we assume the creator of the secretKey has given us an array of bytes which equals `[...privateKey, ...publicKey]`.
347
+ //
348
+ // However, if the second 32 bytes **don't** match the publicKey produced by the first 32 bytes, we no longer know what's going on.
349
+ //
350
+ // In that case we pass the 64 bytes directly through to `@noble/curves/ed25519`, which we expect will throw the error: `private key of length 32 expected, got 64`.
351
+ // But if there's some 64 byte key format for ed25519 we don't know about, or one is added in the future, `@noble/curves/ed25519` can handle that for us instead of throwing.
352
+ if (!isUint8ArrayEq(publicComponent, publicKey)) return ed25519.ed25519.getPublicKey(secretKey);
353
+ return publicKey;
354
+ }
329
355
  return ed25519.ed25519.getPublicKey(secretKey);
330
356
  };
331
357
 
358
+ /** If a is identical to b, this function returns true, otherwise it returns false */
359
+ const isUint8ArrayEq = (a, b) => a.length !== b.length || a.some((v, i) => v !== b[i]) ? false : true;
360
+
332
361
  const deriveEthereum = (seed, derivationPath) => {
333
362
  const hdkey = bip32.HDKey.fromMasterSeed(seed);
334
363
  const childKey = hdkey.derive(derivationPath);
@@ -325,9 +325,38 @@ const deriveEd25519 = (seed, derivationPath) => {
325
325
  };
326
326
  };
327
327
  const getPublicKeyEd25519 = secretKey => {
328
+ // When importing ed25519 polkadot-js accounts via json, which we do inside of `packages/extension-core/src/domains/keyring/getSecretKeyFromPjsJson.ts`,
329
+ // the secretKey we produce is 64 bytes in length.
330
+ //
331
+ // When using the ed25519 curve to derive a publicKey for this 64 bytes privateKey, we should only take the first 32 bytes:
332
+ // - https://github.com/paulmillr/noble-curves/issues/53#issuecomment-1577362759
333
+ // - https://github.com/paulmillr/noble-curves/discussions/33#discussioncomment-5685971
334
+ // - https://github.com/paulmillr/noble-curves/pull/54
335
+ // - https://github.com/paulmillr/noble-curves/issues/88
336
+ //
337
+ // When you compare the ed25519 publicKey of a given account produced by this function to the publicKey produced by
338
+ // polkadot-js, you will find that they are the same as eachother.
339
+ if (secretKey.length === 64) {
340
+ const [privateComponent, publicComponent] = [secretKey.slice(0, 32), secretKey.slice(32)];
341
+ const publicKey = ed25519.getPublicKey(privateComponent);
342
+
343
+ // NOTE: We only accept a 64 byte secretKey when the first 32 bytes successfully produce a public key which equals the second 32 bytes of the secretKey.
344
+ //
345
+ // In this scenario, we assume the creator of the secretKey has given us an array of bytes which equals `[...privateKey, ...publicKey]`.
346
+ //
347
+ // However, if the second 32 bytes **don't** match the publicKey produced by the first 32 bytes, we no longer know what's going on.
348
+ //
349
+ // In that case we pass the 64 bytes directly through to `@noble/curves/ed25519`, which we expect will throw the error: `private key of length 32 expected, got 64`.
350
+ // But if there's some 64 byte key format for ed25519 we don't know about, or one is added in the future, `@noble/curves/ed25519` can handle that for us instead of throwing.
351
+ if (!isUint8ArrayEq(publicComponent, publicKey)) return ed25519.getPublicKey(secretKey);
352
+ return publicKey;
353
+ }
328
354
  return ed25519.getPublicKey(secretKey);
329
355
  };
330
356
 
357
+ /** If a is identical to b, this function returns true, otherwise it returns false */
358
+ const isUint8ArrayEq = (a, b) => a.length !== b.length || a.some((v, i) => v !== b[i]) ? false : true;
359
+
331
360
  const deriveEthereum = (seed, derivationPath) => {
332
361
  const hdkey = HDKey.fromMasterSeed(seed);
333
362
  const childKey = hdkey.derive(derivationPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/crypto",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "GPL-3.0-or-later",
@@ -36,8 +36,8 @@
36
36
  "jest": "^29.7.0",
37
37
  "ts-jest": "^29.2.5",
38
38
  "typescript": "^5.6.3",
39
- "@talismn/eslint-config": "0.0.3",
40
- "@talismn/tsconfig": "0.0.2"
39
+ "@talismn/tsconfig": "0.0.2",
40
+ "@talismn/eslint-config": "0.0.3"
41
41
  },
42
42
  "preconstruct": {
43
43
  "entrypoints": [