@arkecosystem/typescript-crypto 0.0.12 → 0.0.14

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.
package/dist/index.js CHANGED
@@ -5657,7 +5657,7 @@ function weierstrass(curveDef) {
5657
5657
  return drbg(seed, k2sig);
5658
5658
  }
5659
5659
  Point3.BASE._setWindowSize(8);
5660
- function verify2(signature, msgHash, publicKey, opts = defaultVerOpts) {
5660
+ function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
5661
5661
  const sg = signature;
5662
5662
  msgHash = ensureBytes("msgHash", msgHash);
5663
5663
  publicKey = ensureBytes("publicKey", publicKey);
@@ -5707,7 +5707,7 @@ function weierstrass(curveDef) {
5707
5707
  getPublicKey,
5708
5708
  getSharedSecret,
5709
5709
  sign,
5710
- verify: verify2,
5710
+ verify,
5711
5711
  ProjectivePoint: Point3,
5712
5712
  Signature: Signature3,
5713
5713
  utils
@@ -23260,7 +23260,6 @@ var cr = () => (
23260
23260
  );
23261
23261
  var _hmacSync;
23262
23262
  var optS = { lowS: true };
23263
- var optV = { lowS: true };
23264
23263
  var prepSig = (msgh, priv, opts = optS) => {
23265
23264
  if (["der", "recovered", "canonical"].some((k) => k in opts))
23266
23265
  err("option not supported");
@@ -23368,42 +23367,6 @@ var signAsync = async (msgh, priv, opts = optS) => {
23368
23367
  const { seed, k2sig } = prepSig(msgh, priv, opts);
23369
23368
  return hmacDrbg(true)(seed, k2sig);
23370
23369
  };
23371
- var verify = (sig, msgh, pub, opts = optV) => {
23372
- let { lowS } = opts;
23373
- if (lowS == null)
23374
- lowS = true;
23375
- if ("strict" in opts)
23376
- err("option not supported");
23377
- let sig_, h, P2;
23378
- const rs = sig && typeof sig === "object" && "r" in sig;
23379
- if (!rs && toU8(sig).length !== 2 * fLen)
23380
- err("signature must be 64 bytes");
23381
- try {
23382
- sig_ = rs ? new Signature2(sig.r, sig.s).assertValidity() : Signature2.fromCompact(sig);
23383
- h = bits2int_modN(toU8(msgh));
23384
- P2 = pub instanceof Point2 ? pub.ok() : Point2.fromHex(pub);
23385
- } catch (e) {
23386
- return false;
23387
- }
23388
- if (!sig_)
23389
- return false;
23390
- const { r, s } = sig_;
23391
- if (lowS && high(s))
23392
- return false;
23393
- let R;
23394
- try {
23395
- const is = inv(s, N3);
23396
- const u1 = M(h * is, N3);
23397
- const u2 = M(r * is, N3);
23398
- R = G.mulAddQUns(P2, u1, u2).aff();
23399
- } catch (error) {
23400
- return false;
23401
- }
23402
- if (!R)
23403
- return false;
23404
- const v = M(R.x, N3);
23405
- return v === r;
23406
- };
23407
23370
  var hashToPrivateKey = (hash2) => {
23408
23371
  hash2 = toU8(hash2);
23409
23372
  if (hash2.length < fLen + 8 || hash2.length > 1024)
@@ -27847,6 +27810,17 @@ var AbiDecoder = class extends AbiBase {
27847
27810
  args: this.interface.decodeFunctionData(functionFragment, data)
27848
27811
  };
27849
27812
  }
27813
+ decodeError(data) {
27814
+ if (!data.startsWith("0x")) {
27815
+ data = "0x" + data;
27816
+ }
27817
+ const errorSelector = data.slice(0, 10);
27818
+ const errorFragment = this.interface.getError(errorSelector);
27819
+ if (!errorFragment) {
27820
+ throw new Error(`Error selector not found in ABI: ${errorSelector}`);
27821
+ }
27822
+ return errorFragment.name;
27823
+ }
27850
27824
  };
27851
27825
 
27852
27826
  // src/utils/AbiEncoder.ts
@@ -27992,18 +27966,18 @@ var Message = class _Message {
27992
27966
  static async sign(message, passphrase) {
27993
27967
  const privateKey = PrivateKey.fromPassphrase(passphrase);
27994
27968
  const publicKey = PublicKey.fromPassphrase(passphrase).publicKey;
27995
- const signature = await privateKey.sign(Buffer.from(message).toString("hex"));
27969
+ const signature = new SigningKey(`0x${privateKey.privateKey}`).sign(hashMessage(message));
27996
27970
  return _Message.new({
27997
27971
  publicKey,
27998
- signature: signature.r + signature.s + signature.v.toString(16).padStart(2, "0"),
27972
+ signature: signature.serialized,
27999
27973
  message
28000
27974
  });
28001
27975
  }
28002
27976
  verify() {
28003
- const message = Buffer.from(keccak256(Buffer.from(this.message)).slice(2), "hex");
28004
- const signature = Buffer.from(this.signature.slice(0, 128), "hex");
28005
- const publicKey = Buffer.from(this.publicKey, "hex");
28006
- return verify(signature, message, publicKey);
27977
+ const message = new Uint8Array(new TextEncoder().encode(this.message));
27978
+ const address = Address.fromPublicKey(this.publicKey);
27979
+ const signerAddress = verifyMessage(message, this.signature);
27980
+ return signerAddress === address;
28007
27981
  }
28008
27982
  toString() {
28009
27983
  return JSON.stringify(this.toJson());
@@ -2,5 +2,6 @@ import { AbiResult } from "@/types";
2
2
  import { AbiBase } from "./AbiBase";
3
3
  export declare class AbiDecoder extends AbiBase {
4
4
  decodeFunctionData(data: string): AbiResult;
5
+ decodeError(data: string): string;
5
6
  }
6
7
  //# sourceMappingURL=AbiDecoder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AbiDecoder.d.ts","sourceRoot":"","sources":["../../src/utils/AbiDecoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,qBAAa,UAAW,SAAQ,OAAO;IACtC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;CAiB3C"}
1
+ {"version":3,"file":"AbiDecoder.d.ts","sourceRoot":"","sources":["../../src/utils/AbiDecoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,qBAAa,UAAW,SAAQ,OAAO;IACtC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAkB3C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAcjC"}
@@ -14,4 +14,15 @@ export class AbiDecoder extends AbiBase {
14
14
  args: this.interface.decodeFunctionData(functionFragment, data),
15
15
  };
16
16
  }
17
+ decodeError(data) {
18
+ if (!data.startsWith("0x")) {
19
+ data = "0x" + data;
20
+ }
21
+ const errorSelector = data.slice(0, 10);
22
+ const errorFragment = this.interface.getError(errorSelector);
23
+ if (!errorFragment) {
24
+ throw new Error(`Error selector not found in ABI: ${errorSelector}`);
25
+ }
26
+ return errorFragment.name;
27
+ }
17
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/utils/Message.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxC,qBAAa,OAAO;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,aAAa;IAMlC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO;WAI9B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAaxE,MAAM,IAAI,OAAO;IAQjB,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM,EAAE;IAIpB,MAAM,IAAI,aAAa;CAOvB"}
1
+ {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/utils/Message.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAKxC,qBAAa,OAAO;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,aAAa;IAMlC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO;WAI9B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAexE,MAAM,IAAI,OAAO;IASjB,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM,EAAE;IAIpB,MAAM,IAAI,aAAa;CAOvB"}
@@ -7,10 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { PrivateKey } from "@/identities/PrivateKey";
11
10
  import { PublicKey } from "@/identities/PublicKey";
12
- import { keccak256 } from "ethers";
13
- import { verify } from "@noble/secp256k1";
11
+ import { hashMessage, verifyMessage } from "ethers";
12
+ import { Address, PrivateKey } from "@/identities";
13
+ import { SigningKey } from "ethers";
14
14
  export class Message {
15
15
  constructor(message) {
16
16
  this.publicKey = message.publicKey;
@@ -24,19 +24,22 @@ export class Message {
24
24
  return __awaiter(this, void 0, void 0, function* () {
25
25
  const privateKey = PrivateKey.fromPassphrase(passphrase);
26
26
  const publicKey = PublicKey.fromPassphrase(passphrase).publicKey;
27
- const signature = yield privateKey.sign(Buffer.from(message).toString("hex"));
27
+ // Sign messages using eip-191 signed data specification, to be aligned with ledger signing workflow.
28
+ // @see https://developers.ledger.com/docs/ledger-live/discover/integration/wallet-api/server/handlers/message
29
+ const signature = new SigningKey(`0x${privateKey.privateKey}`).sign(hashMessage(message));
28
30
  return Message.new({
29
31
  publicKey,
30
- signature: signature.r + signature.s + signature.v.toString(16).padStart(2, "0"),
32
+ signature: signature.serialized,
31
33
  message,
32
34
  });
33
35
  });
34
36
  }
35
37
  verify() {
36
- const message = Buffer.from(keccak256(Buffer.from(this.message)).slice(2), "hex");
37
- const signature = Buffer.from(this.signature.slice(0, 128), "hex");
38
- const publicKey = Buffer.from(this.publicKey, "hex");
39
- return verify(signature, message, publicKey);
38
+ const message = new Uint8Array(new TextEncoder().encode(this.message));
39
+ const address = Address.fromPublicKey(this.publicKey);
40
+ // Messages need to be signed using eip-191 signed data specification
41
+ const signerAddress = verifyMessage(message, this.signature);
42
+ return signerAddress === address;
40
43
  }
41
44
  toString() {
42
45
  return JSON.stringify(this.toJson());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkecosystem/typescript-crypto",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "engines": {
5
5
  "node": ">=20.12.2"
6
6
  },
@@ -19,4 +19,19 @@ export class AbiDecoder extends AbiBase {
19
19
  args: this.interface.decodeFunctionData(functionFragment, data),
20
20
  };
21
21
  }
22
+
23
+ decodeError(data: string): string {
24
+ if (!data.startsWith("0x")) {
25
+ data = "0x" + data;
26
+ }
27
+
28
+ const errorSelector = data.slice(0, 10);
29
+
30
+ const errorFragment = this.interface.getError(errorSelector);
31
+ if (!errorFragment) {
32
+ throw new Error(`Error selector not found in ABI: ${errorSelector}`);
33
+ }
34
+
35
+ return errorFragment.name;
36
+ }
22
37
  }
@@ -1,8 +1,8 @@
1
- import { PrivateKey } from "@/identities/PrivateKey";
2
1
  import { PublicKey } from "@/identities/PublicKey";
3
2
  import { SignedMessage } from "@/types";
4
- import { keccak256 } from "ethers";
5
- import { verify } from "@noble/secp256k1";
3
+ import { hashMessage, verifyMessage } from "ethers";
4
+ import { Address, PrivateKey } from "@/identities";
5
+ import { SigningKey } from "ethers";
6
6
 
7
7
  export class Message {
8
8
  public publicKey: string;
@@ -23,21 +23,24 @@ export class Message {
23
23
  const privateKey = PrivateKey.fromPassphrase(passphrase);
24
24
  const publicKey = PublicKey.fromPassphrase(passphrase).publicKey;
25
25
 
26
- const signature = await privateKey.sign(Buffer.from(message).toString("hex"));
26
+ // Sign messages using eip-191 signed data specification, to be aligned with ledger signing workflow.
27
+ // @see https://developers.ledger.com/docs/ledger-live/discover/integration/wallet-api/server/handlers/message
28
+ const signature = new SigningKey(`0x${privateKey.privateKey}`).sign(hashMessage(message));
27
29
 
28
30
  return Message.new({
29
31
  publicKey,
30
- signature: signature.r + signature.s + signature.v.toString(16).padStart(2, "0"),
32
+ signature: signature.serialized,
31
33
  message,
32
34
  });
33
35
  }
34
36
 
35
37
  verify(): boolean {
36
- const message = Buffer.from(keccak256(Buffer.from(this.message)).slice(2), "hex");
37
- const signature = Buffer.from(this.signature.slice(0, 128), "hex");
38
- const publicKey = Buffer.from(this.publicKey, "hex");
38
+ const message = new Uint8Array(new TextEncoder().encode(this.message));
39
+ const address = Address.fromPublicKey(this.publicKey);
40
+ // Messages need to be signed using eip-191 signed data specification
41
+ const signerAddress = verifyMessage(message, this.signature);
39
42
 
40
- return verify(signature, message, publicKey);
43
+ return signerAddress === address;
41
44
  }
42
45
 
43
46
  toString(): string {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "message": "Hello, world!",
3
3
  "publicKey": "0243333347c8cbf4e3cbc7a96964181d02a2b0c854faa2fef86b4b8d92afcf473d",
4
- "signature": "0e2e53409be748834cac44052817ecef569b429a0492aa6bbc0d934eb71a09547e77aeef33d45669bbcba0498149f0e2b637fe8905186e08a5410c6f2b013bb400"
4
+ "signature": "0x2bdd0c58ff8a25f456065fb731c73308a25d0a09f351f23e3c7dd3882776d33d626b0cafc0b99dd7504b24f6ecd2e036a267c8e5e005f36dcbc03b2e33fa7fc31c"
5
5
  }
@@ -44,3 +44,32 @@ it("should decode using a custom abi", () => {
44
44
  expect(decodedData.args[0]).toEqual(args[0]);
45
45
  expect(decodedData.args[1].map((value: BigInt) => value.toString())).toEqual(args[1]);
46
46
  });
47
+
48
+ it("should decode error data and return error name", () => {
49
+ const decoder = new AbiDecoder(ContractAbiType.USERNAMES);
50
+
51
+ const errorData = "0xa0ca2f4e";
52
+
53
+ const errorName = decoder.decodeError(errorData);
54
+
55
+ expect(errorName).toBe("TakenUsername");
56
+ });
57
+
58
+ it("should decode error data without 0x prefix", () => {
59
+ const decoder = new AbiDecoder(ContractAbiType.USERNAMES);
60
+
61
+ // Same as above but without 0x prefix
62
+ const errorData = "a0ca2f4e";
63
+
64
+ const errorName = decoder.decodeError(errorData);
65
+
66
+ expect(errorName).toBe("TakenUsername");
67
+ });
68
+
69
+ it("should throw error for unknown error selector", () => {
70
+ const decoder = new AbiDecoder(ContractAbiType.USERNAMES);
71
+
72
+ const errorData = "0x12345678";
73
+
74
+ expect(() => decoder.decodeError(errorData)).toThrow("Error selector not found in ABI: 0x12345678");
75
+ });