Java で SHA256 ダイジェストから 16 進エンコードされた文字列を生成できないようです
質問
ここでどこが間違っているのか理解できないようです:
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);
}
次のような文字列を取得しています:
")469.76F5941+31E25)6,9,C26)978)4*917180A4C(B7C,E,D+6,7133C705167"
明らかに 16 進数ではありません。
質問:
- ハッシュ生成コードは正しいですか?
- 16進数のエンコーディング方法は正しいですか?
- エンコードに関して何かが足りないのでしょうか?
解決
byte
値が署名され、あなたが署名した保存右シフトを使用しています。これは高次のニブルを計算b
ための負の値になります。
例えば、あなたのコードはbyte
値-112(0x90を)して何をするか検討してください。右シフトすると、それは最初int
値、0xFFFFFF90に昇格されます。それは符号を保存、右4ビットシフト、および0xFFFFFFF9なります。次いで、これをバイト、単に破棄する上位24ビットに戻ってキャストされ、そして0xF9(-7小数)はb
に割り当てられます。結果の文字が ')'(-7 + 48)である、またはSO b
が、9以下である。
の代わりにこれを行います:
int hi = (barray[i] & 0xF0) >>> 4, lo = barray[i] & 0xF;
ローカル変数としてbyte
の使用は、32ビットまたは64ビットマシン上の任意の良いを行いません。実際には、byte
へのキャストは、無駄な命令です。
他のヒント
あなたのハッシュ生成コードが正しいです。 16進文字列に変換するbyte[] barray
に、あなたは、単に行うことができます:
String c = new String();
for(short i = 0; i < barray.length; i++) {
c += Integer.toString((barray[i] & 255) + 256, 16).substring(1).toUpperCase();
}
あなたのハッシュ生成と六角両方のコードの動作をコードします。私は、ファイルあなたしている読書の内容を詳しく見てみます。
あなたはまた、のようなので、あなたの進符号化方法を書くことができます:
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();
}
所属していません StackOverflow