diff --git a/src/chains/stellar/meta-address.ts b/src/chains/stellar/meta-address.ts index ccbcf77..0c9e533 100644 --- a/src/chains/stellar/meta-address.ts +++ b/src/chains/stellar/meta-address.ts @@ -77,6 +77,13 @@ export function decodeStealthMetaAddress(metaAddress: string): StealthMetaAddres ); } + if (!/^[0-9a-fA-F]{128}$/.test(hex)) { + throw new InvalidMetaAddressError( + metaAddress, + 'Invalid stealth meta-address hex. Expected 128 hexadecimal chars', + ); + } + const spendingPubKey = hexToBytes(hex.slice(0, 64)); const viewingPubKey = hexToBytes(hex.slice(64)); diff --git a/test/chains/stellar/meta-address.test.ts b/test/chains/stellar/meta-address.test.ts index f6520a3..d38e584 100644 --- a/test/chains/stellar/meta-address.test.ts +++ b/test/chains/stellar/meta-address.test.ts @@ -1,4 +1,5 @@ import { describe, test, expect } from 'vitest'; +import * as fc from 'fast-check'; import { deriveStealthKeys } from '../../../src/chains/stellar/keys'; import { encodeStealthMetaAddress, @@ -37,6 +38,37 @@ describe('meta-address', () => { ); }); + test.each(['g', 'G', '-', ' ', '\u00e9'])('rejects non-hex payload character %j', (character) => { + const keys = deriveStealthKeys(testSig); + const meta = encodeStealthMetaAddress(keys.spendingPubKey, keys.viewingPubKey); + const malformed = `${meta.slice(0, 7)}${character}${meta.slice(8)}`; + + expect(() => decodeStealthMetaAddress(malformed)).toThrow( + 'Invalid stealth meta-address hex. Expected 128 hexadecimal chars', + ); + }); + + test('rejects invalid hex characters at every payload position', () => { + const keys = deriveStealthKeys(testSig); + const meta = encodeStealthMetaAddress(keys.spendingPubKey, keys.viewingPubKey); + + fc.assert( + fc.property( + fc.integer({ min: 0, max: 127 }), + fc.constantFrom('g', 'G', 'z', '-', ' ', '\u00e9'), + (index, character) => { + const payloadIndex = 7 + index; + const malformed = `${meta.slice(0, payloadIndex)}${character}${meta.slice(payloadIndex + 1)}`; + + expect(() => decodeStealthMetaAddress(malformed)).toThrow( + 'Invalid stealth meta-address hex. Expected 128 hexadecimal chars', + ); + }, + ), + { numRuns: 256 }, + ); + }); + test('encode rejects wrong key length', () => { const shortKey = new Uint8Array(31); const keys = deriveStealthKeys(testSig);