用java写一段生成动态令牌OTP的代码
时间: 2024-03-19 08:43:36 浏览: 76
以下是用 Java 生成动态令牌 OTP 的示例代码:
```java
import java.util.Date;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base32;
public class OTPUtil {
private static final int DIGITS = 6;
private static final int PERIOD = 30;
public static String generateOTP(String secretKey) {
try {
byte[] keyBytes = new Base32().decode(secretKey);
// 获取当前时间戳,单位为秒
long timestamp = new Date().getTime() / 1000;
// 计算时间戳的时间段
long counter = timestamp / PERIOD;
// 将计数器转为字节数组
byte[] counterBytes = new byte[8];
for (int i = counterBytes.length - 1; i >= 0; i--) {
counterBytes[i] = (byte) (counter & 0xff);
counter >>= 8;
}
// 计算 HMAC-SHA1 哈希值
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(keyBytes, "RAW"));
byte[] hash = mac.doFinal(counterBytes);
// 获取哈希值的低位 4 位字节
int offset = hash[hash.length - 1] & 0xf;
int binary =
((hash[offset] & 0x7f) << 24) |
((hash[offset + 1] & 0xff) << 16) |
((hash[offset + 2] & 0xff) << 8) |
(hash[offset + 3] & 0xff);
// 对低位 4 位字节进行模运算
int otp = binary % (int) Math.pow(10, DIGITS);
// 将 OTP 转为字符串
String otpStr = Integer.toString(otp);
while (otpStr.length() < DIGITS) {
otpStr = "0" + otpStr;
}
return otpStr;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String generateSecretKey() {
byte[] bytes = new byte[20];
new Random().nextBytes(bytes);
return new Base32().encodeAsString(bytes);
}
}
```
这段代码使用了 Google Authenticator 的算法,可以生成 6 位数字的动态令牌 OTP。其中 `generateSecretKey` 方法用于生成随机的密钥,可以将生成的密钥通过二维码等方式传递给用户,让用户将其添加到 Authenticator 应用中。`generateOTP` 方法用于根据密钥生成动态令牌 OTP,可以在用户登录、重置密码等需要验证身份的场景中使用。
阅读全文