diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt index 093121ae5..2b057dc67 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt @@ -168,18 +168,20 @@ object Bech32 { bech32: String, noChecksum: Boolean = false, ): Triple, Encoding> { + val filteredBech32 = bech32.filter { it.code in 33..126 } + var pos = 0 - bech32.forEachIndexed { index, char -> + filteredBech32.forEachIndexed { index, char -> require(char.code in 33..126) { "invalid character $char" } if (char == '1') { pos = index } } - val hrp = bech32.take(pos).lowercase() // strings must be lower case + val hrp = filteredBech32.take(pos).lowercase() // strings must be lower case require(hrp.length in 1..83) { "hrp must contain 1 to 83 characters" } - val data = Array(bech32.length - pos - 1) { map[bech32[pos + 1 + it].code] } + val data = Array(filteredBech32.length - pos - 1) { map[filteredBech32[pos + 1 + it].code] } return if (noChecksum) { Triple(hrp, data, Encoding.Beck32WithoutChecksum) diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt b/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt index 1edbd57e0..343072320 100644 --- a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt +++ b/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt @@ -21,6 +21,7 @@ package com.vitorpamplona.quartz.nip19Bech32 import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip19Bech32.bech32.bechToBytes import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile @@ -428,4 +429,15 @@ class NIP19ParserTest { nevent, ) } + + @Test + fun decodeBech32WithInvisibleCharacter() { + val bomChar = '\uFEFF' + val withBom = bomChar + "nsec1lfkarc7439n4l3uahr45ej8mrjc39dd879t0ps355550dj8j9uzs3rnw24" + + assertEquals( + "nsec1lfkarc7439n4l3uahr45ej8mrjc39dd879t0ps355550dj8j9uzs3rnw24", + withBom.bechToBytes().toNsec(), + ) + } }