Saltar al contenido principal

Revisiones de seguridad

Antes de su lanzamiento, el código fuente de BitTool Signer 1.0.0 pasó por dos revisiones de seguridad asistidas por IA en cada plataforma, cada una por separado. Los cuatro informes se publican íntegros más abajo. Ninguna encontró problemas de gravedad crítica o alta. Las revisiones de iPhone encontraron un problema de gravedad baja cada una. Las de Android encontraron problemas de gravedad media: cuatro siguen abiertos en la versión publicada de Android 1.0.0, y tres de ellos están en el motor de firma que comparten ambas apps.

Lee primero los límites
  • Ninguna es una auditoría de una empresa de seguridad, y en ninguna participó un auditor humano.
  • Las revisiones Opus 5 y Opus 5.5 provienen de la misma familia de modelos que escribió o modificó una parte importante del código revisado. Los informes dicen que no son una certificación ni una atestación de terceros.
  • Las revisiones GPT-6 Astra se describen como revisiones de ingeniería asistidas por IA preparadas para el propietario del proyecto, no como una certificación de una firma auditora ni una aprobación humana.
  • Ambos informes de Android recomiendan corregir sus hallazgos de gravedad media abiertos antes de que la app proteja carteras valiosas. BitTool Signer para Android 1.0.0 se publicó con ellos abiertos; consulta todos los hallazgos.
  • Todavía no se ha hecho una auditoría independiente de terceros. Los informes la señalan, junto con pruebas en dispositivos reales y pruebas de ida y vuelta con carteras de terceros, como trabajo pendiente antes de guardar fondos importantes.

BitTool Signer para iPhone​

Los dos informes​

Opus 5GPT-6 Astra
Fecha19 de octubre de 202618 de octubre de 2026 (informe BTS-SEC-2026-1018-R3)
Código revisadoTag v1.0.0, commit f621372Árbol de trabajo del 18 de octubre: commit 3d706b7 más 59 archivos modificados y una prueba nueva
Motor revisado (signer.js, SHA-256)6933d0d8…f210776933d0d8…f21077
MétodoRevisión del código fuente línea a línea (3546 líneas de JavaScript y 11 858 de Swift), 11 sondeos de ataque, prueba de mutación de 4000 casos sobre la entrada QR, conjuntos de pruebas, recompilación en un entorno limpioRevisión del código fuente por subsistemas, comparación con la ronda anterior, datos de prueba (fixtures) independientes de Bitcoin y Solana, prueba de mutación de 1509 casos, conjuntos de pruebas, compilación reproducible, avisos de seguridad de las dependencias
Pruebas ejecutadas210 del motor, 168 nativas210 del motor, 177 nativas y de interfaz
Resultado0 Críticas · 0 Altas · 0 Medias · 1 Baja · 3 Informativas0 Críticas · 0 Altas · 0 Medias · 1 Baja · 4 observaciones
IndependenciaAutorrevisión del autor de buena parte del códigoAsistida por IA, preparada para el propietario del proyecto

Las dos revisiones examinaron el mismo archivo del motor que incluye BitTool Signer 1.0.0: en él están todos los analizadores de transacciones, todas las reglas de riesgo y todos los planes de firma. El resto de la app (interfaz, Keychain, almacenamiento) se revisó leyendo el código fuente en Swift.

Todos los hallazgos​

IDGravedadHallazgoEstado en 1.0.0
BTS-OP5-01BajaLa aceptación de los riesgos altos solo se exige en la interfaz. El motor exige una aceptación explícita para las solicitudes parcialmente decodificadas y opacas, pero no para las de alto riesgo totalmente decodificadas (aprobaciones ilimitadas, setApprovalForAll, cambios de permisos de Safe, quemas de tokens). La app desactiva Sign (firmar) hasta que se marca la casilla, así que un atacante no puede llegar a esta situación en 1.0.0; importa porque el motor es la parte que los usuarios pueden verificar por su hash.Abierto. El informe recomienda añadir la comprobación al motor en 1.0.1.
R3-01BajaResumen de Bitcoin para una quema con cambio. En una transacción con una salida OP_RETURN de importe distinto de cero y un cambio verificado, el resumen breve de la pantalla de resultado y de Activity (actividad) dice «Every output returns to your wallet» (todas las salidas vuelven a tu cartera). La propia pantalla de firma muestra correctamente la quema, su importe y el riesgo Alto.Abierto (el motor incluido en 1.0.0 es el que se revisó).
BTS-OP5-02InformativaUna clave de localización de Activity se construye a partir de la salida del motor, y SwiftUI la representa como Markdown. Todos los valores que puede contener hoy son etiquetas fijas, así que es un problema latente.Abierto, latente.
BTS-OP5-03InformativaLa KDF de contraseñas de la bóveda (PBKDF2-HMAC-SHA256, 600 000 iteraciones) no es memory-hard. Lo mitiga la segunda capa de cifrado bajo una clave del Keychain vinculada al dispositivo: un archivo de bóveda copiado, por sí solo, ni siquiera se puede atacar.Aceptado; se sugiere Argon2id para un futuro formato de bóveda.
BTS-OP5-04InformativaEl material de claves Ed25519 intermedio de la derivación de Solana no se borra explícitamente; el control real es descartar el contexto de JavaScript.Abierto, limitación inherente.
O-01InformativaDurante la importación, una búsqueda lenta de «¿ya está aquí esta cartera?» puede terminar después de que se edite la frase y ofrecer restablecer la contraseña de la cartera anterior. El propio restablecimiento vuelve a derivar la identidad de la cartera y rechaza la cartera equivocada; no se modifica ninguna bóveda.Abierto en la fecha del informe.
O-02InformativaLos resúmenes de Safe y Solana proceden de decodificadores acotados, no de ejecutar la transacción. El estado actual del contrato no se conoce sin conexión.Por diseño; se indica en la pantalla de revisión.
O-03InformativaEn Swift y JavaScript no se puede garantizar la puesta a cero completa de la memoria; no se probaron el dispositivo físico, el generador aleatorio del sistema operativo ni el binario distribuido.Limitación.
O-04InformativaSeis avisos de seguridad en dependencias exclusivas de desarrollo (3 moderados, 3 bajos). Los paquetes afectados no están en el motor incluido en la app.Mantenimiento.

Los dos informes también volvieron a comprobar los hallazgos de dos rondas de revisión anteriores, entre ellos uno de gravedad Alta (el resumen de las transacciones multifirma de Safe con DELEGATECALL y MultiSend anidado) y varios de gravedad Baja en los resúmenes de comisiones de Bitcoin y de quemas de Solana, y confirmaron que estaban corregidos. Opus 5 señala además, como una propiedad del protocolo TRON y no como un defecto, que las firmas de TRON no llevan ningún identificador de red; la app lo indica.

Encontrado después en el motor compartido​

BitTool Signer para iPhone 1.0.0 incluye el motor con SHA-256 6933d0d8…f21077. La revisión GPT-6 Astra de la app de Android reprodujo sus hallazgos sobre el motor exactamente con este archivo, y el código de Bitcoin, EVM y TRON detrás de los hallazgos de Opus 5.5 es idéntico en él. Por eso estos hallazgos del motor también se aplican a iPhone 1.0.0:

IDGravedadQué significa en iPhone 1.0.0
BTS-02, BTS-07MediaUna quema, un cambio de autoridad o una delegación de Solana enviados junto con una transferencia diminuta se resumen como esa transferencia. Las advertencias de los detalles y la confirmación del riesgo se mantienen.
BTS-08MediaEl cambio de Bitcoin se acepta en cualquier índice de dirección de los perfiles de firma única de la cartera, incluidos índices que una cartera de solo lectura nunca revisará.
BTS-09Baja–MediaEl resumen guardado omite la moneda nativa enviada con una llamada a un contrato EVM o TRON desconocido. La tarjeta de revisión sí la muestra.

R3-01, más arriba, es el mismo defecto que BTS-04 de Android, que el motor de Android corrige. El informe de Opus 5.5 recomienda corregir los demás en el motor compartido, y la corrección llega entonces a ambas apps.

Qué confirmaron las revisiones​

ÁreaConfirmadoDetalles
FirmaEn las compilaciones Release, la única forma de firmar es mediante un plan fijo. Seis comprobaciones independientes vinculan la firma a la solicitud revisada, a la cartera del plan y a la clave aprobada, y el motor vuelve a derivarlo todo a partir de la semilla descifrada antes de firmar. Confirmado mediante ejecución.Antes de firmar
AleatoriedadLas frases de recuperación proceden de SecRandomCopyBytes; un error detiene la creación sin ninguna alternativa. crypto.getRandomValues y Math.random del motor se conectan a la misma fuente.Generación de la semilla
Almacenamiento de clavesDos capas AES-GCM con cabeceras autenticadas, una clave del Keychain exclusiva del dispositivo y una limitación de los intentos fallidos que se mantiene tras reiniciar.Almacenamiento de claves
RechazosSe cumplen todos los rechazos que describe esta documentación: SIGHASH_NONE/SINGLE/ANYONECANPAY, entradas SegWit v0 sin la transacción anterior, tablas de búsqueda de direcciones de Solana, EIP-7702, transacciones blob, eth_sign sobre un hash sin procesar y chain IDs no compatibles.Límites y errores
Entrada no fiable5509 entradas QR, CBOR, PSBT y JSON mutadas entre las dos revisiones: ninguna se aceptó siendo no válida y no hubo ninguna excepción no controlada.UR y CBOR
Sin conexiónNo se enlaza ni CFNetwork ni Network.framework, y el puente de JavaScript no expone ninguna API de red.Modelo de seguridad
Cadena de suministroEl motor se recompila byte a byte a partir del tag; las dependencias de ejecución están fijadas a versiones exactas; la auditoría de las dependencias de producción no notificó ninguna vulnerabilidad.Más abajo

Qué no cubrieron​

Las pruebas en dispositivos físicos (inyección de fallos, volcados de memoria, canales laterales), el generador aleatorio del sistema operativo y el funcionamiento interno del Secure Enclave, la procedencia del binario de la App Store más allá del archivo del motor, las transacciones en redes reales, las pruebas de ida y vuelta con carteras de terceros, una auditoría completa de las dependencias criptográficas, la revisión lingüística de los 21 idiomas de la interfaz y la verificación formal. Un conjunto de pruebas superado cubre los casos que prueba, no todas las transacciones ni todos los dispositivos.

Verifica el motor por tu cuenta​

El ejecutable de la App Store no se puede reproducir byte a byte (Apple lo vuelve a firmar y lo cifra), pero el motor es un recurso sin cifrar que se puede comparar. Compílalo a partir del tag:

git clone https://github.com/bitbill/bittool-signer-ios
cd bittool-signer-ios && git checkout v1.0.0
cd engine && npm ci --ignore-scripts && npm run build
shasum -a 256 ../BitToolSigner/Resources/signer.js
# 6933d0d8a6f60faa8222506ac0bd7eef80eb884c9f73e31e9f354b4740f21077 (1,181,026 bytes)

Después compáralo con el archivo de la app que tienes instalada: descarga la app como .ipa con Apple Configurator, descomprímela y calcula el hash de Payload/BitToolSigner.app/signer.js. El procedimiento completo, incluido el punto en el que termina la verificación, está en el archivo Reproducible-Build.md del repositorio.

BitTool Signer para Android​

Los dos informes​

Opus 5.5GPT-6 Astra
Fecha25 de octubre de 202624 de octubre de 2026
Código revisadoVersión publicada 1.0.0 (código de versión 1000001): commit de código 71af693, registro de publicación 62996b8Commit e7e71fb, anterior a la publicación: una nueva auditoría de los cambios desde la referencia anterior bb1e656
Motor revisado (signer.js, SHA-256)4b371759…00fa196933d0d8…f21077, el motor que incluye iPhone 1.0.0
MétodoRevisión del código fuente en cinco áreas, cada una seguida de principio a fin; cada hallazgo comprobado de nuevo en el código; reproducciones del motor con datos sintéticos; revisión de dependencias y artefactosRevisión del código modificado y de quienes lo llaman, verificación de tres correcciones, reproducciones del motor con el paquete confirmado, comprobaciones automáticas de regresión
Pruebas ejecutadas2.075 pruebas de la app, 217 del motor y el script de verificación de la publicación, 25 de 251.616 pruebas de Android; 210 del motor, una fallida y otra que pasó sin ejecutarse (BTS-06)
Resultado0 críticos · 0 altos · 4 medios (uno calificado Baja–Media) · 9 bajos · notas informativas0 críticos · 0 altos · abiertos: 1 medio, 1 bajo, 1 de validación · 3 cerrados
RecomendaciónCorregir BTS-07, BTS-08 y BTS-10 antes de un lanzamiento general que proteja carteras valiosasPosponer, en esa revisión, el lanzamiento general para carteras valiosas
IndependenciaLa misma familia de modelos escribió gran parte del código revisadoAsistida por IA; no se modificó código de producción

Ambas revisiones examinaron la app de Android completa: los módulos de Kotlin, el anfitrión nativo (JNI sobre QuickJS y el PBKDF2 nativo) y el motor de firma compartido con iPhone.

Todos los hallazgos​

Opus 5.5 revisó el código publicado, así que estos son los hallazgos de BitTool Signer para Android 1.0.0.

IDGravedadHallazgoDónde
BTS-07MediaLos cambios de autoridad en Solana se esconden tras una transferencia diminuta. Una solicitud que cambia el propietario o la autoridad de una cuenta, aprueba a un delegado o lleva una instrucción opaca, junto con una transferencia de 1 lamport, recibe esa transferencia como titular y como resumen guardado. Las advertencias de riesgo alto siguen en los detalles y la confirmación del riesgo sigue siendo obligatoria.Motor compartido, también en iPhone
BTS-08MediaEl cambio de Bitcoin se acepta en cualquier índice. Una salida cuenta como cambio verificado si su script coincide con cualquiera de los perfiles de firma única de la cartera, en la rama 0 o 1, en cualquier índice hasta 2³¹−1. Los fondos enviados allí se revisan como "Todas las salidas vuelven a tu cartera", pero una cartera que revisa un rango limitado de direcciones puede no encontrarlos nunca.Motor compartido, también en iPhone
BTS-09Baja–MediaEl resumen guardado omite el valor nativo en llamadas a contratos. Una llamada a un contrato EVM o TRON desconocido que también envía la moneda nativa se guarda como "Llamada a contrato desconocido". La tarjeta de revisión y su advertencia sí muestran el valor.Motor compartido, también en iPhone
BTS-10MediaClave de firma de las versiones en la máquina de desarrollo. La clave y sus contraseñas estaban guardadas en texto plano en el árbol de trabajo, excluidas de Git.Proceso de publicación
BTS-11BajaLa cámara de QR puede seguir escaneando detrás de la pantalla del bloqueo de la app. Firmar sigue requiriendo la contraseña de la cartera.App de Android
BTS-12BajaLa confirmación del riesgo para solicitudes de riesgo alto totalmente decodificadas solo se exige en la interfaz.App de Android (iPhone: BTS-OP5-01)
BTS-13BajaTras un error del Keystore en Android 8–11, la clave que autentica los datos públicos de las carteras puede regenerarse, y las carteras necesitan entonces Reparar. No se pierden secretos ni fondos.App de Android
BTS-14BajaDos claves auxiliares no comprueban si hay bloqueo de pantalla, y parte de la documentación exagera la protección. La bóveda en sí sigue exigiéndolo.App de Android
BTS-15BajaLa afinidad de tareas predeterminada permite el secuestro de tareas en versiones antiguas de Android.App de Android
BTS-16BajaLa comprobación de la copia de seguridad se puede superar por ensayo y error.App de Android (igual en iPhone, según el informe)
BTS-17BajaUna Tarjeta de recuperación de una frase de 12 palabras deja unos 40 bits de entropía.App de Android
BTS-18BajaCancelar el emparejamiento con la cartera puede dejar la revisión en "Buscando la cartera correspondiente…".App de Android
BTS-19BajaAndroid 8.0–9 no puede detectar superposiciones que cubren solo parte de un control de consentimiento. La contraseña sigue siendo obligatoria.App de Android

El informe también incluye notas informativas, entre ellas: el hilo del motor no tiene límite de tiempo de CPU (solo afecta a la disponibilidad), la versión de Google Play se firma con la clave del APK hasta que se configure una clave de subida aparte, la espera entre reintentos se basa en el reloj del sistema y hay copias breves de la frase que la JVM no puede borrar.

GPT-6 Astra revisó un commit anterior. Sus hallazgos y su situación en la versión publicada:

IDGravedadHallazgoEn e7e71fbEn Android 1.0.0
BTS-01MediaLos controles de firma y de riesgo parcialmente cubiertos podían pulsarse a través de una superposiciónCerradoCerrado
BTS-02MediaUna quema o un cambio de autoridad de Solana mezclados con una transferencia diminuta se resumen como la transferenciaAbiertoQuemas corregidas; los cambios de autoridad siguen como BTS-07
BTS-03BajaLos búferes con secretos podían sobrevivir a una operación canceladaCerradoCerrado
BTS-04BajaUna quema de Bitcoin con cambio se resume como "Todas las salidas vuelven a tu cartera" (R3-01 de iPhone)AbiertoCorregido
BTS-05FuncionalUn escaneo de QR interrumpido no se reanudabaCerradoCerrado
BTS-06ValidaciónRutas de archivo obsoletas hacían fallar una prueba del motor y que otra pasara sin ejecutarseAbiertoCorregido (pasan las 217 pruebas del motor)

Lo que confirmaron las revisiones​

ÁreaConfirmado
FirmaNo hay forma de saltarse la contraseña ni de firmar nada que no sea la solicitud revisada y emparejada. El plan queda ligado al hash de la solicitud, al hash del plan y al resumen de los bytes que se firman; el motor lo vuelve a resolver con la semilla descifrada y rechaza cualquier cambio en una transacción de Bitcoin sin firmar. Los resultados que llegan tarde tras una cancelación, el bloqueo de la app o una nueva solicitud se descartan.
Almacenamiento de clavesPBKDF2-HMAC-SHA256 con 600.000 iteraciones en código nativo, AES-256-GCM con un nonce y una sal nuevos en cada cifrado y, encima, una clave del Android Keystore por cartera, no exportable (en StrongBox cuando el teléfono lo tiene). Cada intento de contraseña se cuenta antes de derivar la clave, y un contador dañado falla de forma cerrada.
Secretos en memoriaLos secretos desbloqueados viven en contenedores que se cierran tras su uso y se borran incluso si la operación se cancela. La frase de recuperación se escribe en el teclado propio de la app, que ningún método de entrada ve.
Anfitrión del motorEl paquete está fijado por su SHA-256 y su longitud; QuickJS funciona sin eval ni Function, en un entorno de ejecución nuevo para cada operación que toca un secreto o una entrada no confiable, con límites de memoria y de pila.
Sin conexión y plataformaSin permiso de Internet y sin código de red. Solo la pantalla principal es accesible desde fuera, sin enlaces profundos; las copias de seguridad y la transferencia entre dispositivos están excluidas; ninguna ventana aparece en capturas, grabaciones ni en Recientes; las superposiciones de otras apps se ocultan en Android 12 y posteriores. El bloqueo de la app nunca autoriza una firma, y la versión publicada no registra nada.
Cadena de suministroEl motor recompilado tras un npm ci --ignore-scripts limpio es idéntico byte a byte al archivo confirmado y a la copia del APK. La auditoría de dependencias de producción no informa de avisos.

Lo que no cubrieron​

Pruebas en dispositivos reales (el comportamiento del Keystore y de StrongBox de distintos fabricantes, la biometría, las superposiciones y la captura de pantalla), ejercicios con superposiciones maliciosas, canales laterales, la ejecución del código nativo en ARM, transacciones en cadenas reales, un análisis de CVE de las dependencias de Maven y nativas, y la copia que compila Google Play. Ambos informes piden comprobar la versión publicada en dispositivos representativos desde Android 8 hasta la versión más reciente, y Opus 5.5 recomienda una auditoría humana independiente antes de que la app proteja fondos importantes.

Verifica el APK y el motor​

El APK publicado en bittool.com/signer se puede comprobar por completo: su hash, su certificado de firma, el motor que contiene y la ausencia del permiso de Internet (aapt2 dump badging no muestra android.permission.INTERNET).

# 1. The APK from bittool.com/signer
shasum -a 256 BitToolSigner-1.0.0-1000001.apk
# 109dbf5c622ee77672904c34a10229df3c9b0eac45b07096c510b1e1e169c2a4
apksigner verify --print-certs BitToolSigner-1.0.0-1000001.apk
# Signer #1 certificate DN: CN=BITTOOL PTE. LTD., O=BITTOOL PTE. LTD., C=SG
# Signer #1 certificate SHA-256 digest: af41ed101765393ae89038eb4c6fc7fa96d930f6fcd76b881437a39b5a9e4631

# 2. The engine inside it
unzip -p BitToolSigner-1.0.0-1000001.apk assets/engine/signer.js | shasum -a 256
# 4b3717599e8ee3ed9d2480e640e7203731543cc8ab0f2c3cec3b78e6f400fa19 (1,181,432 bytes)

# 3. The same engine, rebuilt from source
git clone https://github.com/bitbill/bittool-signer-android
cd bittool-signer-android && git checkout 71af693
cd engine && npm ci --ignore-scripts && npm run build
shasum -a 256 ../core/engine/src/main/assets/engine/signer.js

El certificado nunca cambia entre versiones, Android solo instala una actualización que lleve el mismo y la app lo muestra en Ajustes › Totalmente de código abierto › Esta versión. Una copia instalada desde Google Play es un archivo distinto, porque Google Play la compila a partir del paquete subido, así que su hash no se puede comparar; su assets/engine/signer.js no cambia y se puede comparar del mismo modo tras un adb pull desde un ordenador. El procedimiento completo está en el Reproducible-Build.md del repositorio. Comprobamos los valores anteriores con el APK publicado el 25 de octubre de 2026.

Descarga los informes​

InformePáginasSHA-256
iPhone · Opus 5, 19 de octubre de 2026 (PDF, 118 KB)17ff7ddd17e5dffccd99db6aaa43b8f0041167b58bd9b2bd7cc11d185e779bca1a
iPhone · GPT-6 Astra, informe R3, 18 de octubre de 2026 (PDF, 46 KB)1602d7a358f8f35b2978eab7db1292add4365a94b736ff79e158dee3afb842b64a
Android · Opus 5.5, 25 de octubre de 2026 (PDF, 252 KB)88242d58aeec1aa88823eb0a938c9461b0681abfab3f37805e2f77a41b3bba34c
Android · GPT-6 Astra, nueva auditoría, 24 de octubre de 2026 (PDF, 22 KB)7b37aaefd40d0d522384a86255accadeb976067175d76e38466a1b4c90b036f53

Los resúmenes de esta página son nuestros; cuando su redacción difiera de la de un informe, prevalece el informe.