Nostr WoT
NostrFirmadorNIP-46Clientes

Amber 6.6.6 corrige un analizador nostrconnect que estropeaba los secretos NIP-46

Un separador por defecto de Kotlin convertía un secreto base64 con relleno en un fragmento separado por comas, y NIP-46 obliga al cliente a rechazar exactamente eso.

Nostr WoT Newsroom

Artículo5 min de lectura

Elaborado por la Redacción de Nostr WoT a partir de las fuentes primarias citadas, y publicado automáticamente sin revisión humana individual.

Amber 6.6.6 corrige un analizador nostrconnect que estropeaba los secretos NIP-46

Amber 6.6.6 se publicó el 28 de septiembre de 2026. Su primera entrada del registro de cambios repara un fallo de análisis en el tratamiento que el firmador hace de los tokens de conexión nostrconnect://: un secreto de conexión que contenía un carácter = regresaba alterado en la respuesta connect, y el cliente solicitante rechazaba la conexión.

La incidencia #526, abierta el 23 de septiembre, expone el caso concreto. Un cliente ofrece un token con la forma nostrconnect://715ad7d1...?relay=wss%3A%2F%2Frelay.primal.net&secret=XQUdha4rjh_gjAgHN8X5yg==&perms=.... El secreto es base64 con su relleno intacto. Amber devolvía XQUdha4rjh_gjAgHN8X5yg, , en su lugar. La incidencia indica que las aplicaciones construidas sobre NDK, citando Nmail como ejemplo, generaban secretos con esta forma.

La especificación convierte el fallo en total, no en cosmético

NIP-46 describe secret como un parámetro de consulta obligatorio, «una cadena aleatoria corta que el remote-signer debería devolver como campo result de su respuesta». Después establece que el valor «MUST be provided to avoid connection spoofing» y que el cliente «MUST validate the secret returned by connect response».

Ese requisito explica por qué una sola secuencia de caracteres alterada termina el intercambio. El cliente no puede aceptar una coincidencia aproximada ni recurrir a confiar en la clave que responde. Compara lo que generó con lo que recibió, ve una cadena distinta y se detiene. El emparejamiento nunca se completa y, desde el lado del usuario, el firmador sencillamente no conecta.

La especificación no impone ninguna restricción sobre el alfabeto del secreto. «Una cadena aleatoria corta» admite base64, y el relleno de base64 es =. Un cliente que producía base64 con relleno se ajustaba a la especificación, y era el firmador quien tenía que aceptarlo.

Un separador por defecto, dos veces

La causa es acotada y queda documentada en el diff. joinToString de Kotlin usa ", " como separador por defecto. El código anterior dividía cada parámetro de consulta en cada =, descartaba el primer elemento y volvía a unir el resto sin pasar un separador:

kotlin
val internalSplit = it.split("=")
val paramName = internalSplit.first()
val json = internalSplit.mapIndexedNotNull { index, s ->
    if (index == 0) null else s
}.joinToString { data -> data }

Aplicado a secret=XQUdha4rjh_gjAgHN8X5yg==, la división produce cuatro elementos, los dos últimos vacíos. Unir los tres finales con ", " da XQUdha4rjh_gjAgHN8X5yg, , . Dos defectos se acumulan en una línea: los caracteres de relleno se consumen como delimitadores y, en su lugar, se inserta un separador que nadie pretendía.

La versión 6.6.6 sustituye todo el bloque por una función auxiliar con nombre que divide una sola vez:

kotlin
fun splitParam(param: String): Pair<String, String> =
    param.substringBefore("=") to param.substringAfter("=", "")

La misma publicación corrige el mismo error en un segundo punto de llamada. El token se divide por ? para separar la clave pública del cliente de la cadena de consulta, y los fragmentos restantes se volvían a unir con split.drop(1).joinToString { it }. Ahora se lee joinToString("") { it }. El primer punto rompía todos los secretos con relleno; el segundo solo afecta a un token cuya cadena de consulta lleve un ? literal, pero es el mismo valor por defecto y la misma clase de error.

Un nuevo archivo de pruebas, NostrConnectUtilsTest.kt, añade siete casos. Cuatro cubren valores que contienen =, incluido el secreto con relleno de la incidencia, un valor con = en medio, una URL de relay codificada en porcentaje y una lista perms. Tres fijan las entradas degeneradas para que la reparación no las altere: un parámetro sin =, uno con valor vacío y la cadena vacía.

El resto de la publicación

Seis commits y dieciséis archivos separan la 6.6.5 de la 6.6.6. El resto es presentación y enrutado más que protocolo.

Tres entradas del registro de cambios tratan sobre el contraste. Se corrigen el texto y los iconos blancos sobre superficies ámbar claras en tema oscuro, en el botón de acción flotante de Edit Relays, en los botones de icono para añadir relays y en los chips de filtro seleccionados de la pantalla de comentarios. El icono de estado de Tor y proxy de la barra superior, descrito como casi invisible en tema claro, ahora usa colores adaptados al tema en ambos casos, y el icono de reconexión de relay se ajusta al recuento de relays contiguo.

La última entrada cambia el destino de los comentarios. Las incidencias de comentarios se publican en los relays anunciados en el anuncio del repositorio de Amber en lugar de en un relay fijo en el código, con vuelta al comportamiento anterior cuando el anuncio no se puede obtener. Los tiempos de espera sobre Tor se alargaron para que un relay lento pueda confirmar la publicación.

Qué establecen los artefactos

La versión 6.6.6 es una publicación de GitHub con recursos para Android y un manifiesto de sumas de verificación firmado, etiquetada en el commit fc2e0de5. El cambio del analizador, la función auxiliar, el segundo punto de llamada y los siete casos de prueba son visibles en la comparación con 6.6.5, así que el registro de cambios y el diff coinciden en esta publicación.

Eso establece lo que el código hace ahora. No establece que una instalación concreta se haya actualizado, y los canales de tienda y de repositorio avanzan a su propio ritmo. Quien tuviera un cliente que seguía fallando su comprobación del secreto debería confirmar la versión que realmente se ejecuta en el dispositivo.

Fuentes

Toda afirmación de este artículo enlaza a una fuente primaria.

  1. Publicación de Amber v6.6.6 — greenart7c3/Amber (28 de septiembre de 2026)
  2. Incidencia #526: el analizador de nostrconnect:// corrompe valores que contienen = — greenart7c3/Amber (23 de septiembre de 2026)
  3. Comparación v6.6.5...v6.6.6 — greenart7c3/Amber (28 de septiembre de 2026)
  4. NIP-46 Nostr Remote Signing — nostr-protocol/nips (28 de septiembre de 2026)

Mantente al día

Recibe noticias sobre las versiones publicadas de Nostr WoT, nuevas funciones e integraciones.

Recibirás el boletín en español.

Guardamos tu dirección de correo electrónico y tu idioma preferido para enviarte el boletín.

Boletines