需求是 会员从C#迁移到了JAVA,但是旧的密码是BASE64(HMACSHA512(value))加密的,用户体验不变,所以java端也要实现这个,可我生成的这么都不对。
c#: PBKDF2
C#生成的 类似:zYKcuNTKMZzvmCptYkXbbfCXkwUiQKf/6qZi/XRNNxSf08pMRcrBO34cj9DMyoQCFOLnbQgDz9aalz8yjbQwng==
而我生成的:
YjA4OTc2ZDJkNmNhYTk4OGJmODI0M2M1OWExZTJjYjMwMmMzNzFmYzA0ZTA2ZTE0ZjkyNGQyNWNiNGI2MTA1ZDc1YTUzNTJjZjI1YjY4ODlhY2JhMTk2M2MwNzcyODE4MjQzZmY3YzczZjMzY2I2OWEyMGIyM2ZkYmNiOTAwOGY=
哪有问题?
下面是代码
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import java.util.Base64;
public class HMAC {
/**
* 定义加密方式
* MAC算法可选以下多种算法
* <pre>
* HmacMD5
* HmacSHA1
* HmacSHA256
* HmacSHA384
* HmacSHA512
* </pre>
*/
private static final String HMAC_SHA1 = "HmacSHA512";
/**
* 生成签名数据_HmacSHA1加密
*
* @param data
* 待加密的数据
* @param key
* 加密使用的key
*/
public static String getSignature(String data, String key) throws Exception {
byte[] keyBytes = key.getBytes();
// 根据给定的字节数组构造一个密钥。
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, HMAC_SHA1);
Mac mac = Mac.getInstance(HMAC_SHA1);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes());
String hexBytes = byte2hex(rawHmac);
return hexBytes;
}
private static String byte2hex(final byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
// 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。
stmp = (java.lang.Integer.toHexString(b[n] & 0xFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs;
}
/**
* @param args
*/
public static void main(String[] args) {
try {
String signature = getSignature("3e043a92a204412cb7098b67c017b1cf", "ants@xpress");
String base64String = Base64.getEncoder().encodeToString(signature.getBytes("UTF-8"));
System.out.println(base64String);
} catch (Exception e) {
e.printStackTrace();
}
}
}
直接对签名算法生成的字节数组做base64编码,不要先转成HAX string。
base64和转成hex都是将字节序列转成可以阅读的字符形式,一般在设计上不会同时使用,同时使用的话只会徒增结果长度,对安全性提升意义不大。
hmac是签名算法,作为开发者建议分清编码、摘要/哈希/杂凑、签名以及加密的区别