5

このサンプル(.NETで作成)に基づいてnode.jsのJWTトークンを解析および検証しようとしています:https ://github.com/liveservices/LiveSDK/blob/master/Samples/Asp.net/AuthenticationTokenSample/ JsonWebToken.cs

トークンを検証するノードjsjavascriptは次のとおりです。

var validateSignature = function(key, claims, envelope, signature) {
    var hasher = crypto.createHash('sha256');
    hasher.update(key + "JWTSig");
    var key = hasher.digest('binary');
    var hmac = crypto.createHmac('sha256', key);
    hmac.update(envelope + '.' + claims);
    var out = hmac.digest('base64');
    console.log(out);
    console.log(signature);
    console.log(out === signature);
}

さて、非常に奇妙なことは-それはほとんど機能します。3つのconsole.logステートメントの出力は次のとおりです。

pEwNPJ+LUHBdvNx631UzdyVhPFUOvFY8jG3x/cP81FE=
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
false

+-/ _ =を除いて、ハッシュが両方とも同じであるのは疑わしいようです。

誰かが私の間違いを見つけますか?私のbase64エンコーディングと関係があります。

アップデート

もう少しプレイしましたが、ここではbase64エンコーディングで何かファンキーなことが起こっているようです。ノードjsの次のコード:

console.log(signature);
var b = new Buffer(signature, 'base64');
console.log(b.toString('base64'));

収量:

pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
pEwNPJLUHBdvNx631UzdyVhPFUOvFY8jG3xcP81F

どちらが非常に奇妙に思えますか?

4

3 に答える 3

4

コメントして正しい方向に押してくれたTimothyMeadeに感謝します。

ノードのバッファタイプは、+、/、および=で標準のBase64を生成します

ここに記載されているように、URLセーフなbase64エンコーディングがあります:http://en.wikipedia.org/wiki/Base64

+を-に、/を_に置き換え、=はオプションです。QueryString(d'uh)で渡されるトークンは、URLセーフバージョンです。したがって、違い。

コードは簡単に修正されました:

out = out.replace('+','-').replace('/','_').replace('=','');
于 2012-01-15T04:06:50.657 に答える
1

私は少し前にこのライブラリを書きました、私はあなたがコードのいくつかを使うことができると思います。node.jsと最新のブラウザの両方で実行されることになっています。

于 2012-08-23T20:31:05.010 に答える
0

これはあなたが使おうとしていた正確な方法ではありませんが、NodeJSでJWTを検証するための好ましい方法だと思います。NPMbase64urlライブラリを使用してbase64Url(JWTのデフォルトのエンコーディング)とbase64(NodeJSが検証関数に期待するもの)の間で変換していることに注意してください。

また、署名と検証をそれぞれ行うには、公開キーペアと秘密キーペアが必要であることに注意してください。この投稿の下部に、このJWTの署名と検証に使用された秘密鍵と公開鍵を含めました。

const base64 = require('base64url');
const crypto = require('crypto');
const verifyFunction = crypto.createVerify('RSA-SHA256');
const fs = require('fs');

// The sample JWT from https://jwt.io/
const JWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA';

// This just gets the value of the public key (same as the one at bottom of this post)
const PUB_KEY = fs.readFileSync(__dirname + '/id_rsa_pub.pem', 'utf8');

// Split the JWT by `.` to get each part
const jwtHeader = JWT.split('.')[0];
const jwtPayload = JWT.split('.')[1];
const jwtSignature = JWT.split('.')[2];

// We only need the first two pieces to verify
verifyFunction.write(jwtHeader + '.' + jwtPayload);
verifyFunction.end();

// IMPORTANT: NodeJS expects base64 format, not base64url format!
const jwtSignatureBase64 = base64.toBase64(jwtSignature);

// IMPORTANT: You need to specify that the `jwtSignatureBase64` data is base64 format, 
// otherwise, it will default to Buffer format and return false
const signatureIsValid = verifyFunction.verify(PUB_KEY, jwtSignatureBase64, 'base64');

console.log(signatureIsValid); // true

以下のキーは、ここで説明したJWTの例からのものです

秘密鍵:

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw
kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr
m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi
NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV
3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2
QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs
kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go
amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM
+bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9
D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC
0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y
lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+
hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp
bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X
+jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B
BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC
2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx
QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz
5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9
Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0
NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j
8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma
3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K
y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB
jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE=
-----END RSA PRIVATE KEY-----

公開鍵:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc
aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9
MwIDAQAB
-----END PUBLIC KEY-----
于 2019-12-09T11:54:21.360 に答える