@aptos-labs/ts-sdk 7.0.1 → 7.1.0
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/account/AbstractKeylessAccount.d.ts.map +1 -1
- package/dist/account/AbstractKeylessAccount.js +3 -0
- package/dist/account/AbstractKeylessAccount.js.map +1 -1
- package/dist/account/EphemeralKeyPair.d.ts +29 -6
- package/dist/account/EphemeralKeyPair.d.ts.map +1 -1
- package/dist/account/EphemeralKeyPair.js +35 -8
- package/dist/account/EphemeralKeyPair.js.map +1 -1
- package/dist/bcs/deserializer.d.ts.map +1 -1
- package/dist/bcs/deserializer.js +15 -0
- package/dist/bcs/deserializer.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/localNode.d.ts.map +1 -1
- package/dist/cli/localNode.js +6 -0
- package/dist/cli/localNode.js.map +1 -1
- package/dist/cli/move.d.ts.map +1 -1
- package/dist/cli/move.js +8 -0
- package/dist/cli/move.js.map +1 -1
- package/dist/cli/spawnArgs.d.ts +12 -0
- package/dist/cli/spawnArgs.d.ts.map +1 -0
- package/dist/cli/spawnArgs.js +51 -0
- package/dist/cli/spawnArgs.js.map +1 -0
- package/dist/core/crypto/ed25519.d.ts +117 -4
- package/dist/core/crypto/ed25519.d.ts.map +1 -1
- package/dist/core/crypto/ed25519.js +128 -14
- package/dist/core/crypto/ed25519.js.map +1 -1
- package/dist/core/crypto/keyless.d.ts +14 -0
- package/dist/core/crypto/keyless.d.ts.map +1 -1
- package/dist/core/crypto/keyless.js +22 -3
- package/dist/core/crypto/keyless.js.map +1 -1
- package/dist/core/crypto/poseidon.js +5 -5
- package/dist/core/crypto/poseidon.js.map +1 -1
- package/dist/core/crypto/secp256k1.d.ts +123 -5
- package/dist/core/crypto/secp256k1.d.ts.map +1 -1
- package/dist/core/crypto/secp256k1.js +137 -13
- package/dist/core/crypto/secp256k1.js.map +1 -1
- package/dist/core/crypto/secp256r1.d.ts +121 -1
- package/dist/core/crypto/secp256r1.d.ts.map +1 -1
- package/dist/core/crypto/secp256r1.js +156 -9
- package/dist/core/crypto/secp256r1.js.map +1 -1
- package/dist/core/crypto/utils.d.ts +28 -1
- package/dist/core/crypto/utils.d.ts.map +1 -1
- package/dist/core/crypto/utils.js +28 -1
- package/dist/core/crypto/utils.js.map +1 -1
- package/dist/errors/index.d.ts +19 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +35 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/internal/account.d.ts +17 -0
- package/dist/internal/account.d.ts.map +1 -1
- package/dist/internal/account.js +66 -17
- package/dist/internal/account.js.map +1 -1
- package/dist/internal/keyless.d.ts.map +1 -1
- package/dist/internal/keyless.js +86 -2
- package/dist/internal/keyless.js.map +1 -1
- package/dist/internal/transaction.d.ts.map +1 -1
- package/dist/internal/transaction.js +20 -3
- package/dist/internal/transaction.js.map +1 -1
- package/dist/transactions/transactionBuilder/encryptPayload.d.ts.map +1 -1
- package/dist/transactions/transactionBuilder/encryptPayload.js +37 -38
- package/dist/transactions/transactionBuilder/encryptPayload.js.map +1 -1
- package/dist/transactions/types.d.ts +17 -13
- package/dist/transactions/types.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +16 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +29 -0
- package/dist/utils/helpers.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/src/account/AbstractKeylessAccount.ts +3 -0
- package/src/account/EphemeralKeyPair.ts +35 -8
- package/src/bcs/deserializer.ts +16 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/localNode.ts +7 -0
- package/src/cli/move.ts +9 -0
- package/src/cli/spawnArgs.ts +55 -0
- package/src/core/crypto/ed25519.ts +132 -15
- package/src/core/crypto/keyless.ts +22 -3
- package/src/core/crypto/poseidon.ts +5 -5
- package/src/core/crypto/secp256k1.ts +141 -13
- package/src/core/crypto/secp256r1.ts +164 -11
- package/src/core/crypto/utils.ts +28 -1
- package/src/errors/index.ts +37 -0
- package/src/internal/account.ts +73 -17
- package/src/internal/keyless.ts +88 -2
- package/src/internal/transaction.ts +22 -3
- package/src/transactions/transactionBuilder/encryptPayload.ts +51 -45
- package/src/transactions/types.ts +17 -13
- package/src/utils/helpers.ts +33 -0
- package/src/version.ts +1 -1
package/src/cli/localNode.ts
CHANGED
|
@@ -3,6 +3,7 @@ import kill from "tree-kill";
|
|
|
3
3
|
import { platform } from "node:os";
|
|
4
4
|
|
|
5
5
|
import { sleep } from "../utils/helpers.js";
|
|
6
|
+
import { assertSafeCliArgs } from "./spawnArgs.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Represents a local node for running a localnet environment.
|
|
@@ -86,6 +87,12 @@ export class LocalNode {
|
|
|
86
87
|
* @category CLI
|
|
87
88
|
*/
|
|
88
89
|
start(): void {
|
|
90
|
+
// Reject shell-metacharacter-bearing extras up front. On Windows we have
|
|
91
|
+
// to spawn with `shell: true` (npx is a .cmd shim and Node refuses to
|
|
92
|
+
// spawn .cmd/.bat without the shell since CVE-2024-27980), so unsafe
|
|
93
|
+
// characters in extraArgs would otherwise be interpreted by cmd.exe.
|
|
94
|
+
assertSafeCliArgs(this.extraArgs);
|
|
95
|
+
|
|
89
96
|
const cliCommand = "npx";
|
|
90
97
|
const cliArgs = [
|
|
91
98
|
"aptos",
|
package/src/cli/move.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { platform } from "node:os";
|
|
|
3
3
|
|
|
4
4
|
import { AccountAddress } from "../core/index.js";
|
|
5
5
|
import { Network } from "../utils/index.js";
|
|
6
|
+
import { assertSafeCliArgs } from "./spawnArgs.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Class representing a Move package management utility for the Aptos blockchain.
|
|
@@ -355,6 +356,14 @@ export class Move {
|
|
|
355
356
|
*/
|
|
356
357
|
|
|
357
358
|
private async runCommand(args: Array<string>, showStdout: boolean = true): Promise<{ result?: any; output: string }> {
|
|
359
|
+
// Reject shell-metacharacter-bearing args up front. On Windows we have to
|
|
360
|
+
// spawn with `shell: true` (npx is a .cmd shim and Node refuses to spawn
|
|
361
|
+
// .cmd/.bat without the shell since CVE-2024-27980), so unsafe characters
|
|
362
|
+
// in args would otherwise be interpreted by cmd.exe. We validate on all
|
|
363
|
+
// platforms for consistency — extraArguments shouldn't contain shell
|
|
364
|
+
// metacharacters regardless of OS.
|
|
365
|
+
assertSafeCliArgs(args);
|
|
366
|
+
|
|
358
367
|
return new Promise((resolve, reject) => {
|
|
359
368
|
const isWindows = platform() === "win32";
|
|
360
369
|
const spawnOptions = isWindows ? { shell: true } : undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Copyright © Aptos Foundation
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shell metacharacters that enable command injection when passed through
|
|
6
|
+
* `spawn(..., { shell: true })`. We have to keep `shell: true` on Windows
|
|
7
|
+
* because Node.js 18.20.2+ / 20.12.2+ refuses to spawn `.cmd`/`.bat` shims
|
|
8
|
+
* (like `npx.cmd`) without it (CVE-2024-27980 mitigation), so the next-best
|
|
9
|
+
* mitigation is to reject argument strings that contain characters the shell
|
|
10
|
+
* would interpret.
|
|
11
|
+
*
|
|
12
|
+
* - cmd.exe metacharacters: `& | < > ^ ( ) " ' % !` plus newlines
|
|
13
|
+
* (`%` triggers environment-variable expansion like `%USERPROFILE%`;
|
|
14
|
+
* `!` triggers delayed expansion).
|
|
15
|
+
* - /bin/sh metacharacters: `& | ; < > ` $ ( ) "` `'` plus newlines.
|
|
16
|
+
*
|
|
17
|
+
* Backslash is intentionally NOT in the blocklist even though it's a
|
|
18
|
+
* /bin/sh escape character — Windows paths (`C:\Program Files\...`) and
|
|
19
|
+
* Windows-style flag values rely on it, and disallowing it would break
|
|
20
|
+
* legitimate `extraArgs` usage on every Move/LocalNode call from a Windows
|
|
21
|
+
* developer machine. The trade-off: on POSIX a caller passing `"a\b"` will
|
|
22
|
+
* have the backslash interpreted by `/bin/sh`, but our spawn call uses
|
|
23
|
+
* `shell: false` on POSIX anyway, so this doesn't materially matter.
|
|
24
|
+
*
|
|
25
|
+
* Common, legitimate CLI argument characters (letters, digits, `-`, `_`,
|
|
26
|
+
* `=`, `.`, `,`, `:`, `/`, `\`, space) are unaffected.
|
|
27
|
+
*/
|
|
28
|
+
const UNSAFE_SHELL_CHARS = /[&|;<>`$()"'\n\r^!*?%]/;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Validates that a CLI argument does not contain shell metacharacters that
|
|
32
|
+
* could be interpreted by the shell when passed via `spawn(..., { shell: true })`.
|
|
33
|
+
*
|
|
34
|
+
* @throws Error if `arg` contains any unsafe shell character.
|
|
35
|
+
*/
|
|
36
|
+
export function assertSafeCliArg(arg: string): void {
|
|
37
|
+
if (typeof arg !== "string") {
|
|
38
|
+
throw new Error(`CLI argument must be a string, received ${typeof arg}`);
|
|
39
|
+
}
|
|
40
|
+
if (UNSAFE_SHELL_CHARS.test(arg)) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`CLI argument contains characters that could be interpreted by the shell: ${JSON.stringify(arg)}. ` +
|
|
43
|
+
"Remove shell metacharacters (& | ; < > \" ' ` $ ( ) ^ ! * ? % newlines).",
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validates every element of an args array. See {@link assertSafeCliArg}.
|
|
50
|
+
*/
|
|
51
|
+
export function assertSafeCliArgs(args: ReadonlyArray<string>): void {
|
|
52
|
+
for (const arg of args) {
|
|
53
|
+
assertSafeCliArg(arg);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -11,6 +11,7 @@ import { CKDPriv, deriveKey, HARDENED_OFFSET, isValidHardenedPath, mnemonicToSee
|
|
|
11
11
|
import { PrivateKey } from "./privateKey.js";
|
|
12
12
|
import { AccountPublicKey, PublicKey, VerifySignatureArgs, VerifySignatureAsyncArgs } from "./publicKey.js";
|
|
13
13
|
import { Signature } from "./signature.js";
|
|
14
|
+
import { TEXT_ENCODER } from "../../utils/const.js";
|
|
14
15
|
import { convertSigningMessage } from "./utils.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -98,26 +99,63 @@ export class Ed25519PublicKey extends AccountPublicKey {
|
|
|
98
99
|
// region AccountPublicKey
|
|
99
100
|
|
|
100
101
|
/**
|
|
101
|
-
* Verifies a
|
|
102
|
+
* Verifies a signature against the exact bytes of `message`. This is the
|
|
103
|
+
* unambiguous form — the input is interpreted as raw bytes regardless of
|
|
104
|
+
* what they encode. Pair with {@link Ed25519PrivateKey.signBytes}.
|
|
105
|
+
*
|
|
106
|
+
* Performs an Ed25519 malleability check (rejects non-canonical S values)
|
|
107
|
+
* before delegating to the underlying curve verifier.
|
|
102
108
|
*
|
|
103
109
|
* @param args - The arguments for verification.
|
|
104
|
-
* @param args.message -
|
|
105
|
-
* @param args.signature - The signature
|
|
110
|
+
* @param args.message - The exact bytes that were signed.
|
|
111
|
+
* @param args.signature - The signature to verify.
|
|
106
112
|
* @group Implementation
|
|
107
113
|
* @category Serialization
|
|
108
114
|
*/
|
|
109
|
-
|
|
115
|
+
verifyBytes(args: { message: Uint8Array; signature: Signature }): boolean {
|
|
110
116
|
const { message, signature } = args;
|
|
111
|
-
// Verify malleability
|
|
112
117
|
if (!isCanonicalEd25519Signature(signature)) {
|
|
113
118
|
return false;
|
|
114
119
|
}
|
|
120
|
+
return ed25519.verify(signature.toUint8Array(), message, this.key.toUint8Array());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Verifies a signature against the UTF-8 encoding of `message`. The input
|
|
125
|
+
* is always treated as text — there is no hex/text heuristic. Pair with
|
|
126
|
+
* {@link Ed25519PrivateKey.signText}.
|
|
127
|
+
*
|
|
128
|
+
* @param args - The arguments for verification.
|
|
129
|
+
* @param args.message - The text that was signed.
|
|
130
|
+
* @param args.signature - The signature to verify.
|
|
131
|
+
* @group Implementation
|
|
132
|
+
* @category Serialization
|
|
133
|
+
*/
|
|
134
|
+
verifyText(args: { message: string; signature: Signature }): boolean {
|
|
135
|
+
return this.verifyBytes({ message: TEXT_ENCODER.encode(args.message), signature: args.signature });
|
|
136
|
+
}
|
|
115
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Verifies a signed message using a public key.
|
|
140
|
+
*
|
|
141
|
+
* @deprecated The polymorphic `message: HexInput` input is ambiguous — a
|
|
142
|
+
* bare even-length string of hex characters (e.g., `"cafe"`) is
|
|
143
|
+
* interpreted as the 2 bytes `[0xCA, 0xFE]`, not as 4 UTF-8 text bytes.
|
|
144
|
+
* Use {@link verifyBytes} for `Uint8Array` input or {@link verifyText}
|
|
145
|
+
* for `string` input; both are unambiguous. See
|
|
146
|
+
* {@link convertSigningMessage} for the full legacy rule.
|
|
147
|
+
*
|
|
148
|
+
* @param args - The arguments for verification.
|
|
149
|
+
* @param args.message - A signed message as a Hex string or Uint8Array.
|
|
150
|
+
* @param args.signature - The signature of the message.
|
|
151
|
+
* @group Implementation
|
|
152
|
+
* @category Serialization
|
|
153
|
+
*/
|
|
154
|
+
verifySignature(args: VerifySignatureArgs): boolean {
|
|
155
|
+
const { message, signature } = args;
|
|
116
156
|
const messageToVerify = convertSigningMessage(message);
|
|
117
157
|
const messageBytes = Hex.fromHexInput(messageToVerify).toUint8Array();
|
|
118
|
-
|
|
119
|
-
const publicKeyBytes = this.key.toUint8Array();
|
|
120
|
-
return ed25519.verify(signatureBytes, messageBytes, publicKeyBytes);
|
|
158
|
+
return this.verifyBytes({ message: messageBytes, signature });
|
|
121
159
|
}
|
|
122
160
|
|
|
123
161
|
/**
|
|
@@ -362,11 +400,40 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
362
400
|
}
|
|
363
401
|
|
|
364
402
|
/**
|
|
365
|
-
*
|
|
366
|
-
* After calling this method
|
|
403
|
+
* Overwrites the underlying private-key byte buffer with random bytes and
|
|
404
|
+
* then zeros. After calling this method the key can no longer sign or
|
|
405
|
+
* derive a public key.
|
|
406
|
+
*
|
|
407
|
+
* SECURITY: This is a best-effort window-narrowing tool, NOT a true
|
|
408
|
+
* zeroization guarantee. In JavaScript, four classes of copies cannot be
|
|
409
|
+
* reached from user code and so survive `clear()`:
|
|
367
410
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
411
|
+
* 1. **JS string copies.** Any value previously produced by `toString()`,
|
|
412
|
+
* `toHexString()`, or `bcsToHex().toString()` is an immutable string
|
|
413
|
+
* in the heap. The language provides no API to overwrite string
|
|
414
|
+
* memory; it is reclaimed only when GC collects it.
|
|
415
|
+
* 2. **noble-curves internals.** The sign path inside `@noble/curves`
|
|
416
|
+
* expands the private key into scalar `BigInt` field elements, which
|
|
417
|
+
* are also immutable in V8/JSC/Hermes. Even if noble explicitly zeroed
|
|
418
|
+
* its own byte copies after use, the `BigInt` intermediates persist.
|
|
419
|
+
* 3. **JIT register / stack residue.** The engine may have held key
|
|
420
|
+
* bytes in CPU registers or on the engine stack during a sign call.
|
|
421
|
+
* There is no JS-visible way to scrub those.
|
|
422
|
+
* 4. **GC-relocated copies.** Generational GCs (V8, JSC) copy live
|
|
423
|
+
* objects between heap regions during minor/major collections. The
|
|
424
|
+
* `Uint8Array` we zeroed may have stale copies sitting in survivor
|
|
425
|
+
* space until the next cycle reclaims them.
|
|
426
|
+
*
|
|
427
|
+
* This method zeros the SDK's own `Uint8Array` (the most reachable
|
|
428
|
+
* copy), but downstream consumers should treat it as a hardening signal,
|
|
429
|
+
* not a guarantee. If you need real key-material hygiene, prefer
|
|
430
|
+
* non-extractable `crypto.subtle` keys (where the underlying algorithm
|
|
431
|
+
* is supported by the host runtime), a WASM-backed crypto library, or
|
|
432
|
+
* hardware-backed keys (passkeys / secure enclave / HSM).
|
|
433
|
+
*
|
|
434
|
+
* To minimize the size of the unreachable-copy set, avoid calling
|
|
435
|
+
* `toString()` / `toHexString()` on private keys at all in long-lived
|
|
436
|
+
* processes — the byte form is what gets cleared.
|
|
370
437
|
*
|
|
371
438
|
* @group Implementation
|
|
372
439
|
* @category Serialization
|
|
@@ -412,10 +479,49 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
412
479
|
return new Ed25519PublicKey(bytes);
|
|
413
480
|
}
|
|
414
481
|
|
|
482
|
+
/**
|
|
483
|
+
* Sign exactly the bytes of `message`. The input is interpreted as raw
|
|
484
|
+
* bytes regardless of what they encode. Pair with
|
|
485
|
+
* {@link Ed25519PublicKey.verifyBytes}.
|
|
486
|
+
*
|
|
487
|
+
* @param message - The exact bytes to sign.
|
|
488
|
+
* @returns A digital signature for the provided bytes.
|
|
489
|
+
* @throws Error if the private key has been cleared from memory.
|
|
490
|
+
* @group Implementation
|
|
491
|
+
* @category Serialization
|
|
492
|
+
*/
|
|
493
|
+
signBytes(message: Uint8Array): Ed25519Signature {
|
|
494
|
+
this.ensureNotCleared();
|
|
495
|
+
const signatureBytes = ed25519.sign(message, this.signingKey.toUint8Array());
|
|
496
|
+
return new Ed25519Signature(signatureBytes);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Sign the UTF-8 encoding of `message`. The input is always treated as
|
|
501
|
+
* text — there is no hex/text heuristic. Pair with
|
|
502
|
+
* {@link Ed25519PublicKey.verifyText}.
|
|
503
|
+
*
|
|
504
|
+
* @param message - The text to sign.
|
|
505
|
+
* @returns A digital signature for the UTF-8 bytes of the provided text.
|
|
506
|
+
* @throws Error if the private key has been cleared from memory.
|
|
507
|
+
* @group Implementation
|
|
508
|
+
* @category Serialization
|
|
509
|
+
*/
|
|
510
|
+
signText(message: string): Ed25519Signature {
|
|
511
|
+
return this.signBytes(TEXT_ENCODER.encode(message));
|
|
512
|
+
}
|
|
513
|
+
|
|
415
514
|
/**
|
|
416
515
|
* Sign the given message with the private key.
|
|
417
516
|
* This function generates a digital signature for the specified message, ensuring its authenticity and integrity.
|
|
418
517
|
*
|
|
518
|
+
* @deprecated The polymorphic `message: HexInput` input is ambiguous — a
|
|
519
|
+
* bare even-length string of hex characters (e.g., `"cafe"`) is signed
|
|
520
|
+
* as the 2 bytes `[0xCA, 0xFE]`, not as 4 UTF-8 text bytes. Use
|
|
521
|
+
* {@link signBytes} for `Uint8Array` input or {@link signText} for
|
|
522
|
+
* `string` input; both are unambiguous. See
|
|
523
|
+
* {@link convertSigningMessage} for the full legacy rule.
|
|
524
|
+
*
|
|
419
525
|
* @param message - A message as a string or Uint8Array in HexInput format.
|
|
420
526
|
* @returns A digital signature for the provided message.
|
|
421
527
|
* @throws Error if the private key has been cleared from memory.
|
|
@@ -423,11 +529,9 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
423
529
|
* @category Serialization
|
|
424
530
|
*/
|
|
425
531
|
sign(message: HexInput): Ed25519Signature {
|
|
426
|
-
this.ensureNotCleared();
|
|
427
532
|
const messageToSign = convertSigningMessage(message);
|
|
428
533
|
const messageBytes = Hex.fromHexInput(messageToSign).toUint8Array();
|
|
429
|
-
|
|
430
|
-
return new Ed25519Signature(signatureBytes);
|
|
534
|
+
return this.signBytes(messageBytes);
|
|
431
535
|
}
|
|
432
536
|
|
|
433
537
|
/**
|
|
@@ -446,6 +550,13 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
446
550
|
/**
|
|
447
551
|
* Get the private key as a hex string with the 0x prefix.
|
|
448
552
|
*
|
|
553
|
+
* SECURITY: This produces an immutable JS string containing the key
|
|
554
|
+
* material in hex. Strings cannot be zeroed by `clear()` (see the
|
|
555
|
+
* `clear()` JSDoc for the four classes of unreachable copies). Avoid
|
|
556
|
+
* calling this method on long-lived `Ed25519PrivateKey` instances in
|
|
557
|
+
* processes where memory hygiene matters; prefer `toUint8Array()`,
|
|
558
|
+
* which returns a clearable `Uint8Array`.
|
|
559
|
+
*
|
|
449
560
|
* @returns string representation of the private key.
|
|
450
561
|
* @throws Error if the private key has been cleared from memory.
|
|
451
562
|
* @group Implementation
|
|
@@ -459,6 +570,9 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
459
570
|
/**
|
|
460
571
|
* Get the private key as a hex string with the 0x prefix.
|
|
461
572
|
*
|
|
573
|
+
* SECURITY: Same caveat as `toString()` — the returned string is an
|
|
574
|
+
* immutable JS heap allocation that `clear()` cannot zero.
|
|
575
|
+
*
|
|
462
576
|
* @returns string representation of the private key.
|
|
463
577
|
* @throws Error if the private key has been cleared from memory.
|
|
464
578
|
*/
|
|
@@ -472,6 +586,9 @@ export class Ed25519PrivateKey extends Serializable implements PrivateKey {
|
|
|
472
586
|
*
|
|
473
587
|
* [Read about AIP-80](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-80.md)
|
|
474
588
|
*
|
|
589
|
+
* SECURITY: Same caveat as `toString()` — produces an immutable JS string
|
|
590
|
+
* containing the key material; cannot be zeroed by `clear()`.
|
|
591
|
+
*
|
|
475
592
|
* @returns AIP-80 compliant string representation of the private key.
|
|
476
593
|
* @throws Error if the private key has been cleared from memory.
|
|
477
594
|
*/
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
PatchedJWKsResponse,
|
|
29
29
|
} from "../../types/keyless.js";
|
|
30
30
|
import { AptosConfig } from "../../api/aptosConfig.js";
|
|
31
|
+
import { u64ToNumberSafe } from "../../utils/helpers.js";
|
|
31
32
|
import { getAptosFullNode } from "../../client/index.js";
|
|
32
33
|
import { memoizeAsync } from "../../utils/memoize.js";
|
|
33
34
|
import { AccountAddress, AccountAddressInput } from "../accountAddress.js";
|
|
@@ -295,6 +296,14 @@ export class KeylessPublicKey extends AccountPublicKey {
|
|
|
295
296
|
* Creates a KeylessPublicKey instance from a JWT and a pepper value.
|
|
296
297
|
* This function is useful for generating a public key that can be used for authentication based on the provided JWT claims and pepper.
|
|
297
298
|
*
|
|
299
|
+
* SECURITY: `jwtDecode` is a decode-only library — it does NOT verify the
|
|
300
|
+
* JWT signature. The cryptographic binding between the JWT and the user's
|
|
301
|
+
* identity is enforced on-chain by the keyless verifier (which validates
|
|
302
|
+
* the JWT signature against the JWK set published on-chain). Callers MUST
|
|
303
|
+
* therefore obtain `jwt` directly from a trusted IdP redirect/OAuth flow;
|
|
304
|
+
* do not accept arbitrary user-supplied JWT strings here, since a tampered
|
|
305
|
+
* JWT will derive a different account address than the chain expects.
|
|
306
|
+
*
|
|
298
307
|
* @param args - The arguments for creating the KeylessPublicKey.
|
|
299
308
|
* @param args.jwt - The JSON Web Token to decode.
|
|
300
309
|
* @param args.pepper - The pepper value used in the key creation process.
|
|
@@ -305,6 +314,7 @@ export class KeylessPublicKey extends AccountPublicKey {
|
|
|
305
314
|
*/
|
|
306
315
|
static fromJwtAndPepper(args: { jwt: string; pepper: HexInput; uidKey?: string }): KeylessPublicKey {
|
|
307
316
|
const { jwt, pepper, uidKey = "sub" } = args;
|
|
317
|
+
// SECURITY: signature is not verified here — see method-level JSDoc.
|
|
308
318
|
const jwtPayload = jwtDecode<JwtPayload & { [key: string]: string }>(jwt);
|
|
309
319
|
if (typeof jwtPayload.iss !== "string") {
|
|
310
320
|
throw new Error("iss was not found");
|
|
@@ -652,7 +662,7 @@ export class KeylessSignature extends Signature {
|
|
|
652
662
|
const ephemeralSignature = EphemeralSignature.deserialize(deserializer);
|
|
653
663
|
return new KeylessSignature({
|
|
654
664
|
jwtHeader,
|
|
655
|
-
expiryDateSecs:
|
|
665
|
+
expiryDateSecs: u64ToNumberSafe(expiryDateSecs, "KeylessSignature.expiryDateSecs"),
|
|
656
666
|
ephemeralCertificate,
|
|
657
667
|
ephemeralPublicKey,
|
|
658
668
|
ephemeralSignature,
|
|
@@ -1116,7 +1126,7 @@ export class ZeroKnowledgeSig extends Signature {
|
|
|
1116
1126
|
|
|
1117
1127
|
static deserialize(deserializer: Deserializer): ZeroKnowledgeSig {
|
|
1118
1128
|
const proof = ZkProof.deserialize(deserializer);
|
|
1119
|
-
const expHorizonSecs =
|
|
1129
|
+
const expHorizonSecs = u64ToNumberSafe(deserializer.deserializeU64(), "ZeroKnowledgeSig.expHorizonSecs");
|
|
1120
1130
|
const extraField = deserializer.deserializeOption("string");
|
|
1121
1131
|
const overrideAudVal = deserializer.deserializeOption("string");
|
|
1122
1132
|
const trainingWheelsSignature = deserializer.deserializeOption(EphemeralSignature);
|
|
@@ -1228,7 +1238,9 @@ export class KeylessConfiguration {
|
|
|
1228
1238
|
gammaAbcG1: res.gamma_abc_g1,
|
|
1229
1239
|
gammaG2: res.gamma_g2,
|
|
1230
1240
|
}),
|
|
1231
|
-
|
|
1241
|
+
// Chain config returns u64 as a decimal string; widen → safe-narrow so
|
|
1242
|
+
// a malformed/exotic value throws rather than silently truncates.
|
|
1243
|
+
maxExpHorizonSecs: u64ToNumberSafe(BigInt(config.max_exp_horizon_secs), "KeylessConfiguration.maxExpHorizonSecs"),
|
|
1232
1244
|
trainingWheelsPubkey: config.training_wheels_pubkey.vec[0],
|
|
1233
1245
|
maxExtraFieldBytes: config.max_extra_field_bytes,
|
|
1234
1246
|
maxJwtHeaderB64Bytes: config.max_jwt_header_b64_bytes,
|
|
@@ -1457,6 +1469,12 @@ export async function getKeylessConfig(args: {
|
|
|
1457
1469
|
/**
|
|
1458
1470
|
* Parses a JWT and returns the 'iss', 'aud', and 'uid' values.
|
|
1459
1471
|
*
|
|
1472
|
+
* SECURITY: This function decodes claims without verifying the JWT signature.
|
|
1473
|
+
* The keyless on-chain verifier is the authority that binds a JWT to its IdP;
|
|
1474
|
+
* the SDK only uses these claims to derive the keyless account address and
|
|
1475
|
+
* package the JWT for the prover service. Callers must source `jwt` from a
|
|
1476
|
+
* trusted IdP redirect flow.
|
|
1477
|
+
*
|
|
1460
1478
|
* @param args - The arguments for parsing the JWT.
|
|
1461
1479
|
* @param args.jwt - The JWT to parse.
|
|
1462
1480
|
* @param args.uidKey - The key to use for the 'uid' value; defaults to 'sub'.
|
|
@@ -1470,6 +1488,7 @@ export function getIssAudAndUidVal(args: { jwt: string; uidKey?: string }): {
|
|
|
1470
1488
|
const { jwt, uidKey = "sub" } = args;
|
|
1471
1489
|
let jwtPayload: JwtPayload & { [key: string]: string };
|
|
1472
1490
|
try {
|
|
1491
|
+
// SECURITY: signature is not verified here — see function-level JSDoc.
|
|
1473
1492
|
jwtPayload = jwtDecode<JwtPayload & { [key: string]: string }>(jwt);
|
|
1474
1493
|
} catch {
|
|
1475
1494
|
throw KeylessError.fromErrorType({
|
|
@@ -68,7 +68,7 @@ export function hashStrToField(str: string, maxSizeBytes: number): bigint {
|
|
|
68
68
|
*/
|
|
69
69
|
function hashBytesWithLen(bytes: Uint8Array, maxSizeBytes: number): bigint {
|
|
70
70
|
if (bytes.length > maxSizeBytes) {
|
|
71
|
-
throw new Error(`
|
|
71
|
+
throw new Error(`Input bytes of length ${bytes.length} is longer than ${maxSizeBytes}`);
|
|
72
72
|
}
|
|
73
73
|
const packed = padAndPackBytesWithLen(bytes, maxSizeBytes);
|
|
74
74
|
return poseidonHash(packed);
|
|
@@ -86,7 +86,7 @@ function hashBytesWithLen(bytes: Uint8Array, maxSizeBytes: number): bigint {
|
|
|
86
86
|
*/
|
|
87
87
|
function padAndPackBytesNoLen(bytes: Uint8Array, maxSizeBytes: number): bigint[] {
|
|
88
88
|
if (bytes.length > maxSizeBytes) {
|
|
89
|
-
throw new Error(`Input bytes of length ${bytes} is longer than ${maxSizeBytes}`);
|
|
89
|
+
throw new Error(`Input bytes of length ${bytes.length} is longer than ${maxSizeBytes}`);
|
|
90
90
|
}
|
|
91
91
|
const paddedStrBytes = padUint8ArrayWithZeros(bytes, maxSizeBytes);
|
|
92
92
|
return packBytes(paddedStrBytes);
|
|
@@ -106,7 +106,7 @@ function padAndPackBytesNoLen(bytes: Uint8Array, maxSizeBytes: number): bigint[]
|
|
|
106
106
|
*/
|
|
107
107
|
export function padAndPackBytesWithLen(bytes: Uint8Array, maxSizeBytes: number): bigint[] {
|
|
108
108
|
if (bytes.length > maxSizeBytes) {
|
|
109
|
-
throw new Error(`Input bytes of length ${bytes} is longer than ${maxSizeBytes}`);
|
|
109
|
+
throw new Error(`Input bytes of length ${bytes.length} is longer than ${maxSizeBytes}`);
|
|
110
110
|
}
|
|
111
111
|
return padAndPackBytesNoLen(bytes, maxSizeBytes).concat([BigInt(bytes.length)]);
|
|
112
112
|
}
|
|
@@ -221,9 +221,9 @@ function padUint8ArrayWithZeros(inputArray: Uint8Array, paddedSize: number): Uin
|
|
|
221
221
|
* @category Serialization
|
|
222
222
|
*/
|
|
223
223
|
export function poseidonHash(inputs: (number | bigint | string)[]): bigint {
|
|
224
|
-
if (inputs.length > numInputsToPoseidonFunc.length) {
|
|
224
|
+
if (inputs.length === 0 || inputs.length > numInputsToPoseidonFunc.length) {
|
|
225
225
|
throw new Error(
|
|
226
|
-
`
|
|
226
|
+
`poseidonHash requires between 1 and ${numInputsToPoseidonFunc.length} inputs, got ${inputs.length}`,
|
|
227
227
|
);
|
|
228
228
|
}
|
|
229
229
|
return numInputsToPoseidonFunc[inputs.length - 1](inputs);
|
|
@@ -12,6 +12,7 @@ import { PrivateKey } from "./privateKey.js";
|
|
|
12
12
|
import { PublicKey } from "./publicKey.js";
|
|
13
13
|
import { Signature } from "./signature.js";
|
|
14
14
|
import { convertSigningMessage } from "./utils.js";
|
|
15
|
+
import { TEXT_ENCODER } from "../../utils/const.js";
|
|
15
16
|
import { AptosConfig } from "../../api/aptosConfig.js";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -62,10 +63,54 @@ export class Secp256k1PublicKey extends PublicKey {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
// region PublicKey
|
|
66
|
+
/**
|
|
67
|
+
* Verifies a signature against the exact bytes of `message`. This is the
|
|
68
|
+
* unambiguous form — the input is interpreted as raw bytes regardless of
|
|
69
|
+
* what they encode. Pair with {@link Secp256k1PrivateKey.signBytes}.
|
|
70
|
+
*
|
|
71
|
+
* The message is SHA3-256 hashed before verification (matching the
|
|
72
|
+
* Aptos-side Secp256k1 signing convention), and the signature is required
|
|
73
|
+
* to be in canonical low-S form for malleability resistance.
|
|
74
|
+
*
|
|
75
|
+
* @param args - The arguments for verification.
|
|
76
|
+
* @param args.message - The exact bytes that were signed.
|
|
77
|
+
* @param args.signature - The signature to verify.
|
|
78
|
+
* @group Implementation
|
|
79
|
+
* @category Serialization
|
|
80
|
+
*/
|
|
81
|
+
verifyBytes(args: { message: Uint8Array; signature: Secp256k1Signature }): boolean {
|
|
82
|
+
const { message, signature } = args;
|
|
83
|
+
const messageSha3Bytes = sha3_256(message);
|
|
84
|
+
return secp256k1.verify(signature.toUint8Array(), messageSha3Bytes, this.key.toUint8Array(), {
|
|
85
|
+
lowS: true,
|
|
86
|
+
prehash: false,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Verifies a signature against the UTF-8 encoding of `message`. The input
|
|
92
|
+
* is always treated as text — there is no hex/text heuristic. Pair with
|
|
93
|
+
* {@link Secp256k1PrivateKey.signText}.
|
|
94
|
+
*
|
|
95
|
+
* @param args - The arguments for verification.
|
|
96
|
+
* @param args.message - The text that was signed.
|
|
97
|
+
* @param args.signature - The signature to verify.
|
|
98
|
+
* @group Implementation
|
|
99
|
+
* @category Serialization
|
|
100
|
+
*/
|
|
101
|
+
verifyText(args: { message: string; signature: Secp256k1Signature }): boolean {
|
|
102
|
+
return this.verifyBytes({ message: TEXT_ENCODER.encode(args.message), signature: args.signature });
|
|
103
|
+
}
|
|
104
|
+
|
|
65
105
|
/**
|
|
66
106
|
* Verifies a Secp256k1 signature against the public key.
|
|
67
107
|
*
|
|
68
|
-
*
|
|
108
|
+
* @deprecated The polymorphic `message: HexInput` input is ambiguous — a
|
|
109
|
+
* bare even-length string of hex characters (e.g., `"cafe"`) is verified
|
|
110
|
+
* against the 2 bytes `[0xCA, 0xFE]`, not 4 UTF-8 text bytes. Use
|
|
111
|
+
* {@link verifyBytes} for `Uint8Array` input or {@link verifyText} for
|
|
112
|
+
* `string` input; both are unambiguous. See
|
|
113
|
+
* {@link convertSigningMessage} for the full legacy rule.
|
|
69
114
|
*
|
|
70
115
|
* @param args - The arguments for verifying the signature.
|
|
71
116
|
* @param args.message - The message that was signed.
|
|
@@ -77,9 +122,7 @@ export class Secp256k1PublicKey extends PublicKey {
|
|
|
77
122
|
const { message, signature } = args;
|
|
78
123
|
const messageToVerify = convertSigningMessage(message);
|
|
79
124
|
const messageBytes = Hex.fromHexInput(messageToVerify).toUint8Array();
|
|
80
|
-
|
|
81
|
-
const signatureBytes = signature.toUint8Array();
|
|
82
|
-
return secp256k1.verify(signatureBytes, messageSha3Bytes, this.key.toUint8Array(), { lowS: true, prehash: false });
|
|
125
|
+
return this.verifyBytes({ message: messageBytes, signature });
|
|
83
126
|
}
|
|
84
127
|
|
|
85
128
|
/**
|
|
@@ -308,11 +351,42 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
308
351
|
}
|
|
309
352
|
|
|
310
353
|
/**
|
|
311
|
-
*
|
|
312
|
-
* After calling this method
|
|
354
|
+
* Overwrites the underlying private-key byte buffer with random bytes and
|
|
355
|
+
* then zeros. After calling this method the key can no longer sign or
|
|
356
|
+
* derive a public key.
|
|
357
|
+
*
|
|
358
|
+
* SECURITY: This is a best-effort window-narrowing tool, NOT a true
|
|
359
|
+
* zeroization guarantee. In JavaScript, four classes of copies cannot be
|
|
360
|
+
* reached from user code and so survive `clear()`:
|
|
361
|
+
*
|
|
362
|
+
* 1. **JS string copies.** Any value previously produced by `toString()`,
|
|
363
|
+
* `toHexString()`, or `bcsToHex().toString()` is an immutable string
|
|
364
|
+
* in the heap. The language provides no API to overwrite string
|
|
365
|
+
* memory; it is reclaimed only when GC collects it.
|
|
366
|
+
* 2. **noble-curves internals.** The sign path inside `@noble/curves`
|
|
367
|
+
* expands the private key into scalar `BigInt` field elements, which
|
|
368
|
+
* are also immutable. Even if noble explicitly zeroed its own byte
|
|
369
|
+
* copies after use, the `BigInt` intermediates persist.
|
|
370
|
+
* 3. **JIT register / stack residue.** The engine may have held key
|
|
371
|
+
* bytes in CPU registers or on the engine stack during a sign call.
|
|
372
|
+
* There is no JS-visible way to scrub those.
|
|
373
|
+
* 4. **GC-relocated copies.** Generational GCs (V8, JSC) copy live
|
|
374
|
+
* objects between heap regions during minor/major collections. The
|
|
375
|
+
* `Uint8Array` we zeroed may have stale copies sitting in survivor
|
|
376
|
+
* space until the next cycle reclaims them.
|
|
313
377
|
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
378
|
+
* This method zeros the SDK's own `Uint8Array` (the most reachable
|
|
379
|
+
* copy), but downstream consumers should treat it as a hardening signal,
|
|
380
|
+
* not a guarantee. If you need real key-material hygiene, prefer a
|
|
381
|
+
* WASM-backed secp256k1 implementation that exposes explicit
|
|
382
|
+
* `memzero`, or hardware-backed keys (HSM / TPM / secure enclave).
|
|
383
|
+
* Note that `crypto.subtle` does NOT support secp256k1 on any major
|
|
384
|
+
* runtime, so non-extractable WebCrypto keys are not available for
|
|
385
|
+
* this curve.
|
|
386
|
+
*
|
|
387
|
+
* To minimize the size of the unreachable-copy set, avoid calling
|
|
388
|
+
* `toString()` / `toHexString()` on private keys at all in long-lived
|
|
389
|
+
* processes — the byte form is what gets cleared.
|
|
316
390
|
*
|
|
317
391
|
* @group Implementation
|
|
318
392
|
* @category Serialization
|
|
@@ -344,10 +418,54 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
344
418
|
return this.cleared;
|
|
345
419
|
}
|
|
346
420
|
|
|
421
|
+
/**
|
|
422
|
+
* Sign exactly the bytes of `message`. The input is interpreted as raw
|
|
423
|
+
* bytes regardless of what they encode. Pair with
|
|
424
|
+
* {@link Secp256k1PublicKey.verifyBytes}.
|
|
425
|
+
*
|
|
426
|
+
* The message is SHA3-256 hashed before signing (matching the Aptos-side
|
|
427
|
+
* Secp256k1 signing convention), and the produced signature is in
|
|
428
|
+
* canonical low-S form for malleability resistance.
|
|
429
|
+
*
|
|
430
|
+
* @param message - The exact bytes to sign.
|
|
431
|
+
* @returns The generated signature for the provided bytes.
|
|
432
|
+
* @throws Error if the private key has been cleared from memory.
|
|
433
|
+
* @group Implementation
|
|
434
|
+
* @category Serialization
|
|
435
|
+
*/
|
|
436
|
+
signBytes(message: Uint8Array): Secp256k1Signature {
|
|
437
|
+
this.ensureNotCleared();
|
|
438
|
+
const messageHashBytes = sha3_256(message);
|
|
439
|
+
const signature = secp256k1.sign(messageHashBytes, this.key.toUint8Array(), { lowS: true, prehash: false });
|
|
440
|
+
return new Secp256k1Signature(signature);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Sign the UTF-8 encoding of `message`. The input is always treated as
|
|
445
|
+
* text — there is no hex/text heuristic. Pair with
|
|
446
|
+
* {@link Secp256k1PublicKey.verifyText}.
|
|
447
|
+
*
|
|
448
|
+
* @param message - The text to sign.
|
|
449
|
+
* @returns The generated signature for the UTF-8 bytes of the provided text.
|
|
450
|
+
* @throws Error if the private key has been cleared from memory.
|
|
451
|
+
* @group Implementation
|
|
452
|
+
* @category Serialization
|
|
453
|
+
*/
|
|
454
|
+
signText(message: string): Secp256k1Signature {
|
|
455
|
+
return this.signBytes(TEXT_ENCODER.encode(message));
|
|
456
|
+
}
|
|
457
|
+
|
|
347
458
|
/**
|
|
348
459
|
* Sign the given message with the private key.
|
|
349
460
|
* This function generates a cryptographic signature for the provided message, ensuring the signature is canonical and non-malleable.
|
|
350
461
|
*
|
|
462
|
+
* @deprecated The polymorphic `message: HexInput` input is ambiguous — a
|
|
463
|
+
* bare even-length string of hex characters (e.g., `"cafe"`) is signed
|
|
464
|
+
* as the 2 bytes `[0xCA, 0xFE]`, not 4 UTF-8 text bytes. Use
|
|
465
|
+
* {@link signBytes} for `Uint8Array` input or {@link signText} for
|
|
466
|
+
* `string` input; both are unambiguous. See
|
|
467
|
+
* {@link convertSigningMessage} for the full legacy rule.
|
|
468
|
+
*
|
|
351
469
|
* @param message - A message in HexInput format to be signed.
|
|
352
470
|
* @returns Signature - The generated signature for the provided message.
|
|
353
471
|
* @throws Error if the private key has been cleared from memory.
|
|
@@ -355,12 +473,9 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
355
473
|
* @category Serialization
|
|
356
474
|
*/
|
|
357
475
|
sign(message: HexInput): Secp256k1Signature {
|
|
358
|
-
this.ensureNotCleared();
|
|
359
476
|
const messageToSign = convertSigningMessage(message);
|
|
360
|
-
const messageBytes = Hex.fromHexInput(messageToSign);
|
|
361
|
-
|
|
362
|
-
const signature = secp256k1.sign(messageHashBytes, this.key.toUint8Array(), { lowS: true, prehash: false });
|
|
363
|
-
return new Secp256k1Signature(signature);
|
|
477
|
+
const messageBytes = Hex.fromHexInput(messageToSign).toUint8Array();
|
|
478
|
+
return this.signBytes(messageBytes);
|
|
364
479
|
}
|
|
365
480
|
|
|
366
481
|
/**
|
|
@@ -393,6 +508,13 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
393
508
|
/**
|
|
394
509
|
* Get the private key as a string representation.
|
|
395
510
|
*
|
|
511
|
+
* SECURITY: This produces an immutable JS string containing the key
|
|
512
|
+
* material in hex. Strings cannot be zeroed by `clear()` (see the
|
|
513
|
+
* `clear()` JSDoc for the four classes of unreachable copies). Avoid
|
|
514
|
+
* calling this method on long-lived `Secp256k1PrivateKey` instances in
|
|
515
|
+
* processes where memory hygiene matters; prefer `toUint8Array()`,
|
|
516
|
+
* which returns a clearable `Uint8Array`.
|
|
517
|
+
*
|
|
396
518
|
* @returns string representation of the private key
|
|
397
519
|
* @throws Error if the private key has been cleared from memory.
|
|
398
520
|
* @group Implementation
|
|
@@ -406,6 +528,9 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
406
528
|
/**
|
|
407
529
|
* Get the private key as a hex string with the 0x prefix.
|
|
408
530
|
*
|
|
531
|
+
* SECURITY: Same caveat as `toString()` — the returned string is an
|
|
532
|
+
* immutable JS heap allocation that `clear()` cannot zero.
|
|
533
|
+
*
|
|
409
534
|
* @returns string representation of the private key.
|
|
410
535
|
* @throws Error if the private key has been cleared from memory.
|
|
411
536
|
*/
|
|
@@ -419,6 +544,9 @@ export class Secp256k1PrivateKey extends Serializable implements PrivateKey {
|
|
|
419
544
|
*
|
|
420
545
|
* [Read about AIP-80](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-80.md)
|
|
421
546
|
*
|
|
547
|
+
* SECURITY: Same caveat as `toString()` — produces an immutable JS string
|
|
548
|
+
* containing the key material; cannot be zeroed by `clear()`.
|
|
549
|
+
*
|
|
422
550
|
* @returns AIP-80 compliant string representation of the private key.
|
|
423
551
|
* @throws Error if the private key has been cleared from memory.
|
|
424
552
|
*/
|