本帖最后由 爱飞的猫 于 2024-8-30 09:32 编辑
Java 处理文字转码的情况和 Python 不一样,遇到非法字符的时候会替换为 EF BF BD
Python 也让他这么处理就行。
此外,或许是我找的 Java JWT 库版本不同,我找的这个版本会对 header 进行排序,因此我在 py 版本也做了对应的更改。最终生成的 token 一致。
实际上不需要管它要不要进行排序,因为签名验证是对你提供的编码后的数据进行校验的(先校验,后反序列化)。
Java 可以观察到这一现象:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
public class Main {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
String jwtSecret;
String secret1 = "key1";
String secret2 = "key2";
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret1.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
mac.update(secret2.getBytes(StandardCharsets.UTF_8));
byte[] hmac_digest = mac.doFinal();
System.out.print("hmac_digest: ");
for (byte b : hmac_digest) {
System.out.printf("%02X ", b);
}
System.out.println();
jwtSecret = new String(hmac_digest, StandardCharsets.UTF_8);
System.out.println("jwtSecret: " + jwtSecret);
byte[] secretBytes = jwtSecret.getBytes(StandardCharsets.UTF_8);
for (byte b : secretBytes) {
System.out.printf("%02X ", b);
}
System.out.println();
{
Algorithm algorithm = Algorithm.HMAC256(jwtSecret);
String token = JWT.create()
.withClaim("a", "b")
.sign(algorithm);
System.out.println("Generated JWT Token (jwtSecret): " + token);
}
{
Algorithm algorithm = Algorithm.HMAC256(secretBytes);
String token = JWT.create()
.withClaim("a", "b")
.sign(algorithm);
System.out.println("Generated JWT Token (secretBytes): " + token);
}
}
}
输出(注意打印 jwtSecret 数组时,多次出现的 EF BF BD ):
hmac_digest: BA 20 B4 F6 37 E6 2A 43 D8 36 81 FA 4C 22 24 EA AA 06 DA 9D CE 9C 23 EA 63 E3 07 2D A0 B2 B8 04
jwtSecret: ? ??7?*C?6??L"$???#?c?-???
EF BF BD 20 EF BF BD EF BF BD 37 EF BF BD 2A 43 EF BF BD 36 EF BF BD EF BF BD 4C 22 24 EF BF BD 06 DA 9D CE 9C 23 EF BF BD 63 EF BF BD 07 2D EF BF BD EF BF BD EF BF BD 04
Generated JWT Token (jwtSecret): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.5bL_MzQ0Kv6RcnfeG9e5vw5YC-dHJTwFTUAv6roVdBA
Generated JWT Token (secretBytes): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.5bL_MzQ0Kv6RcnfeG9e5vw5YC-dHJTwFTUAv6roVdBA
Python:
import hmac
import hashlib
import jwt
secret1 = "key1"
secret2 = "key2"
mac = hmac.new(secret1.encode('utf-8'), digestmod=hashlib.sha256)
mac.update(secret2.encode('utf-8'))
jwt_secret = mac.digest()
jwt_secret_bytes = jwt_secret.decode('utf-8', errors='replace')
print(f'JWT Secret (bytes): {jwt_secret_bytes.encode('utf-8')}')
print(f'JWT Secret (bytes/old): {jwt_secret}')
token = jwt.encode({"a": "b"}, jwt_secret_bytes, headers={"typ": "JWT", "alg": "HS256"}, sort_headers=True)
print(f"Generated JWT Token: {token}")
跑 py 版本可以看到也加入了对应的 ef bf bd 字符:
JWT Secret (bytes): b'\xef\xbf\xbd \xef\xbf\xbd\xef\xbf\xbd7\xef\xbf\xbd*C\xef\xbf\xbd6\xef\xbf\xbd\xef\xbf\xbdL"$\xef\xbf\xbd\x06\xda\x9d\xce\x9c#\xef\xbf\xbdc\xef\xbf\xbd\x07-\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\x04'
JWT Secret (bytes/old): b'\xba \xb4\xf67\xe6*C\xd86\x81\xfaL"$\xea\xaa\x06\xda\x9d\xce\x9c#\xeac\xe3\x07-\xa0\xb2\xb8\x04'
Generated JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.5bL_MzQ0Kv6RcnfeG9e5vw5YC-dHJTwFTUAv6roVdBA
|