Parece que não consigo gerar string codificada por hexépo
Pergunta
Não consigo descobrir onde estou dando errado aqui:
private static String generateHashFromFile(String filePath) {
try {
final int BUFSZ = 32768;
MessageDigest sha = MessageDigest.getInstance("SHA-256");
FileInputStream in = new FileInputStream(filePath);
BufferedInputStream is = new BufferedInputStream(in, BUFSZ);
byte[] buffer = new byte[BUFSZ];
int num = -1;
while((num = is.read(buffer)) != -1) {
sha.update(buffer, 0, num);
}
is.close();
byte[] hash = sha.digest();
return byteArrayToHex(hash);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static String byteArrayToHex(byte[] barray)
{
char[] c = new char[barray.length * 2];
byte b;
for (int i = 0; i < barray.length; ++i)
{
b = ((byte)(barray[i] >> 4));
c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(barray[i] & 0xF));
c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new String(c);
}
Estou recebendo cordas como:
")469.76F5941+31E25)6,9,C26)978)4*917180A4C(B7C,E,D+6,7133C705167"
Claramente não é hexadecimal!
Perguntas:
- O código de geração de hash está correto?
- O método de codificação hexadecimal está correto?
- Estou perdendo algo com relação à codificação?
Solução
UMA byte
O valor é assinado e você está usando o deslocamento da direita de preservação assinada. Isso resultará em valores negativos para b
Ao calcular o Nybble de alta ordem.
Por exemplo, considere o que seu código faz com um byte
Valor -112 (0x90). Quando a mudança da direita, é promovido pela primeira vez a um int
valor, 0xffffff90. Em seguida, é deslocado para a direita de 4 bits, preservando o sinal e se torna 0xfffffff9. Isso é então lançado de volta a um byte, que simplesmente descarta os 24 bits de ordem alta, e 0xf9 (-7 decimal) é atribuído a b
. b
não é maior que 9, então o caractere resultante é (-7 + 48), ou ')'.
Faça isso em vez disso:
int hi = (barray[i] & 0xF0) >>> 4, lo = barray[i] & 0xF;
O uso de um byte
Como uma variável local não faz bem em uma máquina de 32 ou 64 bits. De fato, o elenco para byte
é uma instrução desperdiçada.
Outras dicas
Seu código de geração de hash está correto. Converter byte[] barray
em uma corda hexadecimal, você pode simplesmente fazer:
String c = new String();
for(short i = 0; i < barray.length; i++) {
c += Integer.toString((barray[i] & 255) + 256, 16).substring(1).toUpperCase();
}
Tanto a sua geração de hash quanto o código de codificação Hex. Eu examinaria mais de perto o conteúdo do arquivo que você está lendo.
Você também pode escrever seu método de codificação hexadecimal como assim:
public static String byteArrayToHex(byte[] barray) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < barray.length; i++) {
String hex = Integer.toHexString(0xff & barray[i]);
if (hex.length() == 1) sb.append('0');
sb.append(hex);
}
return sb.toString();
}