如何在 python 3.7 中编辑 JWT header?
How do I edit the JWT header in python 3.7?
我正在尝试编写一个程序,它将尝试 brute-force 用于通过 words-list.
在 JWT 令牌中签署签名的秘密
问题是每当我使用 PyJWT 生成令牌时,header(在 base64 解码之后)是:{"typ":"JWT","alg":"HS512"}
但我试图破解的大多数 JWT 令牌具有以下 header:{"alg":"HS512","typ":"JWT"}
token = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS512'}
这是我得到的令牌:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzb21lIjoicGF5bG9hZCJ9.EgMnzcJYrElON09Bw_OwaqR_Z7Cq30n7cgTZGJqtK1YHfG1cGnGJoJGwOLj6AWg9taOyJN3Dnqd9NXeTCjTCwA
不出所料,散列签名会有所不同,我的程序将无法正常工作,我知道可以在 header 中添加更多数据,但不知道如何在两者之间切换"typ" 和 "alg".
如果有任何帮助,我将不胜感激,我希望继续使用 python 而不是更改为其他编程语言。
如果您要暴力破解 JWT(这将是一项艰巨的任务,祝您好运),那么只需直接从前两部分自己生成签名即可。 Python 字典和 JSON 对象是 无序结构 所以任何一个顺序都是有效的,JWT 规范没有指定顺序,任何 JWT 实现只接受现有数据对于前两部分来验证签名。他们不会重新生成 JSON.
PyJWT 库在 jwt.algorithms
模块中将所有支持的算法作为单独的对象提供;只需调用 jwt.algorithms.get_default_algorithms()
即可获取到 Algorithm
instance.
的字典映射名称
每个这样的对象都有 .sign(msg, key)
和 .verify(msg, key, sig)
方法。传入前两段(base64编码,.
,作为bytes
对象)作为消息,你将得到二进制签名(not base64 编码)在使用 .sign()
时返回,或者在使用 .verify()
验证时,您传入从 base64 数据解码的二进制签名。
因此,对于作为 bytes
对象的给定 token
,您可以获得算法并验证密钥:
import json
from jwt.utils import base64url_decode
from jwt.algorithms import get_default_algorithms
algorithms = get_default_algorithms()
msg, _, signature_part = token.rpartition(b'.')
header = json.loads(base64url_decode(msg.partition(b'.')[0]))
algo = algorithms[header['alg']]
signature = base64url_decode(signature_part)
# bytes key from other source; brute-force or otherwise
if algo.verify(msg, key, signature):
# key correct
鉴于您的示例 token
和 key
设置为 b'secret'
,以上验证:
>>> import json
>>> from jwt.utils import base64url_decode
>>> from jwt.algorithms import get_default_algorithms
>>> token = b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzb21lIjoicGF5bG9hZCJ9.EgMnzcJYrElON09Bw_OwaqR_Z7Cq30n7cgTZGJqtK1YHfG1cGnGJoJGwOLj6AWg9taOyJN3Dnqd9NXeTCjTCwA'
>>> key = b'secret'
>>> algorithms = get_default_algorithms()
>>> msg, _, signature_part = token.rpartition(b'.')
>>> header = json.loads(base64url_decode(msg.partition(b'.')[0]))
>>> algo = algorithms[header['alg']]
>>> signature = base64url_decode(signature_part)
>>> algo.verify(msg, key, signature)
True
通过在循环中生成密钥来进行暴力破解很容易验证。请注意,任何超出小键(使用有限字母表)的东西都很快变得不可行;即使使用系统编程语言,一个 16 字节的完全随机密钥值(128 位)也需要几十年的时间才能在现代硬件上进行暴力破解,更不用说 Python 循环的较慢速度了。
我正在尝试编写一个程序,它将尝试 brute-force 用于通过 words-list.
在 JWT 令牌中签署签名的秘密问题是每当我使用 PyJWT 生成令牌时,header(在 base64 解码之后)是:{"typ":"JWT","alg":"HS512"}
但我试图破解的大多数 JWT 令牌具有以下 header:{"alg":"HS512","typ":"JWT"}
token = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS512'}
这是我得到的令牌:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzb21lIjoicGF5bG9hZCJ9.EgMnzcJYrElON09Bw_OwaqR_Z7Cq30n7cgTZGJqtK1YHfG1cGnGJoJGwOLj6AWg9taOyJN3Dnqd9NXeTCjTCwA
不出所料,散列签名会有所不同,我的程序将无法正常工作,我知道可以在 header 中添加更多数据,但不知道如何在两者之间切换"typ" 和 "alg".
如果有任何帮助,我将不胜感激,我希望继续使用 python 而不是更改为其他编程语言。
如果您要暴力破解 JWT(这将是一项艰巨的任务,祝您好运),那么只需直接从前两部分自己生成签名即可。 Python 字典和 JSON 对象是 无序结构 所以任何一个顺序都是有效的,JWT 规范没有指定顺序,任何 JWT 实现只接受现有数据对于前两部分来验证签名。他们不会重新生成 JSON.
PyJWT 库在 jwt.algorithms
模块中将所有支持的算法作为单独的对象提供;只需调用 jwt.algorithms.get_default_algorithms()
即可获取到 Algorithm
instance.
每个这样的对象都有 .sign(msg, key)
和 .verify(msg, key, sig)
方法。传入前两段(base64编码,.
,作为bytes
对象)作为消息,你将得到二进制签名(not base64 编码)在使用 .sign()
时返回,或者在使用 .verify()
验证时,您传入从 base64 数据解码的二进制签名。
因此,对于作为 bytes
对象的给定 token
,您可以获得算法并验证密钥:
import json
from jwt.utils import base64url_decode
from jwt.algorithms import get_default_algorithms
algorithms = get_default_algorithms()
msg, _, signature_part = token.rpartition(b'.')
header = json.loads(base64url_decode(msg.partition(b'.')[0]))
algo = algorithms[header['alg']]
signature = base64url_decode(signature_part)
# bytes key from other source; brute-force or otherwise
if algo.verify(msg, key, signature):
# key correct
鉴于您的示例 token
和 key
设置为 b'secret'
,以上验证:
>>> import json
>>> from jwt.utils import base64url_decode
>>> from jwt.algorithms import get_default_algorithms
>>> token = b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzb21lIjoicGF5bG9hZCJ9.EgMnzcJYrElON09Bw_OwaqR_Z7Cq30n7cgTZGJqtK1YHfG1cGnGJoJGwOLj6AWg9taOyJN3Dnqd9NXeTCjTCwA'
>>> key = b'secret'
>>> algorithms = get_default_algorithms()
>>> msg, _, signature_part = token.rpartition(b'.')
>>> header = json.loads(base64url_decode(msg.partition(b'.')[0]))
>>> algo = algorithms[header['alg']]
>>> signature = base64url_decode(signature_part)
>>> algo.verify(msg, key, signature)
True
通过在循环中生成密钥来进行暴力破解很容易验证。请注意,任何超出小键(使用有限字母表)的东西都很快变得不可行;即使使用系统编程语言,一个 16 字节的完全随机密钥值(128 位)也需要几十年的时间才能在现代硬件上进行暴力破解,更不用说 Python 循环的较慢速度了。