直接用下面代码测试,将主函数内的密钥改成自己的密钥就行了:
特别注意gradle需依赖
compile group: 'commons-codec', name: 'commons-codec', version: '1.10'
以下代码:
package websockettest;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base32;
public class GoogleYanZheng {
// 最多可偏移的时间
int window_size = 3; // default 3 - max 17
public void setWindowSize(int s) {
if (s >= 1 && s <= 17)
window_size = s;
}
public String check_code(String secret, long timeMsec) {
Base32 codec = new Base32();
byte[] decodedKey = codec.decode(secret);
long t = (timeMsec / 1000L) / 30L;
long hash=0;
for (int i = -window_size; i <= window_size; ++i) {
try {
hash = verify_code(decodedKey, t + i);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
return Long.toString(hash);
}
private static int verify_code(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {
byte[] data = new byte[8];
long value = t;
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signKey);
byte[] hash = mac.doFinal(data);
int offset = hash[20 - 1] & 0xF;
// We're using a long because Java hasn't got unsigned int.
long truncatedHash = 0;
for (int i = 0; i < 4; ++i) {
truncatedHash <<= 8;
// We are dealing with signed bytes:
// we just keep the first byte.
truncatedHash |= (hash[offset + i] & 0xFF);
}
truncatedHash &= 0x7FFFFFFF;
truncatedHash %= 1000000;
return (int) truncatedHash;
}
public static void main(String[] args) {
//改成自己的密钥
String secret="OURODB4DCLQGWN7Y";
long t = System.currentTimeMillis();
GoogleYanZheng ga = new GoogleYanZheng();
ga.setWindowSize(5);
String r = ga.check_code(secret, t);
System.out.println("google验证码为:"+ r);
}
}