¿Por qué las mismas 12 palabras pueden producir diferentes semillas en un archivo de billetera Electrum?

Estaba revisando un archivo de billetera Electrum (de Electrum 1.9.6 para Windows, si es importante) tratando de entender qué información contenía, e inicialmente no pude averiguar exactamente dónde estaban almacenadas las claves privadas (o incluso si eran tal vez se almacenaron en algún otro archivo). Supongo que el campo "semilla" en el archivo default_wallet contiene suficiente información para que se generen las claves privadas, las claves públicas y el mnemotécnico de 12 palabras. ¿Tengo razón hasta ahora?

Para experimentar un poco más, quería ver si 2 archivos de billetera que usan el mismo mnemotécnico de 12 palabras serían idénticos. Como era de esperar, cuando no encripté las billeteras, la misma mnemotécnica parecía conducir a archivos de billetera idénticos. Sin embargo, también intenté encriptar cada billetera con la misma contraseña y, para mi sorpresa, los archivos tenían diferentes valores en el campo "seed". Esto me sorprendió, así que me pregunto si este es el comportamiento esperado y por qué sucede.

Si el mnemotécnico de 12 palabras produce una billetera diferente, eso hace que el mnemotécnico sea inútil. ¿Estás seguro de que no escribiste mal las palabras o algo así?
Copié y pegué y vi el mismo efecto varias veces. Las billeteras son iguales en el sentido de que tienen las mismas direcciones.
Quizás la "semilla" es una sal/IV utilizada para el cifrado. La transformación de frase de contraseña a claves privadas debe ser determinista, el cifrado no necesita serlo.
@CodesInChaos Esa es mi suposición, pero esperaba que alguien con más familiaridad con el funcionamiento interno lo verificara. Una mirada muy, muy superficial al código no me hizo evidente si este era el caso o no.
El cifrado casi siempre incorpora algún elemento aleatorio.

Respuestas (2)

En realidad es una buena pregunta. Echemos un vistazo a lo que está sucediendo. Primero, Electrum procesa tu mnemotécnico para generar una semilla. De hecho, la semilla contiene toda la información necesaria para generar la clave pública maestra y la clave secreta maestra, la primera se usa para generar la secuencia de claves públicas (direcciones) y la segunda se usa para derivar una clave secreta de una clave pública (en realidad es un poco más complejo). Luego, Electrum guarda el archivo de la billetera, que contiene la semilla y las claves que están realmente en uso, la secuencia completa de pares de claves a menos que llegue a 5 direcciones consecutivas sin usar. Puede almacenarlo sin encriptar o encriptado. En el primer caso, el valor semilla en el archivo siempre tendrá el mismo aspecto, al igual que las claves privadas. En el segundo caso, sin embargo, no lo harán. ¿Por qué? La documentación de Electrum dice:

Electrum usa AES-256-CBC para encriptar la semilla y las claves privadas en la billetera.

¿Qué significa? AES-256 es simplemente un cifrado de bloque. Toma un bloque de datos (128 bits en este caso) y un bloque de clave (256 bits) y genera 128 bits de datos cifrados. Pero no es lo que hace Electrum. En realidad, nadie usa cifrados de bloque como ese y nadie debería hacerlo. En su lugar, se utilizan los llamados modos.En nuestro caso, es el modo Cipher Block Chaining (CBC). Electrum primero genera un vector de inicialización aleatorio (IV), lo mezcla (por operación o exclusiva) con los primeros 128 bits de entrada y usa AES-256 en este bloque mixto para producir el primer bloque encriptado. Para cualquier bloque subsiguiente hace lo mismo, excepto que en lugar de IV toma el bloque cifrado anterior para mezclarlo con el bloque de texto sin formato. El IV se guarda junto con el archivo. Finalmente, es por eso que siempre llega con un valor inicial diferente en un archivo, incluso cuando usa la misma contraseña (lo que da como resultado la misma clave para el cifrado AES-256-CBC [1]): se usa un IV diferente cada vez.

[1] Probablemente tampoco sea el caso, ya que es probable que se utilice la Función de derivación de clave para entregar una clave de su frase de contraseña, en cuyo caso se agrega un valor de sal aleatorio adicional a la frase de contraseña antes de codificarla y guardarla junto, de manera similar a la IV.

"siendo utilizado para derivar una clave secreta de una clave pública". Si uno puede hacer eso, ¿entonces no hay mucha seguridad? ¿Seguro que es al revés?
@Ardilla No realmente. Uno puede derivar cualquier clave privada de su clave pública correspondiente con conocimiento adicional. Es seguro siempre que el usuario no revele este conocimiento adicional.
Acabo de leer sobre esto: la 'derivación endurecida' protege contra esto. ¿El 'conocimiento adicional' al que te refieres es el código de cadena?
Primero, perdón por la respuesta tardía, ha sido un tiempo muy ocupado para mí. No, la derivación reforzada está destinada a proteger contra este "ataque", pero el conocimiento adicional es algo completamente diferente: es la clave privada maestra que se puede extraer de manera efectiva de la clave pública maestra y de cualquiera de las claves privadas individuales. Me encantaría explicar esto con más detalles si hace una pregunta, ya que no encajará tan bien en un comentario y los comentarios no permiten todo el formato matemático. Solo asegúrate de decirme que lo has pedido.

La semilla es la clave que se toma para derivar todas sus direcciones de forma determinista. El cifrado es para proteger la semilla https://electrum.org/faq.html#wallet-encryption

https://electrum.org/faq.html#seed

Leí esos enlaces antes de hacer mi pregunta... esto no responde a la pregunta de por qué el archivo de la billetera muestra 2 semillas diferentes para el mismo mnemotécnico de 12 palabras. Parece que es probable que el usuario agregue algo de entropía a algún tipo de sal, pero me gustaría alguna confirmación al respecto.
Está completamente equivocado en la mayor parte del contenido de su pregunta, por lo que si realmente leyó todo el contenido de esos enlaces, entonces no entendió nada. ¿Por qué importaría eso si la semilla cifrada no coincide? Solo importa que las semillas sean las mismas después de descifrarlas, así es como funciona el cifrado.
Si me equivoco acerca de alguna de mis suposiciones, por favor infórmeme... es por eso que existe este sitio.
En cuanto a por qué importa si la semilla cifrada no coincide, es muy importante para confirmar mi comprensión de qué información está y qué información no está en el archivo default_wallet. Ver que eran diferentes me sorprendió y me hizo preguntarme si mi comprensión del archivo era incorrecta o si tal vez había algún error en la implementación.