Javastring到SHA1
我正在尝试在Java中做一个简单的stringSHA1转换器,这是我得到的…
public static String toSHA1(byte[] convertme) { MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-1"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } return new String(md.digest(convertme)); }
当我把它传递给toSHA1("password".getBytes())
,我得到“[ a ɹ?? %l 3〜 。 我知道这可能是一个像UTF-8简单的编码修复,但有人可以告诉我该怎么做才能得到我想要的“5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8”? 还是我这样做完全错了?
非常感谢!
UPDATE
您可以使用Apache Commons Codec (版本1.7+)为您完成这项工作。
DigestUtils.sha1Hex(stringToConvertToSHexRepresentation)
感谢@ Jon Onstott对此build议。
老答案
将您的字节数组转换为hexstring。 真正的如何告诉你如何 。
return byteArrayToHexString(md.digest(convertme))
和(从真实的如何)
public static String byteArrayToHexString(byte[] b) { String result = ""; for (int i=0; i < b.length; i++) { result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 ); } return result; }
顺便说一句,你可能会得到更紧凑的代表使用Base64。 Apache Commons Codec API 1.4 ,有这个很好的工具来消除所有的痛苦。 请参阅这里
这是我把string转换为sha1的解决scheme。 它适用于我的Android应用程序:
private static String encryptPassword(String password) { String sha1 = ""; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); sha1 = byteToHex(crypt.digest()); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } catch(UnsupportedEncodingException e) { e.printStackTrace(); } return sha1; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; }
使用番石榴散列类 :
Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString()
只需使用apache commons编解码器库。 他们有一个名为DigestUtils的工具类
没有必要进入细节。
SHA-1(以及所有其他哈希algorithm)返回二进制数据。 这意味着(在Java中)它们产生一个byte[]
。 该byte
数组不代表任何特定的字符,这意味着你不能像你一样简单地把它变成一个String
。
如果你需要一个String
,那么你必须以一种可以被表示为一个String
的方式来格式化这个byte[]
(否则,只需保持byte[]
)。
将任意byte[]
表示为可打印字符的两种常见方式是BASE64或简单的hexstring(即用两个hex数字表示每个byte
)。 它看起来像你试图产生一个hexstring。
还有一个错误:如果你想得到一个Java String
的SHA-1,那么你首先需要将该String
转换为一个byte[]
(因为SHA-1的input也是一个byte[]
)。 如果您只是简单地使用myString.getBytes()
,那么它将使用平台默认编码,因此将取决于您在其中运行的环境(例如,它可能会根据语言/区域设置返回不同的数据你的操作系统)。
更好的解决scheme是指定用于String
到byte[]
转换的编码,如下所示: myString.getBytes("UTF-8")
。 selectUTF-8(或其他可以代表每个Unicode字符的编码)是最安全的select。
如果将string转换为hex格式,这是非常简单的解决scheme:
private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); return new BigInteger(1, crypt.digest()).toString(16); }
如前所述使用apache commons编解码器。 这也是春季大家推荐的(参见Spring doc中的DigestUtils)。 例如:
DigestUtils.sha1Hex(b);
绝对不会在这里使用最高评分的答案。
它不能正确打印,因为您需要使用Base64编码。 使用Java 8,您可以使用Base64编码器类进行编码。
public static String toSHA1(byte[] convertme) { md = MessageDigest.getInstance("SHA-1"); return Base64.getEncoder().encodeToString((md.digest(convertme)); }
结果
这会给你预期的输出5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
这不起作用的原因是当你调用String(md.digest(convertme))
,你告诉Java将一串encryption字节解释为一个String。 你想要的是将字节转换成hex字符。
转换字节数组为hexstring
public static String toSHA1(byte[] convertme) { final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-1"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] buf = md.digest(convertme); char[] chars = new char[2 * buf.length]; for (int i = 0; i < buf.length; ++i) { chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4]; chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F]; } return new String(chars); }