当前位置: 首页 > 知识库问答 >
问题:

ES256的JWT签名无效

萧展鹏
2023-03-14

我正在尝试手动创建ES256 JWT令牌。我有一个用python编写的小脚本,它对使用ecdsa python的sha256哈希进行签名。但签名在jwt上无效。木卫一。

繁殖步骤:

  1. 创建Base64报头html" target="_blank">负载:

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9。EYJZDWIixMJ0Nty3ODKwiiBmFtzSi6IkPvAg4GrG9LiiWiyWrTaw4IonrydWusimlHDCI6MTuxNjizotaYMn0

FFC89E33091FFDD3C61798A0A74BF7C2D1A6FD231A6CB519F33952F7696BBE9F

openssl ec-inec_private.pem-noout-text

from json import dumps
from ellipticcurve.ecdsa import Ecdsa
from ellipticcurve.privateKey import PrivateKey

import base64

def toBase64Url(input):
    return input.replace("+", "-").replace("/", "_").rstrip("=")

# Generate privateKey from PEM string
privateKey = PrivateKey.fromPem("""
    -----BEGIN EC PARAMETERS-----
    BgUrgQQACg==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIJfChy9fKFItzqcb8DKBm+2oH0YTZ7N61SQpyABgVZANoAoGCCqGSM49
    AwEHoUQDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0uoYcvX4Z7ROUIgYRvgfpsjBa
    Iv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ==
    -----END EC PRIVATE KEY-----
""")

# Create message from json
message = "FFC89E33091FFDD3C61798A0A74BF7C2D1A6FD231A6CB519F33952F7696BBE9F"

signature = Ecdsa.sign(message, privateKey)

# Generate Signature in base64. This result can be sent to Stark Bank in the request header as the Digital-Signature parameter.
print("Base64: " + signature.toBase64())
print("Base64Url: " +toBase64Url(signature.toBase64()))



# To double check if the message matches the signature, do this:
publicKey = privateKey.publicKey()

print("Hash verification succesfull: " + str(Ecdsa.verify(message, signature, publicKey)))

输出:

Base64:Meqcifip4iozghzgfdcpx6fvxjtb nrxdvhotqwdc5vu8z4eaibnalfghqdao3nctqimpahf IHzxk8em OMMHrJkPOhA==

Base64Url:MEQCIFIP4IOZGHZGFDCX6FVXJTB-NRXDVHOTQWDC5VU8Z4EAIBNALFGHQDAO3NCTQIMPAHF-IHzxk8em-OMMHrJkPOhA

哈希验证成功:True

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9。EYJZDWIixMJ0Nty3ODKWIIbMfTzSi6IkPvAg4GrG9LiiWiyWrTaw4IonrydWusimlHDCI6mtuxNjizotaymn0。MEQCIFIp4IOZGHZGFDCx6FVXJTB-NRXDVHOTQWDC5VU8Z4EAIBNALFGHQDAO3NCTQIMPAHF-IHzxk8em-OMMHrJkPOhA

钥匙:

公众:

-----开始公钥------MFKWEWYHKOZJ0CAQYIKOZJ0DAQCDQGAE1TG2UVIMDFWKTEIDWEHNYBQSW/0 UOYCVX4Z7ROUIGYRVGFPSJBAIV70SUYPMBL0AUEBOXIVTCLCME6SDEQ=----结束公钥-----

私人:

-----BEGIN EC私有密钥-----MHcCAQEEIJfChy9fKFItzqcb8DKBm 2oH0YTZ7N61SQpyABgVZANoAoGCCqGSM49 AwEHoUQDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0uoYcvX4Z7ROUIgYRvgfpsjBa Iv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ== -----END EC私有密钥-----

我知道有很多jwt签名python库,但是使用它是为了理解jwt令牌是如何创建的。

编辑:

Secp256r1|prime256v1|NIST P-256都是由不同的标准组织为同一曲线选择的不同名称(椭圆曲线密码学(ECC)安全传输层协议密码套件(TLS))。我将库更改为python-ecdsa,代码更改为:

from ecdsa import SigningKey, NIST256p
import base64

def toBase64Url(input):
    return input.replace("+", "-").replace("/", "_").rstrip("=")


sk = SigningKey.from_pem("""
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIJfChy9fKFItzqcb8DKBm+2oH0YTZ7N61SQpyABgVZANoAoGCCqGSM49
    AwEHoUQDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0uoYcvX4Z7ROUIgYRvgfpsjBa
    Iv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ==
    -----END EC PRIVATE KEY-----
""")
vk = VerifyingKey.from_pem("""
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0
uoYcvX4Z7ROUIgYRvgfpsjBaIv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ==
-----END PUBLIC KEY-----
""")
signature = sk.sign(b"FFC89E33091FFDD3C61798A0A74BF7C2D1A6FD231A6CB519F33952F7696BBE9F")

print(base64.b64encode(signature))
print("Base64: " + base64.b64encode(signature).decode("utf-8"))
print("Base64Url: " + toBase64Url(base64.b64encode(signature).decode("utf-8")))

assert vk.verify(signature, b"FFC89E33091FFDD3C61798A0A74BF7C2D1A6FD231A6CB519F33952F7696BBE9F")
print("Hash verification succesfull: " + str(vk.verify(signature, b"FFC89E33091FFDD3C61798A0A74BF7C2D1A6FD231A6CB519F33952F7696BBE9F")))

输出:

Base64: rMBgC0ismGdd5rd7n1L LDsQ2UO5 cjBwPNYh xBZvO6fKoJIfmfyNpxw kxmyKWlK 55dF5eMH1u327DMJvvA==

Base64Url:RMB0ISMGDD5RD7N1L-LDsQ2UO5-cjBwPNYh-xBZvO6fKoJIfmfyNpxw-kxmyKWlK-55dF5eMH1u327DMJvvA

哈希验证成功:True

但是签名仍然无效。

共有1个答案

徐鑫鹏
2023-03-14

您正在隐式使用哈希的库,默认情况下应用SHA1。即,为了与ES256兼容,必须明确指定SHA256,并且必须使用未剪切的JWT,例如:

from ecdsa import SigningKey, VerifyingKey
import base64
from hashlib import sha256

def toBase64Url(input):
    return input.replace("+", "-").replace("/", "_").rstrip("=")

jwt = b"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0"

sk = SigningKey.from_pem("""
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJfChy9fKFItzqcb8DKBm+2oH0YTZ7N61SQpyABgVZANoAoGCCqGSM49
AwEHoUQDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0uoYcvX4Z7ROUIgYRvgfpsjBa
Iv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ==
-----END EC PRIVATE KEY-----
""")
vk = VerifyingKey.from_pem("""
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1TG2uvIMdfWkteiDWeHNYbQNSW/0
uoYcvX4Z7ROUIgYRvgfpsjBaIv70SuYpmBLwl0AuEBoXIVTCclCme6SdEQ==
-----END PUBLIC KEY-----
""")

signature = sk.sign(jwt, hashfunc=sha256)

print("Base64: " + base64.b64encode(signature).decode("utf-8"))
print("Base64Url: " + toBase64Url(base64.b64encode(signature).decode("utf-8")))

assert vk.verify(signature, jwt, hashfunc=sha256)
print("Hash verification succesfull: " + str(vk.verify(signature, jwt, hashfunc=sha256)))

可能的输出是:

Base64: Mr4/DF87ek66E2GcAc+2H3ulHplCnxygz65h9dkdvm8QsZBbm2N5EjIgyiWsynza9zCGjjnzBUiXYvij9LLikA==
Base64Url: Mr4_DF87ek66E2GcAc-2H3ulHplCnxygz65h9dkdvm8QsZBbm2N5EjIgyiWsynza9zCGjjnzBUiXYvij9LLikA
Hash verification succesfull: True

生成的签名令牌

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.Mr4_DF87ek66E2GcAc-2H3ulHplCnxygz65h9dkdvm8QsZBbm2N5EjIgyiWsynza9zCGjjnzBUiXYvij9LLikA

然后可以在上成功验证https://jwt.io/使用这里使用的公钥。

 类似资料:
  • 我正在使用Azure AD对spring boot应用程序进行用户身份验证。我创建了一个应用程序来获取登录用户的访问令牌(令牌创建者应用程序)。在此应用程序中,“/token”API从@RegisteredAuth2AuthorizedClient读取访问令牌,并返回与响应相同的令牌。 然后,我必须使用返回的令牌作为RESTAPI的承载令牌,用于具有相同客户端id和相同配置的另一个应用程序。 但当

  • 我正在JWT(JSON Web令牌)方案的帮助下实现一个登录系统。基本上,在用户登录/登录之后,服务器签署一个JWT并将其传递给客户机。 然后,客户机返回每个请求的令牌,服务器在发送回响应之前验证令牌。 这是你所期望的,但是我在这个过程的逻辑上遇到了一些问题。从我读过的所有数学文章来看,RSA签名似乎使用非对称密钥进行签名。由于公钥(顾名思义)是向客户机公开的,而私钥保留在服务器上,因此使用发送给

  • 我正在使用谷歌KMS(https://cloud.google.com/kms/)使用非对称签名密钥对节点中的JSON Web令牌(jwt)进行签名。js应用程序。 我能够创建标头和有效载荷,并与谷歌KMS nodejs库(https://github.com/googleapis/nodejs-kms)我可以签署令牌。 但似乎生成的令牌无效。 事实上,我正在执行以下步骤来生成令牌: 将jwt头定

  • 这是一场噩梦。我在使用jwt验证Azure访问令牌签名时遇到问题。木卫一。不管我做什么,答案总是无效的签名。 有人能帮忙吗? 我的步骤: 我从MSALJava应用示例(msal-java-webapp-samp)生成了一个Token Id和Access Token。 我从我的Azure访问令牌中获得访问令牌头中的孩子访问。 我访问

  • 我想用JSON Web签名(JWS)做一个项目,并且我想发送用于签名的证书的公钥,以便在收到该公钥后可以验证消息。我正在使用Ninbus JOS JWT库。我可以对JSON对象进行签名,并且可以看到公钥,但是我无法正确验证它。代码如下: 公钥是:“Sun RSA公钥,2048位”,但当我从JWK(_RSA公钥2)获得它时,我得到了“Sun RSA公钥,3696位”,我不知道为什么。 谢谢

  • 我目前正在使用Vapor开发Swift后端。我的iOS客户端使用新的iOS 13功能“使用Apple登录”。当用户登录时,我会得到一个身份令牌(访问令牌),这是一个由Apple签名的有效JWT令牌。这将在所有正在进行的通信中发送到服务器,以验证服务器提供的某些路由。 在服务器上,我想通过验证令牌签名来验证发送的令牌是否确实由Apple签名,并且不是由某些恶意用户专门创建的。Apple提供了一个HT