Files
VibeCoding/WebRTCSignalServer/src/main/java/com/ttstd/signaling/security/TokenUtils.java
tongtongstudio 6eb2c7321a feat(controlled): 实现设备激活与安全认证流程
- 添加API客户端、加密存储和provision/token激活逻辑
- WebSocket改用Bearer令牌认证,移除REGISTER请求
- 设备ID改为服务端下发,支持令牌刷新和强制下线处理
- 新增deviceSecret加密存储和accessToken自动刷新
- 更新设备ID获取方式为出厂SN,添加安全存储依赖
2026-08-01 15:13:12 +08:00

58 lines
2.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.ttstd.signaling.security;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
/**
* 随机 ID / 密钥生成与哈希工具。
*/
public final class TokenUtils {
private static final SecureRandom RANDOM = new SecureRandom();
private static final Base64.Encoder B64URL = Base64.getUrlEncoder().withoutPadding();
private static final char[] BASE62 =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private TokenUtils() {
}
/** 生成高熵、不可枚举的 Base62 字符串。 */
public static String randomBase62(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(BASE62[RANDOM.nextInt(BASE62.length)]);
}
return sb.toString();
}
/** 生成 URL-safe 的随机密钥(用于 deviceSecret / refreshToken。 */
public static String randomSecret(int bytes) {
byte[] buf = new byte[bytes];
RANDOM.nextBytes(buf);
return B64URL.encodeToString(buf);
}
/** 对不可逆凭据做 SHA-256 摘要(适用于高熵随机串,无需加盐慢哈希)。 */
public static String sha256(String raw) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return B64URL.encodeToString(md.digest(raw.getBytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("SHA-256 不可用", e);
}
}
/** 常量时间字符串比较。 */
public static boolean constantTimeEquals(String a, String b) {
if (a == null || b == null) {
return false;
}
return MessageDigest.isEqual(
a.getBytes(StandardCharsets.UTF_8),
b.getBytes(StandardCharsets.UTF_8));
}
}