Nuevo sistema de direcciones en LISK
En este artículo, ofrecemos una descripción general de las principales mejoras relacionadas con el nuevo sistema de identificación introducido en la plataforma Lisk, como parte de la fase de longevidad de la red de la hoja de ruta del protocolo Lisk . Todos estos cambios se especifican formalmente como propuestas de mejora de Lisk (LIP) que se han investigado y revisado a fondo.
Comenzamos presentando los principales conceptos técnicos utilizados en este artículo. A esto le sigue una explicación del nuevo sistema de direcciones para el ecosistema Lisk ( LIP 0018 ). Lo discutimos desde la perspectiva del protocolo y también desde la perspectiva de la interfaz de usuario. A continuación, le sigue el nuevo formato de ID para transacciones ( LIP 0019 ) y, finalmente, se cubre el nuevo sistema de ID para bloques en Lisk ( LIP 0020).
Experiencia técnica
Este artículo menciona algunos conceptos técnicos que son importantes para comprender completamente la motivación detrás del nuevo sistema de identificación.
En esta sección, explicamos brevemente estos conceptos en caso de que no esté familiarizado con ellos.
Conceptos básicos de hash
Una función hash es una función que asigna una entrada de tamaño arbitrario a una salida de tamaño fijo. Una de las funciones hash más utilizadas es SHA-256, que tiene una longitud de salida fija de 256 bits. Una función hash criptográfica es una función hash que es adecuada para su uso en criptografía y debe tener algunas propiedades adicionales. En este artículo, estamos particularmente interesados en las siguientes dos propiedades de las funciones hash criptográficas: resistencia a preimagen y resistencia a colisiones.
Resistencia a la preimagen
Dada cualquier salida de hash, debería ser difícil encontrar una entrada que dé esta salida. Las funciones que carecen de esta propiedad son vulnerables a los ataques de preimagen . Si la longitud de salida es de 128 bits, hay 2 128 salidas posibles de la función hash. Para una función hash criptográfica, se supone que estas salidas son igualmente probables. Entonces, a su vez, se necesitarían 2 128 intentos de expectativa para encontrar la entrada que produzca la salida de hash deseada. Esto se considera lo suficientemente difícil como para que se asuma que las salidas hash de al menos 128 bits de longitud son seguras en la comunidad de criptografía.
Resistencia a colisiones
Una
función hash es resistente a colisiones, si es difícil encontrar dos entradas
diferentes de modo que sus salidas hash sean las mismas. Cuando esto
ocurre, lo definimos como una colisión hash. Cada función hash tiene
colisiones debido al tamaño fijo de la salida y al número infinito de entradas
posibles. En este contexto, difícil significa que básicamente no hay mejor
manera de encontrar una colisión hash que probar numerosas entradas hasta que dos
de ellas produzcan la misma salida.
Representación de números
En este artículo, vemos diferentes representaciones numéricas utilizadas para representar claves públicas y direcciones tanto en el formato antiguo como en el nuevo. La siguiente tabla muestra un ejemplo básico de estas representaciones numéricas y ejemplos de uso:
Nuevo sistema de direcciones para el ecosistema Lisk
En Lisk, se genera una dirección a partir de la frase de contraseña de 12 palabras elegida inicialmente por el usuario para crear una nueva cuenta. Esta frase de contraseña se codifica utilizando SHA-256 en una cadena de 256 bits. Esta cadena se usa como semilla para generar tanto la clave privada como la clave pública usando el esquema de firma Ed25519 . A esto le sigue un paso final que transforma la clave pública en la dirección.
Este formato de dirección fue diseñado con el objetivo de que sea conveniente para los usuarios al leer, escribir o comunicar una dirección. Sin embargo, también tiene tres deficiencias relevantes, dos de ellas afectan la seguridad de los usuarios:
1. Baja resistencia a la preimagenActualmente, se recomienda encarecidamente a los titulares de Lisk que realicen al menos una transacción desde su cuenta. De esta manera, su clave pública se almacena en la cadena de bloques Lisk como parte de la cuenta, y solo esta clave pública puede firmar cualquier transacción futura desde la cuenta. De lo contrario, cualquiera que tenga una clave pública con la misma dirección podrá acceder a todos los fondos de la cuenta. Para 64 bits, esto sigue siendo muy poco probable, pero como se mencionó anteriormente, la resistencia de preimagen de 128 bits se considera segura, mientras que la resistencia de preimagen de 64 bits generalmente se considera demasiado pequeña a largo plazo.
2. Baja resistencia a colisiones
Debido a la longitud de sólo 64 bits, la probabilidad de tener una colisión de direcciones, es decir, dos usuarios generando coincidentemente pares de claves que producen la misma dirección, no es despreciable. Tenga en cuenta que las colisiones no aportan ningún valor a un atacante en sí, pero pueden provocar una pérdida accidental de dinero si un nuevo usuario genera una dirección existente.
Las direcciones no tienen ningún mecanismo para detectar errores tipográficos o errores en una dirección. Por lo tanto, escribir mal un solo carácter de la dirección en una transacción de transferencia de saldo da como resultado el envío de fondos a una cuenta diferente. Además, esos fondos se perderán para siempre si ningún usuario tiene el par de claves correspondiente para la cuenta receptora.
Explicaremos en las siguientes subsecciones cómo el nuevo sistema de direcciones resuelve estas deficiencias y cómo planeamos migrar a él en la plataforma Lisk.
Nueva dirección
A
nivel de protocolo, la nueva dirección son los 160 bits más significativos del hash SHA-256 de la clave
pública de la cuenta. Por ejemplo, supongamos que tenemos una clave
pública, dada en formato hexadecimal como se muestra a continuación:
`0x0eb0a6d7b862dc35c856c02c47fde3b4f60f2f3571a888b9a8ca7540c6793243`, entonces
la dirección utilizada en el nivel de protocolo es la siguiente 0x` a
representaciones hexadecimales).
Con una longitud de 160
bits, las nuevas direcciones son lo suficientemente largas para que no sea
factible computacionalmente encontrar un nuevo par de claves (clave pública y
clave privada), que devuelva una dirección existente. A 160 bits medios
larga cadena uno tiene que tratar de 2 160 pares de claves en
promedio para encontrar el par de claves para una dirección dada (véase Resistencia preimagen arriba). Por lo tanto, los
usuarios ya no necesitan realizar el proceso de transacción de registro
inicial. Esto también significa que es prácticamente imposible que dos
usuarios independientes elijan dos pares de claves que den como resultado la
misma dirección.
Sin embargo, tratar con estas cadenas hexadecimales puede resultar tedioso y propenso a errores para los usuarios finales. Codificamos esta cadena de 160 bits de manera que el formato de dirección en el nivel de la interfaz de usuario sea más fácil de usar, más compacto y evite errores de escritura o de copiar y pegar. Veamos cómo funciona esta codificación en la siguiente subsección.
Codificación para el nivel de interfaz de usuario
Para
los usuarios de la plataforma Lisk, las direcciones siempre se mostrarán en un
formato Base32 fácil de usar e incluirán una suma de verificación que detecta
errores tipográficos. Esto significa que en lugar de
'0xc247a42e09e6aafd818821f75b2f5b0de47c8235', la dirección de ejemplo anterior
se verá como 'lsk24cd35u4jdq8szo3pnsqe5dsxwrnazyqqqg5eu' .
Este formato de dirección de la interfaz de usuario siempre tiene 41 caracteres, contiene dígitos decimales y letras minúsculas del alfabeto latino y comienza con el prefijo 'lsk'. Básicamente, la codificación de las direcciones para el nivel de la interfaz de usuario se divide en tres pasos principales que se enumeran a continuación:
1. Calcule una suma de comprobación de 30 bits de la dirección de 160 bits y agregue esta suma de comprobación a la dirección.
2. Codifique la salida en el formato Base32.
3. Anteponga el prefijo "lsk" a la salida anterior.
En el
siguiente diagrama, podemos ver cómo funciona todo el proceso de generación de
direcciones en cada paso, y cómo se aplica para nuestra clave pública inicial:
`0x0eb0a6d7b862dc35c856c02c47fde3b4f0f2f3571a888b9a8ca7540c6793243`
Capacidades de detección de errores y suma de comprobación
Una suma de comprobación es un pequeño fragmento de
datos redundantes que se agrega a un determinado bloque de datos, es decir, con
el fin de detectar errores que puedan haberse introducido durante su
transmisión o manipulación. El ejemplo más simple y común de suma de
control es el bit de paridad. Esto significa que agrega un 0 o 1 adicional
a los datos de manera que el número total de 1 en la representación binaria sea
par. Esto le permite detectar cambios de un solo bit o un número impar de
bits. Con este objetivo, introdujimos una suma de comprobación de 30 bits
para que fuera parte de la dirección. Esto se calcula utilizando el
mismo código BCH que se utiliza en bech32 para Bitcoin.
Gracias a esta suma de
comprobación adicional, un usuario puede escribir mal hasta 4 caracteres en la
dirección y se garantiza que la aplicación lo detectará. No importa si los
errores se introducen en la parte de suma de comprobación y / o en la parte que
representa la dirección de 160 bits. Si el usuario introduce más de 4
errores, ya no hay garantía de detección, pero sí una probabilidad de detección
muy alta. Por ejemplo, la probabilidad de detectar 5 errores es superior
al 99,9999999%.
Consideremos nuevamente
la dirección anterior: 'lsk24cd35u4jdq8szo3pnsqe5dsxwrnazyqqqg5eu'. Para
esta dirección, la suma de comprobación (en Base32) es 'qqg5eu'. Imagina
que un usuario quiere enviar LSK a esta dirección, el siguiente gráfico muestra
cómo el envío de una transacción a una dirección que incluye 4 errors sería
rechazado por la billetera:
Codificación de formato Base32
Una
codificación Base32 básicamente significa que usamos un conjunto de 32 dígitos,
cada uno de los cuales representa 5 bits (tenga en cuenta que 32 es
2 5 ). Base32 es especialmente interesante para nuestro caso
porque nos permite usar números y letras comunes para representar estos 32
dígitos. Dado que el alfabeto latino moderno tiene 26 letras y hay 10
dígitos decimales, es decir, 36 caracteres distintos en general, tenemos que
elegir qué caracteres van a representar nuestro formato Base32. Por tanto,
se excluyen los caracteres más ambiguos, "i", "l",
"0" y "1". Además, por razones de legibilidad, solo
usamos letras minúsculas. Por lo tanto, los 32 caracteres utilizados en
nuestro formato Base32 en orden de codificación son los siguientes:
" Zxvcpmbn3465o978uyrtkqew2adsjhfg "
Una dirección en Lisk que contenga un carácter que no esté en esta lista resultará automáticamente en una dirección inválida (excluyendo el 'prefijo lsk)'. Para convertir la dirección de nivel de protocolo a este formato Base32, cada fragmento de 5 bits se asigna al carácter Base32 correspondiente.
Migración al nuevo sistema de direcciones
Para
la mayoría de los usuarios, la migración a este nuevo sistema de direcciones se
realizará sin problemas. Una vez que se introduzca el nuevo sistema de
direcciones, los usuarios aún podrán iniciar sesión en Lisk Mobile o Lisk
Desktop con la contraseña como antes. La única diferencia será que ahora
la interfaz mostrará la nueva dirección Lisk en el formato Base32, y los
usuarios solo podrán enviar dinero a direcciones en este nuevo formato. De
ahí que el único requisito para los usuarios sea familiarizarse con el nuevo
formato de dirección y su apariencia, para que puedan seguir utilizando la
plataforma como de costumbre. Este es el caso de las cuentas con una clave
pública asociada, que son la mayoría en Lisk.
Solo las cuentas que
nunca envían una transacción no se pueden migrar al nuevo sistema de
direcciones automáticamente, ya que la clave pública no se almacena en la
cadena de bloques Lisk. Para estas cuentas, los usuarios deberán enviar
una vez una transacción de reclamo especial , firmada con su
par de claves original para realizar la migración.
Nuevo sistema de identificación para transacciones
En
Lisk, cada transacción tiene un identificador, abreviado como un ID de
transacción que se supone que identifica de manera única una transacción, ya
sea incluida en la cadena de bloques o en espera de
inclusión. Actualmente, este ID de transacción es un valor de 64 bits que
se muestra en representación decimal en las interfaces de usuario. Por
ejemplo, una de las primeras transacciones incluidas en el bloque génesis de
Lisk tiene el ID de transacción ' 5449806225917864483'. Los identificadores de
transacciones no sufren las mismas vulnerabilidades de seguridad que las
direcciones. Sin embargo, la longitud actual de 64 bits tiene algunos
inconvenientes en la experiencia del usuario, ya que la probabilidad de una
colisión hash no es despreciable. Por ejemplo, si cada bloque contiene 120
transacciones, se espera una colisión en aproximadamente 11 años. Esto
significa que los usuarios pueden experimentar un escenario en el que la red
rechaza una transacción firmada válidamente, debido al requisito de unicidad de
los ID de transacción. Más importante aún, el nivel de la interfaz de
usuario (por ejemplo, el explorador Lisk ) también se vería afectado ya
que la transacción ya incluida y la transacción rechazada tienen ID iguales.
La solución para este
problema es tan sencilla como puede suponer aquí, que es que necesitamos
definir ID de transacción más
largos . Por lo
tanto, el nuevo ID de transacción es la salida SHA-256 completa de la
transacción, que tiene 256 bits de longitud. Con esta longitud de
identificación, asumiendo que cada bloque contiene alrededor de 120
transacciones, la probabilidad de tener una colisión en los próximos 50 años es
prácticamente nula. Para una representación más compacta en las interfaces
de usuario para ID de 256 bits, cambiamos de una representación decimal a una
representación hexadecimal. Esto significa que, en el futuro, aparecerá un
ID de transacción como el siguiente:
'0xda63e78daf2096db8316a157a839c8b9a616d3ce6692cfe61d6d380a623a1902' en lugar de
' 15822870279184933850'.
Nuevo sistema de identificación para bloques
Los
identificadores actuales para bloques, también indicados por ID de bloque,
tienen el mismo formato que los ID de transacción, es decir, un valor de 64
bits derivado del encabezado del bloque y mostrado en representación
decimal. Para los ID de bloque, el rango limitado de posibles valores hash
proporciona solo una protección relativamente débil contra ataques previos a la
imagen. Esto significa que un atacante podría intentar crear un bloque
alternativo con el mismo ID de bloque, y también la misma propiedad de bloque anterior que un bloque dado en la cadena
de bloques. Si tienen éxito, otros miembros de la comunidad podrían ser
engañados para sincronizar desde la cadena del atacante, ya que podrían estar
convencidos de que esto es genuino, ya que la cadena alterada sería
válida. Para poder realizar todo el ataque, el atacante necesitaría el par
de claves para el delegado de la ranura de bloque correspondiente, para
completar ~ 2 64pasos de cálculo, y también los usuarios objetivo necesitarían
sincronizarse con la cadena de bloques alterada. Esto significa que este
ataque es muy caro y complejo de lograr prácticamente.
Sin embargo, para
garantizar la inmutabilidad de la cadena de bloques Lisk durante mucho tiempo
en el futuro, el nuevo ID de bloque es la salida SHA-256 completa del
encabezado del bloque. Esta longitud de 256 bits proporciona resistencia
contra ataques previos a la imagen de 256 bits, lo que hace que el ataque
explicado sea inviable en cualquier situación en el futuro previsible.
Esta publicación de
blog ofrece una descripción general del nuevo sistema de identificación, pero
todos los detalles se dan en los LIP específicos. Para más preguntas y
comentarios sobre el tema, organizaremos un AMA en Lisk.chat con Iker Alustiza (Investigador
científico) este viernes 24 de julio a las 4 pm CEST . También invitamos a
todos los miembros de la comunidad a que vayan al foro de Lisk Research, donde siempre nos complace
escuchar sus comentarios y participar en debates sobre este y otros temas.
Lisk tiene la misión de
permitirle crear aplicaciones blockchain descentralizadas, eficientes y
transparentes.
Recursos:
Fuente: Blog de Lisk