Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A breaking change will get clearly marked in this log.
### Changed
- `scValToNative` converts an `scvExecutableTag` to its tag: a string when the bytes are valid UTF-8, otherwise the raw bytes (same rule as `scvString` and `scvSymbol`) ([#1577](https://github.com/stellar/js-stellar-sdk/pull/1577)).
- `buildInvocationTree` renders CAP-85 external-executable creations instead of throwing. `CreateInvocation.type` gains an `"external"` case, whose details live in a new `external` field (`owner`, `tag`, `address`, `salt`, and `constructorArgs` for `CREATE_CONTRACT_V2`). `tag` is `string | Uint8Array` — an executable tag is an unbounded `SCString`, so a binary one is returned as raw bytes rather than lossily decoded ([#1577](https://github.com/stellar/js-stellar-sdk/pull/1577)).
- `StrKey.decode*` and the underlying `decodeCheck` now validate the encoded string's length against the requested strkey type before decoding it. Two consequences: a long attacker-supplied string is rejected up front instead of driving a full base32 decode plus canonical re-encode, and a strkey whose payload is the wrong size for its type now throws instead of returning a mis-sized buffer (previously, a 37-byte payload encoded as an `ed25519PublicKey` strkey decoded to 37 bytes and only failed later, if at all). Inputs that were already invalid may now report a length error rather than a checksum or version-byte error.
- `contract.Client.from` and `rpc.Server.getContractWasmByContractId` support contracts created from a CAP-85 external executable reference. The reference names an owner contract and a tag; the owner holds a persistent contract data entry keyed by that tag whose value is the Wasm hash, so both methods resolve that entry and then load the Wasm as usual ([#1577](https://github.com/stellar/js-stellar-sdk/pull/1577)).

## [v16.2.0](https://github.com/stellar/js-stellar-sdk/compare/v16.1.0...v16.2.0)
Expand Down
56 changes: 28 additions & 28 deletions docs/reference/core-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ class StrKey {
}
```

**Source:** [src/base/strkey.ts:55](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L55)
**Source:** [src/base/strkey.ts:74](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L74)

### `new StrKey()`

Expand All @@ -482,7 +482,7 @@ constructor();
static types: Record<string, VersionByteName>;
```

**Source:** [src/base/strkey.ts:56](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L56)
**Source:** [src/base/strkey.ts:75](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L75)

### `StrKey.decodeClaimableBalance(address)`

Expand All @@ -496,7 +496,7 @@ static decodeClaimableBalance(address: string): Uint8Array;

- **`address`** — `string` (required) — balance to decode

**Source:** [src/base/strkey.ts:246](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L246)
**Source:** [src/base/strkey.ts:265](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L265)

### `StrKey.decodeContract(address)`

Expand All @@ -510,7 +510,7 @@ static decodeContract(address: string): Uint8Array;

- **`address`** — `string` (required) — address to decode

**Source:** [src/base/strkey.ts:219](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L219)
**Source:** [src/base/strkey.ts:238](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L238)

### `StrKey.decodeEd25519PublicKey(data)`

Expand All @@ -527,7 +527,7 @@ static decodeEd25519PublicKey(data: string): Uint8Array;

- **`data`** — `string` (required) — "G..." (or "M...") key representation to decode

**Source:** [src/base/strkey.ts:75](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L75)
**Source:** [src/base/strkey.ts:94](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L94)

### `StrKey.decodeEd25519SecretSeed(address)`

Expand All @@ -541,7 +541,7 @@ static decodeEd25519SecretSeed(address: string): Uint8Array;

- **`address`** — `string` (required) — data to decode

**Source:** [src/base/strkey.ts:102](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L102)
**Source:** [src/base/strkey.ts:121](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L121)

### `StrKey.decodeLiquidityPool(address)`

Expand All @@ -555,7 +555,7 @@ static decodeLiquidityPool(address: string): Uint8Array;

- **`address`** — `string` (required) — address to decode

**Source:** [src/base/strkey.ts:273](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L273)
**Source:** [src/base/strkey.ts:292](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L292)

### `StrKey.decodeMed25519PublicKey(address)`

Expand All @@ -569,7 +569,7 @@ static decodeMed25519PublicKey(address: string): Uint8Array;

- **`address`** — `string` (required) — data to decode

**Source:** [src/base/strkey.ts:129](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L129)
**Source:** [src/base/strkey.ts:148](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L148)

### `StrKey.decodePreAuthTx(address)`

Expand All @@ -583,7 +583,7 @@ static decodePreAuthTx(address: string): Uint8Array;

- **`address`** — `string` (required) — data to decode

**Source:** [src/base/strkey.ts:156](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L156)
**Source:** [src/base/strkey.ts:175](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L175)

### `StrKey.decodeSha256Hash(address)`

Expand All @@ -597,7 +597,7 @@ static decodeSha256Hash(address: string): Uint8Array;

- **`address`** — `string` (required) — data to decode

**Source:** [src/base/strkey.ts:174](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L174)
**Source:** [src/base/strkey.ts:193](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L193)

### `StrKey.decodeSignedPayload(address)`

Expand All @@ -611,7 +611,7 @@ static decodeSignedPayload(address: string): Uint8Array;

- **`address`** — `string` (required) — address to decode

**Source:** [src/base/strkey.ts:192](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L192)
**Source:** [src/base/strkey.ts:211](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L211)

### `StrKey.encodeClaimableBalance(data)`

Expand All @@ -625,7 +625,7 @@ static encodeClaimableBalance(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:237](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L237)
**Source:** [src/base/strkey.ts:256](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L256)

### `StrKey.encodeContract(data)`

Expand All @@ -639,7 +639,7 @@ static encodeContract(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:210](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L210)
**Source:** [src/base/strkey.ts:229](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L229)

### `StrKey.encodeEd25519PublicKey(data)`

Expand All @@ -653,7 +653,7 @@ static encodeEd25519PublicKey(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — raw data to encode

**Source:** [src/base/strkey.ts:63](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L63)
**Source:** [src/base/strkey.ts:82](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L82)

### `StrKey.encodeEd25519SecretSeed(data)`

Expand All @@ -667,7 +667,7 @@ static encodeEd25519SecretSeed(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:93](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L93)
**Source:** [src/base/strkey.ts:112](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L112)

### `StrKey.encodeLiquidityPool(data)`

Expand All @@ -681,7 +681,7 @@ static encodeLiquidityPool(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:264](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L264)
**Source:** [src/base/strkey.ts:283](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L283)

### `StrKey.encodeMed25519PublicKey(data)`

Expand All @@ -695,7 +695,7 @@ static encodeMed25519PublicKey(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:120](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L120)
**Source:** [src/base/strkey.ts:139](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L139)

### `StrKey.encodePreAuthTx(data)`

Expand All @@ -709,7 +709,7 @@ static encodePreAuthTx(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:147](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L147)
**Source:** [src/base/strkey.ts:166](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L166)

### `StrKey.encodeSha256Hash(data)`

Expand All @@ -723,7 +723,7 @@ static encodeSha256Hash(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:165](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L165)
**Source:** [src/base/strkey.ts:184](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L184)

### `StrKey.encodeSignedPayload(data)`

Expand All @@ -737,7 +737,7 @@ static encodeSignedPayload(data: Uint8Array): string;

- **`data`** — `Uint8Array` (required) — data to encode

**Source:** [src/base/strkey.ts:183](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L183)
**Source:** [src/base/strkey.ts:202](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L202)

### `StrKey.getVersionByteForPrefix(address)`

Expand All @@ -752,7 +752,7 @@ static getVersionByteForPrefix(address: string): VersionByteName | undefined;

- **`address`** — `string` (required) — the strkey address to check

**Source:** [src/base/strkey.ts:292](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L292)
**Source:** [src/base/strkey.ts:311](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L311)

### `StrKey.isValidClaimableBalance(address)`

Expand All @@ -766,7 +766,7 @@ static isValidClaimableBalance(address: string): boolean;

- **`address`** — `string` (required) — balance to check

**Source:** [src/base/strkey.ts:255](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L255)
**Source:** [src/base/strkey.ts:274](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L274)

### `StrKey.isValidContract(address)`

Expand All @@ -780,7 +780,7 @@ static isValidContract(address: string): boolean;

- **`address`** — `string` (required) — signer key to check

**Source:** [src/base/strkey.ts:228](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L228)
**Source:** [src/base/strkey.ts:247](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L247)

### `StrKey.isValidEd25519PublicKey(publicKey)`

Expand All @@ -794,7 +794,7 @@ static isValidEd25519PublicKey(publicKey: string): boolean;

- **`publicKey`** — `string` (required) — public key to check

**Source:** [src/base/strkey.ts:84](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L84)
**Source:** [src/base/strkey.ts:103](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L103)

### `StrKey.isValidEd25519SecretSeed(seed)`

Expand All @@ -808,7 +808,7 @@ static isValidEd25519SecretSeed(seed: string): boolean;

- **`seed`** — `string` (required) — seed to check

**Source:** [src/base/strkey.ts:111](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L111)
**Source:** [src/base/strkey.ts:130](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L130)

### `StrKey.isValidLiquidityPool(address)`

Expand All @@ -822,7 +822,7 @@ static isValidLiquidityPool(address: string): boolean;

- **`address`** — `string` (required) — pool to check

**Source:** [src/base/strkey.ts:282](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L282)
**Source:** [src/base/strkey.ts:301](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L301)

### `StrKey.isValidMed25519PublicKey(publicKey)`

Expand All @@ -836,7 +836,7 @@ static isValidMed25519PublicKey(publicKey: string): boolean;

- **`publicKey`** — `string` (required) — public key to check

**Source:** [src/base/strkey.ts:138](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L138)
**Source:** [src/base/strkey.ts:157](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L157)

### `StrKey.isValidSignedPayload(address)`

Expand All @@ -850,7 +850,7 @@ static isValidSignedPayload(address: string): boolean;

- **`address`** — `string` (required) — signer key to check

**Source:** [src/base/strkey.ts:201](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L201)
**Source:** [src/base/strkey.ts:220](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/strkey.ts#L220)

## sign

Expand Down
77 changes: 36 additions & 41 deletions src/base/strkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ function hasVersionByteName(
return Object.prototype.hasOwnProperty.call(versionBytes, versionByteName);
}

/** Legal encoded (strkey string) length range for a strkey type. */
function encodedLengthRange(name: VersionByteName): [number, number] {
switch (name) {
case "ed25519PublicKey":
case "ed25519SecretSeed":
case "preAuthTx":
case "sha256Hash":
case "contract":
case "liquidityPool":
return [56, 56];
case "claimableBalance":
return [58, 58];
case "med25519PublicKey":
return [69, 69];
case "signedPayload":
return [56, 165];
Comment thread
Ryang-21 marked this conversation as resolved.
}
}

/**
* StrKey is a helper class that allows encoding and decoding Stellar keys
* to/from strings, i.e. between their binary (Uint8Array, xdr.PublicKey, etc.) and
Expand Down Expand Up @@ -314,43 +333,9 @@ function isValid(versionByteName: string, encoded: unknown): boolean {
return false;
}

// basic length checks on the strkey lengths
switch (versionByteName) {
case "ed25519PublicKey": // falls through
case "ed25519SecretSeed": // falls through
case "preAuthTx": // falls through
case "sha256Hash": // falls through
case "contract": // falls through
case "liquidityPool":
if (encoded.length !== 56) {
return false;
}
break;

case "claimableBalance":
if (encoded.length !== 58) {
return false;
}
break;

case "med25519PublicKey":
if (encoded.length !== 69) {
return false;
}
break;

case "signedPayload":
if (encoded.length < 56 || encoded.length > 165) {
return false;
}
break;

default:
return false;
}

let decoded: Uint8Array;
try {
// encoded-length bounds are enforced by `decodeCheck`
decoded = decodeCheck(versionByteName, encoded);
} catch {
return false;
Expand Down Expand Up @@ -399,6 +384,22 @@ export function decodeCheck(
throw new TypeError("encoded argument must be of type String");
}

if (!hasVersionByteName(versionByteName)) {
throw new Error(
`${versionByteName} is not a valid version byte name. ` +
`Expected one of ${Object.keys(versionBytes).join(", ")}`,
);
}

const [minLen, maxLen] = encodedLengthRange(versionByteName);
if (encoded.length < minLen || encoded.length > maxLen) {
throw new Error(
`invalid encoded string length: expected ` +
`${minLen === maxLen ? minLen : `${minLen}-${maxLen}`}, ` +
`got ${encoded.length}`,
);
}

const decoded = fromBase32(encoded, { padding: false });
const versionByte = decoded[0];
const payload = decoded.slice(0, -2);
Expand All @@ -409,12 +410,6 @@ export function decodeCheck(
throw new Error("invalid encoded string");
}

if (!hasVersionByteName(versionByteName)) {
throw new Error(
`${versionByteName} is not a valid version byte name. ` +
`Expected one of ${Object.keys(versionBytes).join(", ")}`,
);
}
const expectedVersion = versionBytes[versionByteName];

if (versionByte !== expectedVersion) {
Expand Down
Loading
Loading