And*_*ett 2 java md5 one-time-password java-me
我注意到我的很多谷歌搜索都把我带到了这里,所以我想也许我可以借用你的思想:)
作为我的三年级学位论文的一部分,我正在为移动设备(以及登录的网站)开发一次性密码生成器.
使用org.bouncycastle.crypto.digests.MD5Digest库,我将获取一个字节数组(来自字符串用户输入),然后将其散列X次.这也称为菊花链哈希字符串或灯串加密方法.
我的问题是,如果字符串被哈希一次然后它正确地哈希它,但是如果新哈希再次被哈希,结果是不正确的.
见下面的代码:
private String generateHash(String OTP, int loopNum)
{
byte[] secretBytes = OTP.getBytes();
for (int x = 0; x < loopNum; x++)
{
byte[] tempStore = new byte[16];
tempStore = hash(secretBytes);
secretBytes = tempStore;
}
return convertToHex(secretBytes);
}
public byte[] hash(byte[] secretBytes)
{
org.bouncycastle.crypto.digests.MD5Digest digest = new org.bouncycastle.crypto.digests.MD5Digest();
digest.reset();
// Update MD5 digest with user secret in byte format
digest.update(secretBytes, 0, secretBytes.length);
// get length of digest to initialise new md5 byte array
int length = digest.getDigestSize();
// create md5 byte array using length
byte[] md5 = new byte[length];
// calculate MD5 hash, using md5 byte array, 0 for buffer offset
digest.doFinal(md5, 0);
return md5;
}
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
String Hex;
String formattedHex;
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] <<< 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a'+ (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
Hex = buf.toString();
formattedHex = "\n" + Hex.substring(0, 4) + " " + Hex.substring(4, 8) + " " + Hex.substring(8, 12) + " "
+ Hex.substring(12, 16) + " " + Hex.substring(16, 20) + " " +Hex.substring(20, 24) + " "
+ Hex.substring(24, 28) + " " + Hex.substring(28, 32);
return formattedHex;
}
Run Code Online (Sandbox Code Playgroud)
我认为它要么;
我使用以下秘密进行测试:A具有以下MD5输出:
非常感谢您的帮助:)
ps我正在检查PHP md5这可能是一个问题吗?
MD5应用于由单个字节值0x41('A')组成的输入时,产生一个16字节的输出,当以十六进制打印时,输出为7fc56270e7a70fa81a5935b72eacbe29.
如果你在这16个字节上应用MD5 ,你应该得到8f28f2e7231860115d2a8cacba019dbe,这就是你得到的.
现在,如果你认为MD5应用于一个32字节的字符串,这是字符串" 7fc56270e7a70fa81a5935b72eacbe29" 的ASCII编码,那么这就产生了4cbd6d53280de25e04712c7434a70642.因此,我认为您的Java代码很好(为此),您的困惑来自于如何将输入数据提供给基于PHP的测试代码.您编写7fc562...并将其视为"值为0x7f的一个字节,然后是值为0xc5的一个字节,然后......"但PHP代码将其视为"值为0x37的一个字节("7"的ASCII代码),那么一个字节的值为0x66('f'的ASCII码),然后......".
在Linux系统上,试试这个:
$ printf A | md5sum
7fc56270e7a70fa81a5935b72eacbe29 -
$ printf 7fc56270e7a70fa81a5935b72eacbe29 | md5sum
4cbd6d53280de25e04712c7434a70642 -
$ printf "\x7f\xc5\x62\x70\xe7\xa7\x0f\xa8\x1a\x59\x35\xb7\x2e\xac\xbe\x29" | md5sum
8f28f2e7231860115d2a8cacba019dbe -
Run Code Online (Sandbox Code Playgroud)
作为附注:
OTP.getBytes().它通过使用依赖于语言环境的字符集将字符串转换为字节.这将使用UTF-8,UTF-16,ISO-8859-1,......取决于系统配置,通常与"系统语言"相关联.您的代码将对同一个字符串采取不同的行为,这很少是一个好主意.相反,使用OTP.getBytes("UTF-8")哪个将计算相同的字节,而不管本地配置如何.Hex成hex.halfByte作为" & 0x0F" 的结果获得时,它必然包含0到15之间的值." 0 <= halfByte"测试是不必要的.