Quantos caracteres diferentes em SHA-512 [RESOLVIDO]

Pessoal, andei pesquisando mas não encontrei nada. Parte do meu projeto analisa algumas hashs SHA-512 e verifica quantos caracteres diferentes tem dentro dela.

Criado o código, testei e me deparei com um resultado. Todas as hashs analisadas possuem 16 caracteres diferentes, nunca menos, nunca mais.
Alguém sabe me informar se esse número é imutável ou eu dei muita sorte e existem SHA-512 com outras quantidades de caracteres diferentes?

Obrigado galera :thumbup:

Só uma pergunta: isso não teria relação com a base hexadecimal não?

[]'s

SHA e suas variantes (assim como o MD5) são algoritmos criptográficos de hash, que resultam sempre em um número fixo de bits. No caso do SHA-512 ele retorna um hash de 512 bits (o nome não é mera coincidência) para qualquer frase/arquivo/conjunto de bits que passar pelo algoritmo. Portanto não é possível determinar o “número de caracteres” a partir de um hash.

Algumas referências:
http://en.wikipedia.org/wiki/SHA_hash_functions
http://pt.wikipedia.org/wiki/SHA1#SHA-512_hashes
http://pt.wikipedia.org/wiki/MD5

[quote=AUser]Só uma pergunta: isso não teria relação com a base hexadecimal não?

[]'s[/quote]

Acho que o que ele quer saber é se não é possível sair um hash assim:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

E eu acho que é possível sim, basta vc ter uma amostra populacional suficientemente grande.
Digo acho pois nunca estudei a fundo o SHA(nem MD5, ou qualquer outro algoritmo de hash), mas que eu me lembre não existe nada que impeça isso

Para todos os efeitos, você pode considerar um SHA-512 como um número aleatório.

Existem apenas 16 valores de SHA-512 (um número hexadecimal de 128 dígitos) em um universo de 2^512 valores possíveis. Ou seja, a probabilidade de você ter um dado qualquer cujo SHA-512 seja de 128 dígitos repetidos é de:
16 * 2 elevado a 512 = 1,19 vezes 10 elevado a menos 153.

Um número realmente absurdo, considerando que o número de partículas no universo é de 10 elevado a 87 ( http://www.strangehorizons.com/2001/20010402/biggest_numbers.shtml ).

A única forma de conseguir achar um dado que tenha esse hash é você conseguir, de alguma forma, “quebrar” esse hash (isso requer, obviamente, você ser um excelente criptógrafo - apenas recentemente é que um chinês afirmou que conseguiu “quebrar” o MD5), de forma que você consiga construir um dado que tenha um determinado hash.

Além disso, você quer saber se pode haver um caso em que apareçam apenas 15 dígitos hexadecimais diferentes em um SHA-512, em vez dos 16 diferentes que você encontrou? Pode sim, vamos calcular a probabilidade, que é de 0,17%.

A probabilidade de aparecer um determinado dígito é de 1/16. Então a probabilidade de não aparecer é de 1 - 1/16 = 15/16.
Há 128 dígitos hexadecimais em um SHA-512.
Digamos que queremos um SHA-512 que não tenha um determinado dígito (digamos o dígito 0).
A probabilidade de termos um SHA-512 que não tem o dígito 0 é de (15/16) elevado a 128, ou seja, 1,0684808453952617024956635126888e-4 = 0,010684808453952617024956635126888%.
Como há 16 dígitos possíveis, então devemos multiplicar essa probabilidade por 16. Isso dá:
0,1709569352632418723993061620302 %.

Ou seja, você teria de calcular talvez um pouco mais de 292 SHA-512 diferentes para encontrar um SHA-512 com apenas 15 dígitos hexadecimais diferentes.

O programa abaixo imprime vários buffers de bytes que tem apenas 14 ou menos dígitos hexadecimais diferentes em seus SHA-512.


import java.security.*;
import java.util.*;

class TesteSHA512 {
    private static char[] hexDigits = "0123456789ABCDEF".toCharArray();
    private static String hex (byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append (hexDigits[(b & 0xF0) >>> 4]).append (hexDigits[b & 0x0F]);
        }
        return sb.toString();
    }
    private static String hexSep (byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append (hexDigits[(b & 0xF0) >>> 4]).append (hexDigits[b & 0x0F]).append (',');
            
        }
        return sb.toString();
    }
    private static int countDistinctDigits (String hex) {
        BitSet bs = new BitSet();
        for (int i = 0; i < hex.length(); ++i) {
            bs.set (hex.charAt (i));
        }
        return bs.cardinality();
    }
    private static String absentDigits (String hex) {
        BitSet bs = new BitSet();
        for (int i = 0; i < hex.length(); ++i) {
            bs.set (hex.charAt (i));
        }
        StringBuilder sbMessage = new StringBuilder();
        sbMessage.append ("The following digits were not found: ");
        for (char ch : "0123456789ABCDEF".toCharArray()) {
            if (!bs.get (ch)) {
                sbMessage.append (ch).append (", ");
            }
        }
        return sbMessage.toString();
    }
    public static void main (String[] args) throws Exception {
        byte[] b = new byte[3];
        byte[] digest;
        MessageDigest md = MessageDigest.getInstance ("SHA-512");
        for (int i = 0; i < 256 * 256 * 256; ++i) {
            b[0] = (byte) ((i >>> 16) & 0xFF);
            b[1] = (byte) ((i >>> 8) & 0xFF);
            b[2] = (byte) (i & 0xFF);
            md.reset();
            digest = md.digest (b);
            String s = hex (digest);
            int count = countDistinctDigits (s);
            if (count < 15) {
                System.out.println ("The buffer [" + hexSep (b) + "] has the following SHA-512 with " + 

count + " distinct digits:");
                System.out.println (s);
                System.out.println (absentDigits (s));
                System.out.println ();
            }
        }
    }
}

Galera, era isso mesmo que eu queria saber.

Obrigado pela ajuda!