最近不知道為什麼,突然被派去做三方驗證了,說起來這種比較高技術的事情不應該交給我這種菜雞來做的說,可能是當太久的米蟲終於被抓到了吧,ㄏㄏ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
| /**
* 透過tgAuthResult decode出包含的Hash,與Bot Token 進行驗證,具體步驟如下
* 1. 將tgAuthResult進行Base64 decode
* 2. 去除掉回傳的HashCode
* 3. 按照字母順序去排序這些key-value
* 4. 計算Bot Token的 sha256
* 5. 計算HMAC_Sha256,明文是上面Bot Token的sha256,key是Bot Token,然後將結果轉換成Hex
* 6. 比較上面得到的Hex和回傳的HashCode是否一致
*
* @param tgAuthResult
* @return
*/
@Slf4j
public class TestMain {
private static final String BOT_TOKEN = "Token放這邊";
public static void main(String[] args) throws NoSuchAlgorithmException {
String tgAuthResult = "oauth回傳的tgAuthResult放這邊,應該會是一段base64的編碼文字";
// Step 1: Parse JSON
String decodedData = new String(Base64.getDecoder().decode(tgAuthResult));
JsonObject jsonObject = JsonParser.parseString(decodedData).getAsJsonObject();
// Step 2: Extract hash and other fields for verification
String receivedHash = jsonObject.get("hash").getAsString();
jsonObject.remove("hash"); // Remove hash from the map before verification
// Step 3: Create data string for hashing
TreeMap<String, String> sortedData = new TreeMap<>();
for (Map.Entry<String, com.google.gson.JsonElement> entry : jsonObject.entrySet()) {
if (!entry.getKey().equals("hash")) { // Make sure "hash" is excluded from sortedData
sortedData.put(entry.getKey(), entry.getValue().getAsString());
}
}
StringBuilder dataString = new StringBuilder();
for (Map.Entry<String, String> entry : sortedData.entrySet()) {
if (dataString.length() > 0) dataString.append("\n");
dataString.append(entry.getKey()).append("=").append(entry.getValue());
}
// Calculate HMAC
// String secretKey = BOT_TOKEN;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] secretKey = digest.digest(BOT_TOKEN.getBytes(StandardCharsets.UTF_8));
String calculatedHash = calculateHMAC(dataString.toString(), secretKey);
// Step 5: Verify hash
if (calculatedHash.equals(receivedHash)) {
log.info("Verification successful! User authenticated.");
} else {
log.warn("Verification failed! Data may have been tampered with.");
}
}
public static String calculateHMAC(String data, byte[] key) {
try {
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] hashBytes = mac.doFinal(data.toString().getBytes(StandardCharsets.UTF_8));
// Convert bytes to hex format using Apache Commons Codec
return bytesToHex(hashBytes);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC", e);
}
}
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
}
}
|