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 severidad crítica o alta. Las revisiones de iPhone encontraron un problema de severidad baja cada una. Las de Android encontraron problemas de severidad 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 severidad 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 por línea (3,546 líneas de JavaScript, 11,858 de Swift), 11 sondeos de ataque, prueba de mutación de la entrada QR con 4,000 casos, suites de pruebas, recompilación en un entorno limpio (clean-room)Revisión del código fuente por subsistema, comparación con la ronda anterior, datos de prueba (fixtures) independientes de Bitcoin y Solana, prueba de mutación con 1,509 casos, suites de pruebas, compilación reproducible, avisos de seguridad de dependencias
Pruebas ejecutadas210 del motor, 168 nativas210 del motor, 177 nativas y de interfaz
ResultadoCrítica: 0 · Alta: 0 · Media: 0 · Baja: 1 · Informativa: 3Crítica: 0 · Alta: 0 · Media: 0 · Baja: 1 · 4 observaciones
IndependenciaAutorrevisión del autor de gran parte del códigoAsistida por IA, preparada para el propietario del proyecto

Ambas 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​

IDSeveridadHallazgoEstado en 1.0.0
BTS-OP5-01BajaEl consentimiento para riesgo alto 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 riesgo alto totalmente decodificadas (aprobaciones ilimitadas, setApprovalForAll, cambios de permisos de Safe, quemas de tokens). La app desactiva Firmar hasta que se marca la casilla, así que en 1.0.0 un atacante no puede llegar a este caso; importa porque el motor es la parte que los usuarios pueden verificar por su hash.Abierto. El informe recomienda agregar la verificació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 monto distinto de cero y cambio verificado, el resumen corto de la pantalla de resultado y de Actividad dice "Every output returns to your wallet" (todas las salidas vuelven a tu billetera). La propia pantalla de firma muestra correctamente la quema, su monto y el riesgo Alto.Abierto (el motor incluido en 1.0.0 es el que se revisó).
BTS-OP5-02InformativaUna clave de localización en Actividad se construye a partir de la salida del motor, y SwiftUI la renderiza como Markdown. Todos los valores que puede tener hoy son etiquetas fijas, así que el problema es latente.Abierto, latente.
BTS-OP5-03InformativaLa KDF de contraseñas de la bóveda (PBKDF2-HMAC-SHA256, 600,000 rondas) no exige mucha memoria (no es memory-hard). Lo mitiga la segunda capa de cifrado con 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 formato de bóveda futuro.
BTS-OP5-04InformativaEl material de clave intermedio de Ed25519 en 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 "¿esta billetera ya está aquí?" puede terminar después de que se edita la frase y ofrecer restablecer la contraseña de la billetera anterior. El restablecimiento en sí vuelve a derivar la identidad de la billetera y rechaza la billetera equivocada; no se modifica ninguna bóveda.Abierto en el momento del informe.
O-02InformativaLos resúmenes de Safe y Solana provienen de decodificadores acotados, no de ejecutar la transacción. El estado en vivo del contrato no se conoce sin conexión.Por diseño; se informa en la pantalla de revisión.
O-03InformativaNo se puede garantizar el borrado completo de la memoria (zeroization) en Swift y JavaScript; no se probaron el dispositivo físico, el generador aleatorio del sistema operativo ni el binario distribuido.Limitación.
O-04InformativaSeis avisos de seguridad de dependencias que solo se usan en desarrollo (3 moderados, 3 bajos). Los paquetes afectados no están en el motor distribuido.Mantenimiento.

Ambos informes también volvieron a probar los hallazgos de dos rondas de revisión anteriores, incluido uno de severidad Alta (el resumen de las transacciones multisig de Safe con DELEGATECALL y MultiSend anidado) y varios de severidad Baja en los resúmenes de comisiones de Bitcoin y de quemas de Solana, y comprobaron que están 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 un identificador de red; la app lo informa.

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:

IDSeveridadQué 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.

Lo que confirmaron las revisiones​

ÁreaConfirmadoDetalles
FirmaEn las compilaciones Release, la única forma de firmar es mediante un plan fijo. Seis verificaciones independientes vinculan la firma con la solicitud revisada, la billetera planificada y la clave aprobada, y el motor vuelve a derivar todo a partir de la semilla descifrada antes de firmar. Confirmado mediante ejecución.Antes de firmar
AleatoriedadLas frases de recuperación provienen de SecRandomCopyBytes; un error detiene la creación y no hay ninguna alternativa. crypto.getRandomValues y Math.random del motor están conectados a la misma fuente.Generación de la semilla
Almacenamiento de clavesDos capas AES-GCM con encabezados autenticados, una clave del Keychain solo para el dispositivo y una ralentización de los intentos fallidos que se mantiene después de reiniciar.Almacenamiento de claves
RechazosSe cumple cada rechazo que describe esta documentación: SIGHASH_NONE/SINGLE/ANYONECANPAY, entradas SegWit v0 sin la transacción previa, 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 confiable5,509 entradas QR, CBOR, PSBT y JSON mutadas entre ambas revisiones: no se aceptó ninguna invá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 suministroAl recompilar el motor a partir del tag se obtiene el mismo archivo byte por byte; las dependencias de ejecución están fijadas a versiones exactas; la auditoría de dependencias de producción no reportó vulnerabilidades.Más abajo

Lo que no cubrieron​

Pruebas en dispositivos físicos (inyección de fallas, 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, transacciones en cadenas en vivo, pruebas de ida y vuelta con billeteras 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. Una suite de pruebas que pasa cubre los casos que prueba, no todas las transacciones ni todos los dispositivos.

Verifica el motor tú mismo​

El ejecutable de la App Store no se puede reproducir byte por 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)

Luego compáralo con el archivo de la app que instalaste: descarga la app como .ipa con Apple Configurator, descomprímela y calcula el hash de Payload/BitToolSigner.app/signer.js. El procedimiento completo, incluido hasta dónde llega la verificación, está en Reproducible-Build.md, en el 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.

IDSeveridadHallazgoDó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:

IDSeveridadHallazgoEn 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 Configuración › 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 una computadora. 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 difiere de la de un informe, prevalece el informe.