仅使用hashlib库验证RS256算法的JWT令牌问题求助
手动验证AWS JWT的问题解决方法
问题2:sig**e计算耗时极久的解决办法
直接用Python内置的pow函数三参数形式:pow(sig, e, n)。这是模幂运算,底层用了高效的快速幂算法,避免了直接计算超大数幂导致的内存和时间爆炸,几毫秒就能完成计算,完全不会出现长时间无结果的情况。
原理:RSA验证的核心是计算 sig^e mod n,Python的pow(base, exp, mod)专门针对该场景优化,跳过了生成天文数字的中间步骤。
问题1:padded_hashed_ph结果不合理的排查与修正
你需要严格遵循RSA PKCS#1 v1.5填充规则(RS256等RSA签名算法默认使用该填充),同时确保每一步编码/解码无错误,步骤如下:
1. 正确解码JWT签名部分
JWT签名采用Base64URL编码,解码前需先做格式转换:
- 将签名中的
-替换为+,_替换为/ - 补全Base64填充:按每4个字符一组补
=(如长度模4余1补3个=,余2补2个,余3补1个) - 用
base64.b64decode()解码为二进制字节,再转成整数sig:int.from_bytes(decoded_sig, byteorder='big')
2. 正确计算头部+载荷的哈希
- 取JWT拆分后的前两部分:
header_str + '.' + payload_str,用UTF-8编码为字节:data = f"{header}.{payload}".encode('utf-8') - 根据JWK的
alg字段选择哈希算法:比如RS256对应SHA-256,用hashlib.sha256(data).digest()得到哈希字节
3. 执行PKCS#1 v1.5填充
填充后的字节长度需与RSA模数n的字节长度一致(如2048位的n对应256字节),填充规则为:0x00 + 0x01 + [0xFF * k] + 0x00 + ASN.1_DER_PREFIX + 哈希值
其中:
k为填充的0xFF数量,需满足总长度等于模数字节长度- SHA-256的ASN.1 DER前缀为固定字节串:
b'\x30\x31\x30\x0D\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
示例代码(假设模数为256字节):
import hashlib import base64 # 假设已获取header_str, payload_str, sig_b64url, e, n(e和n为JWK中转换后的整数) data = f"{header_str}.{payload_str}".encode('utf-8') hash_bytes = hashlib.sha256(data).digest() # SHA-256的ASN.1 DER前缀 der_prefix = b'\x30\x31\x30\x0D\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20' encoded_hash = der_prefix + hash_bytes # 计算填充长度 modulus_bytes_length = (n.bit_length() + 7) // 8 padding_length = modulus_bytes_length - len(encoded_hash) - 2 # 减去0x00和0x01的长度 # 构造填充后的字节 padded_bytes = b'\x00\x01' + (b'\xFF' * padding_length) + b'\x00' + encoded_hash # 转成整数 padded_hashed_ph = int.from_bytes(padded_bytes, byteorder='big')
4. 对比验证
用pow(sig, e, n)得到结果,与padded_hashed_ph对比,若相等则签名验证通过。
内容的提问来源于stack exchange,提问作者Jamie Marshall
相关产品推荐
相关产品推荐

