El número de seguridad es una derivación del identificador estable y la clave pública de un usuario. Los números de seguridad se calculan para ambas personas en una conversación.
El código realmente importante es este snipit
byte[] publicKey = getLogicalKeyBytes(unsortedIdentityKeys);
byte[] hash = ByteUtil.combine(ByteUtil.shortToByteArray(FINGERPRINT_VERSION), publicKey, stableIdentifier.getBytes());
for (int i=0;i<iterations;i++) {
digest.update(hash);
hash = digest.digest(publicKey);
}
Lo que está sucediendo es que estamos tomando la versión de huella digital, la clave pública y el identificador estable como entradas de inicio y hashing que una vez con SHA-512. La segunda iteración define la clave pública del hash que acabamos de producir, y luego la hace una segunda vez.
Este proceso de agregar la clave pública y repetir el hash continúa para el número de iteraciones indicadas.
¿Por qué necesitamos hacer más iteraciones que en el pasado?
Esto se debe a un problema fundamental si hash. ¿Cuál es la posibilidad de colisiones hash.
Digamos que soy un atacante (Eve). Alice quiere hablar con Bob, así que Signal envía su clave pública a Bob, pero Eve intercepta la clave pública y la sustituye por la suya. Normalmente hay una indicación de que la clave cambió, y el número de seguridad cambia.
Si Eve tenía suficientes recursos, podría construir una clave pública que coincidiera con el número de seguridad. Para combatir esta amenaza, lo hacemos para que Eve tenga que encontrar una colisión que ocurra después de 5200 rondas de hash, con la adición de esa misma clave en cada ronda.
Esto se vuelve inviable computacionalmente ya que cada ronda de hashing hace que encontrar una colisión sea más costoso computacionalmente. El número de iteraciones actualmente seleccionadas generalmente se calcula sobre el tiempo que tomaría un ataque de este estilo en función de los recursos de la amenaza percibida.
No puedo encontrar ningún cálculo de Signal sobre por qué eligieron 5200.