Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用char[]生成MD5哈希_Java_Security_Hash_Md5_Message Digest - Fatal编程技术网

Java 使用char[]生成MD5哈希

Java 使用char[]生成MD5哈希,java,security,hash,md5,message-digest,Java,Security,Hash,Md5,Message Digest,如何转换使用此方法获得的char[]密码: char[] password = passwordInputField.getPassword(); 到MD5散列?通常我会使用下面的方法,但getBytes仅与字符串兼容: MessageDigest md = MessageDigest.getInstance("MD5"); md.update(password.getBytes()); String hashedPass = new BigInteger(1, md.digest()).to

如何转换使用此方法获得的char[]密码:

char[] password = passwordInputField.getPassword();
到MD5散列?通常我会使用下面的方法,但getBytes仅与字符串兼容:

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
String hashedPass = new BigInteger(1, md.digest()).toString(16);

注意:MD5哈希算法不应用于密码存储,因为它的哈希很容易被破解。但是,为了简单起见,我将使用它

快速/简单/不安全的修复方法是将char数组转换为字符串。但是,这是不安全的,因为字符串是不可变的,无法从内存中清除

String password = new String(passwordInputField.getPassword());

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
String hashedPass = new BigInteger(1, md.digest()).toString(16);
更安全的解决方案是:将char[]转换为byte[],然后从内存中清除数组

private byte[] toBytes(char[] chars) {
    CharBuffer charBuffer = CharBuffer.wrap(chars);
    ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
    byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
            byteBuffer.position(), byteBuffer.limit());
    Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
    Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
    return bytes;
}

char[] passChars = passwordInputField.getPassword();
byte[] passBytes = toBytes(passChars);

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(passBytes);
String hashedPass = new BigInteger(1, md.digest()).toString(16);

Arrays.fill(passChars, '\u0000'); // clear sensitive data
Arrays.fill(passBytes, (byte) 0); // clear sensitive data
编辑:

使用更安全的解决方案更新了答案(这一想法归功于user2656928)


要归功于andreyne

快速简便,是的。但是
getPassword()
返回的是
char[]
for。在处理密码时应牢记这一点。这与swing将密码返回为
char[]
而不是
String
的安全原因背道而驰,也就是说,字符串是不可变的,因此创建了字符串之后,无法将其从内存中删除。使用
char[]
您可以在处理完数据后覆盖数据(除了允许GC移动对象,如果GC移动了对象,则不能指望它擦除原始数据)。如果你关心安全性,你真的需要找到一个
char[]
byte[]
转换器,然后擦洗两个数组。@realpoint你没有错,但是如果出于任何安全目的直接传输或存储MD5哈希,那么整个系统的问题就比分配的字符串在内存中停留一段时间更大了。@Barend是的,当然。对此,我完全不以为然。谢谢@Connor,尽管看起来你确实犯了一个错误。字节是指字节:字节[]passBytes=toBytes(passChars);不确定您的应用程序是什么,但MD5通常不再用于安全目的。所以您建议使用什么?假设您希望在登录时进行密码存储和验证,这是今天的问题。有关Java实现,请参阅。