本文介绍了如何在Deno中验证具有RS256签名的JWT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想立即验证使用RS256作为签名算法的Google JWT的签名(来自Google的证书: https://www.googleapis.com/oauth2/v3/certs ),而我为Deno可以找到的唯一一个库处理HS256( https://deno.land/x/djwt ).

I want to verify a signature from a Google JWT which uses RS256 as signature algorithm as of right now (Certs from Google: https://www.googleapis.com/oauth2/v3/certs), and the only libary which i could find for Deno handles HS256 (https://deno.land/x/djwt).

我真的不参与整个密码游戏,也许有人知道我如何验证签名,也许已经有一个例子了?我真的不知道我需要使用SHA-256进行哈希运算还是使用RSA的方式,当我尝试查找如何实现此功能时,我看到了很多技术上的解释,但没有关于如何处理的真正示例.

I am really not into the whole Cipher game, maybe anybody got an idea how i can verify the signature maybe there already is something with an example? I really don't know what i need to hash with SHA-256 or how i use RSA, when i try to look up how to implement this, I see a lot of technical explanation but no real examples on what to do with what.

我通常只在Node上使用过Google脚本包,请参见: https://developers.google.com/identity/sign-in/web/backend-auth

I usually just used Googles Scriptpackage on Node see: https://developers.google.com/identity/sign-in/web/backend-auth

我具有使用SHA-256进行哈希处理的功能,但关于RSA却一无所知?

I have functions to hash with SHA-256 but nothing about RSA?

推荐答案

djwt .

但是,这里我使用一个名为 God Crypto 的加密模块来验证RS256签名令牌. God Crypto具有解析 JSON Web密钥(JWK)的功能验证Google提供的JWT.

However, here I'm using a crypto module named God Crypto to verify a RS256 signed token. God Crypto has a function to parse a JSON Web Key (JWK), a feature that we need to verify a JWT provided by Google.

首先,我展示一个简短的示例,其中包含JWK的硬编码值和为该演示组成的令牌:

First I show a short example with hardcoded values for the JWK and a token that I made up for this demonstration:

import { RSA, encode } from "https://deno.land/x/god_crypto@v1.4.8/mod.ts";

const jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlctNjduZWt0WVRjOEpWWVBlV0g1c1dlN1JZVm5uMFN5NzQxZjhUT0pfQWMifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.hiKxeC66LIyVKOXjiOk7iScFPy_5-ATw7hEfqGij8sBZmwXAeTPT5BRFYHitFKSXomGqmy_63LLvg4zbhcTTmNf8XIeDAuLsC32soO5woSByisswWHVf8BgxMkI_FPW_oEtEQ8Xv3FL_1rF9j9Oy3jIjgjqhFhXUtsSQWAeuGYH-OQljFwiuO5Bqexcw-H71OEWvQLQof_6KJ0viJyte8QEwEVridyO834-ppHzeaoW2sTvZ22ZNfxPCew0Ul2V_TxHTtO7ZuJCZ81EmeIV6dYJ2GrYh3UN1x1PHy4-tEn-PL4otlaO3PYOcXfCHxHa6xtPsquzPZJnB1Vq8zULLfQ"

// public key in JSON Web Key(JWK) format:
const pubJWK = {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "W-67nektYTc8JVYPeWH5sWe7RYVnn0Sy741f8TOJ_Ac",
    "alg": "RS256",
    "n": "kFpGoVmBmmKepvBQiwq3hU9lIAuGsAPda4AVk712d3Z_QoS-5veGp4yltnyEFYyX867GOKDpbH7OF2uIjDg4-FPZwbuhiMscbkZzh25SQmfRtCT5ocUloQiopBcNAE-sd1p-ayUJWjhPrFoBrBLZHYxVEjY4JrWevQDj7kSeX7eJpud_VuZ77TNoIzj7d_iUuJUUlqF1ZF540igHKoVJJ6ujQLHh4ob8_izUuxX2iDq4h0VN3-uer59GsWw6OHgkOt85TsjMwYbeN9iw_7cNfLEYpSiH-sVHBCyKYQw7f8bKaChLxDRhUUTIEUUjGT9Ub_A3gOXq9TIi8BmbzrzVKQ"
}

// parse the JWK to RSA Key
const publicKey = RSA.parseKey(pubJWK)
const rsa = new RSA(publicKey)

// split the token into it's parts for verifcation
const [headerb64, payloadb64, signatureb64] = jwt.split(".")

// verify the signature based on the given public key
console.log(await rsa.verify(
    encode.base64url(signatureb64),
    headerb64 + "." + payloadb64,
    { algorithm: "rsassa-pkcs1-v1_5", hash: "sha256" },
  ))

您可以直接运行上面的代码并获取结果

you can directly run the code above and get theresult

成功进行验证.

第二个示例从google certs端点加载JWKS(JSON Web密钥集),尝试找到匹配的密钥,然后在找到匹配的密钥时验证令牌.

The second example loads the JWKS (JSON Web Key Set) from the google certs endpoint, tries to find the matching key and then verifies the token when a matching key was found.

令牌标头包含密钥ID(孩子"),该ID标识应用于验证的密钥.

The token header contains a key Id ("kid"), which identifies the key that should be used for verification.

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "W-67nektYTc8JVYPeWH5sWe7RYVnn0Sy741f8TOJ_Ac"
}
import { RSA, encode } from "https://deno.land/x/god_crypto@v1.4.8/mod.ts";
import { decode } from "https://deno.land/x/djwt@v2.2/mod.ts"

// the JWT that we want to verify
const jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlctNjduZWt0WVRjOEpWWVBlV0g1c1dlN1JZVm5uMFN5NzQxZjhUT0pfQWMifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.hiKxeC66LIyVKOXjiOk7iScFPy_5-ATw7hEfqGij8sBZmwXAeTPT5BRFYHitFKSXomGqmy_63LLvg4zbhcTTmNf8XIeDAuLsC32soO5woSByisswWHVf8BgxMkI_FPW_oEtEQ8Xv3FL_1rF9j9Oy3jIjgjqhFhXUtsSQWAeuGYH-OQljFwiuO5Bqexcw-H71OEWvQLQof_6KJ0viJyte8QEwEVridyO834-ppHzeaoW2sTvZ22ZNfxPCew0Ul2V_TxHTtO7ZuJCZ81EmeIV6dYJ2GrYh3UN1x1PHy4-tEn-PL4otlaO3PYOcXfCHxHa6xtPsquzPZJnB1Vq8zULLfQ"

// get the JSON Web Key Set (JWKS) from google certs endpoint
const certs = fetch("https://www.googleapis.com/oauth2/v3/certs");
var jwks = await certs.then((response) => {
  return response.json()
})


// decode the JWT to get the key Id ('kid') from the header
// in Version 2.2 of djwt decode returns a 3 tuple instead of an object
const [ header, payload, signature  ] = decode(jwt)
var keyId = Object(header).kid

// find the matching JSON Web Key (JWK)
var pubjwk = findJWKByKeyId(String(keyId))

// parse the JWK to RSA Key
if (pubjwk) {
    const publicKey = RSA.parseKey(pubjwk)
    const rsa = new RSA(publicKey)

    // split the token into it's parts for verifcation
    const [headerb64, payloadb64, signatureb64] = jwt.split(".")

    // verify the signature based on the given public key
    console.log(await rsa.verify(
        encode.base64url(signatureb64),
        headerb64 + "." + payloadb64,
        { algorithm: "rsassa-pkcs1-v1_5", hash: "sha256" },
    ))
}
else
{
    console.log("key with kid (" + keyId +") not found")
}

// function to find a certain JWK by its Key Id (kid)
function findJWKByKeyId(kid:string) {
    return jwks.keys.find(
        function(x:string){ return Object(x).kid == kid }
    )
  }

在令牌标头中,您看到"alg": "RS256",但在rsa.verify()中, ,它是RS256中RS的长格式,如Scott Brady 解释.

In the token header you see "alg": "RS256", but in rsa.verify(), algorithm: "rsassa-pkcs1-v1_5"is used, which is ithe long form for the RS in RS256`, as Scott Brady explains.

由于给定令牌(在 jwt.io 上创建的示例)没有经过Google签名,因此没有匹配的密钥可以被发现,因此无法验证.使用您自己的Google签名的JWT测试上面的代码.

As the given token (an example created on jwt.io) was not signed by Google, no matching key can be found and therefore it can't be verified. Use your own Google signed JWT to test the above code.

部分验证代码基于 God Crypto Github页面中的示例

Parts of the verification code are based on examples from the God Crypto Github page

这篇关于如何在Deno中验证具有RS256签名的JWT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-17 13:22
查看更多