簡體   English   中英

為什么 openssl 生成的簽名看起來與 pyjwt 生成的簽名不同

[英]Why openssl generated signature looks different than pyjwt generated signature

我正在嘗試驗證使用 PyJWT 創建的 JWT 簽名,但它失敗了。 如果使用 openssl 命令創建簽名,則它可以工作。

我有兩個腳本。

Python 腳本,它使用 PyJWT 和 PyOpenSSL 創建 JWT。 如果成功,它會在標准輸出上吐出 JWT。

執行兩個實驗的 Bash 腳本。

  • 運行 Python 腳本並捕獲 JWT。 解碼 header 有效載荷部分。 構造要簽名的消息。 使用 openssl 命令創建簽名(使用 dgst),使用公鑰進行驗證。
  • 從 JWT 中,解碼 heder、payload、簽名部分。 使用 openssl 命令驗證 JWT 使用公鑰創建的簽名。

實驗一成功,二失敗。

我對類似問題的回答很少,並試圖確保

  • 我使用 urlsafe b64 編碼
  • 我使用 openssl dgst 命令從已簽名的輸入消息中創建 hash。
  • 移動數據時使用 echo -n

使用 openssl 命令生成的簽名驗證成功。 使用 PyJWT 生成的簽名無法通過 openssl 驗證。 使用 PyJWT 創建的 JWT 使用 PyJWT 成功解碼。

我已經沒有關於調試這個的想法了。 任何幫助,方向都非常感謝。

jwttest.py(需要 PyJwt、PyOpenSSL)

import sys
import base64
import jwt

'''
# Just in case keys are not available
privkey="-----BEGIN PRIVATE KEY-----\n" \
"MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQC8JuSavoT2vyZi\n" \
"2RsQ0BFBySQVbK2JJPXXi1O33D3JZhUjQhyRh4yaG6ubirdM/r0eZeADdD047T8i\n" \
"wXFxH/dCZun7AF1dBcXxx1/Jr1VsNiaymXPrnRUBSrCSjqNEJIEbRiKna/JY8i6q\n" \
"cXZRTOYead8fXrTIWJRUTx5F4MNAXqdZ5v/oAsxXc1E7il55vOBDgKZSW4rV7SRC\n" \
"W4zqQA/PE9FmkrygV2x4Kbzc3aObgjgMYR99o6vyOkIhqycBPivwvyLgymDah07r\n" \
"1OR/u2z2w1zX5wD9NyLx2wqbpFQypDr0bOW4CsXuHcPEo206g//6EYlkGOW16ZZr\n" \
"Rhv9t8ipAgMBAAECgf92U/9xUmBMzepWQDPFXxV7SgRndPGuTpBN/lGoT9qLzqd8\n" \
"hRdybsz+HmjOaW7d/Vbyxx8bDP9zzcDnGsE9Y90c5ZxBPvl4hyj15W1YaexPIb80\n" \
"k01T4HZVWaOyiAIl2M9ZV8JziG/hgG3Yw4KlnrcaaXrpP6ZyWULvwtJHIBOrZsei\n" \
"CIlF/cmmwS1uHmXLGTUmZyusOeMfhcQFIh1p3r6dw9Dt6r022FvuMWrqxfsdEAP0\n" \
"kCfhuyyczPIX50gMnVN07ApqH/aMh+77fa8z6pEhqqQeQTkM6ttVzz8l9bEdaHyd\n" \
"T3IXI0G2BfuokGKLAWEKCTFfJbEODDSaSacua9UCgYEA4x+POFom84xJhqgvQdAL\n" \
"ZbDjNadRA6avJ2lDz6PhPSAzq6lleyUj7wv6p1O+37MriPKqkwMXWfZuPXaYEApv\n" \
"VQRxNCofeLjYoueWRAxIts6//1L3ueW1KmQBqGAC5oq3+vy372EvIubmzAmr5hcb\n" \
"3jmzCBjsWzTS/z3s2DpVa78CgYEA1BLjb5zrpnrMP/JJ5SaE9JzGRZ2wmB6wph83\n" \
"U3YYm9j/Qtih24I48EON7zLz/utzGZstoHEwAe8d0F1mxFslsj0A0Y6nIE1rH0Za\n" \
"MAsjkxlU0e+iaZZ9WSVvg7D3i7+dYVKpvHW7SKKYcqvJWNs7u+qkGUqiGuDoEJPr\n" \
"JM5lhZcCgYBlFXa4recIHjfbJp9huyZXbBKznnQAG/94mvEDSPzGJ77Xd90iobUM\n" \
"f1hfgHZDOYr2uIoSRB3wfC00TcP/36UNQZzgip7XK+2/EzNdtdnnAr2Q9Wwr4IBx\n" \
"DXFvbsvbr4GSw0dZ0vcXoYy24tcO4NoWXbfAstb/ANOnpffzhILgIQKBgAw43nSz\n" \
"RX19vEG/M/UJ6EW0t1SRxvitZB7e07BysO5ibiurEoD1G1T1f7uWYyuA5ExIfjOt\n" \
"8kdaQYydpWuRmTWRgHeTUhxxecf+pPn52l4C6rmCpwiQzL6Tgr7DNzENpQNT4UZk\n" \
"PpvsCv8o2VzOnb2xwy1V+Mu1xIoYDEg9wOoXAoGBAN8jWNrtxMQCgCdjwc5gOgs5\n" \
"fRdGVa2yly4dXCzVJl6DN3sEmIOuIZfMXeSNuA40AR6qT36F72WcCVE63ZzKvqtX\n" \
"WPjy/jPyQ9pp1dBKKRQCtktt7Iovuqfkc/XtGg1vv5PCefR4f2GKPCvCL3mPKOEB\n" \
"QWCwIEiwAse5z50XfN10\n" \
"-----END PRIVATE KEY-----\n"

pubkey = "-----BEGIN PUBLIC KEY-----\n" \
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvCbkmr6E9r8mYtkbENAR\n" \
"QckkFWytiST114tTt9w9yWYVI0IckYeMmhurm4q3TP69HmXgA3Q9OO0/IsFxcR/3\n" \
"Qmbp+wBdXQXF8cdfya9VbDYmsplz650VAUqwko6jRCSBG0Yip2vyWPIuqnF2UUzm\n" \
"HmnfH160yFiUVE8eReDDQF6nWeb/6ALMV3NRO4peebzgQ4CmUluK1e0kQluM6kAP\n" \
"zxPRZpK8oFdseCm83N2jm4I4DGEffaOr8jpCIasnAT4r8L8i4Mpg2odO69Tkf7ts\n" \
"9sNc1+cA/Tci8dsKm6RUMqQ69GzluArF7h3DxKNtOoP/+hGJZBjltemWa0Yb/bfI\n" \
"qQIDAQAB\n" \
"-----END PUBLIC KEY-----\n"
'''

data={}
'''
data=
{
  "iss": "http://localhost:8080/uaa/oauth/token",
  "user_name": "DBA",
  "nbf": 1592397960,
  "exp": 1621295999
}
'''

def padstr(str):
        padding = len(str) % 4
        if padding:
                data = str
                data += '=' * (4 - padding) 
                return data
        return str

if len(sys.argv) < 3 :
        print "Usage: " + sys.argv[0] + " <private key file>" + " <public key file>"
        exit(1)

with open(sys.argv[1], "r") as f:
        privkey=f.read()
#print privkey

with open(sys.argv[2], "r") as f:
        pubkey=f.read()
#print pubkey

encoded=jwt.encode(data, privkey, algorithm="RS256")
decoded=jwt.decode(encoded, pubkey, algorithms="RS256")

if( decoded != data ):
        print "decoded JWT does not match data"
        print "Data=" + str(data)
        print "Decoded=" + decoded
        exit(1)
else:
        print encoded
        exit(0)

sign_verification.sh

#!/bin/bash

function create_true_digest {
        data_file=$1
        digest_file=$2
        echo "Creating SHA256 digest for $data_file"
        ls -l $data_file
        cat $data_file
        echo
        openssl dgst -sha256 $data_file  | cut -d" " -f2 | xxd -r -p > $digest_file
        echo "digest stored in $digest_file"
        cat ${digest_file} | base64 -w 0 | sed 's/+/-/g' | sed 's/\//_/g' > ${digest_file}.base64
        echo "Base64 encoded digest stored in ${digest_file}.base64"
        ls -l ${digest_file}
        cat ${digest_file}.base64
        echo
        echo "............................................................"
}

function create_digest {
        create_true_digest $1 $2
}

function sign_data {
        data_file=$1
        pvtkey_file=$2
        signature_file=$3
        echo "Signing $data_file with $pvtkey_file"
        ls -l $data_file
        openssl dgst -sha256 -sign $pvtkey_file -out $signature_file $data_file
        #openssl dgst -sha256 -sign $pvtkey_file -binary -out $signature_file $data_file
        echo "Signature stored in $signature_file"
        cat $signature_file | base64 -w 0 | sed 's/+/-/g' | sed 's/\//_/g' > ${signature_file}.base64
        echo "Base64 encoded signature stored in ${signature_file}.base64"
        ls -l ${signature_file} ${signature_file}.base64
        echo "............................................................"
}

function verify_signature {
        signature_file=$1
        pubkey_file=$2
        data_file=$3
        echo "Verifying signature $signature_file with $pubkey_file against $data_file"
        openssl dgst -sha256 -verify $pubkey_file -signature $signature_file $data_file
        echo "............................................................"
}

function experiment_1 {
        echo "Experiment 1: This experiment accepts a message to verify"
        echo "  It uses openssl commands to generate a signature and verifies it"
        echo

        message_to_verify=$1
        #message_to_verify="{\"alg\":\"RS256\",\"typ\":\"JWT\"}.{}"
        pvtkey_file=$2
        pubkey_file=$3

        data_file="sign_data.txt"
        rm -f $data_file
        echo -n $message_to_verify > $data_file
        echo "Data stored in $data_file"

        digest_file="data_digest.bin"
        rm -f $digest_file
        rm -f ${digest_file}.base64
        create_digest $data_file $digest_file

        signature_file="signature_r.bin"
        rm -f $signature_file
        rm -f ${signature_file}.base64
        sign_data $data_file $pvtkey_file $signature_file

        verify_signature $signature_file $pubkey_file $data_file

        echo "............................................................"
}

function experiment_2 {
        echo "Experiment 2: This experiment accepts a message to verify and signature to verify against"
        echo "  It uses openssl commands to verify the signature against the message"
        message_to_verify=$1
        signature=$2 # keep it encoded
        pubkey_file=$3

        data_file="sign_data.txt"
        rm -f $data_file
        echo -n $message_to_verify > $data_file
        echo "Data stored in $data_file"
        cat $data_file
        echo

        signature_file="signature_r.bin"
        rm -f $signature_file
        rm -f ${signature_file}.base64
        echo -n $signature | sed 's/-/+/g' | sed 's/_/\//g' | base64 -di >$signature_file
        echo "Signature stored in $signature_file"
        cat $signature_file | base64 -w 0 | sed 's/+/-/g' | sed 's/\//_/g' > ${signature_file}.base64
        echo "Base64 encoded signature stored in ${signature_file}.base64"
        ls -l ${signature_file} ${signature_file}.base64

        verify_signature $signature_file $pubkey_file $data_file

        echo "............................................................"
}

if [ $# -lt 2 ]
then
        echo "Usage: $0 <private key file> <public key file>"
        exit
fi

pvtkey_file=$1
pubkey_file=$2

# Get Base64URL encoded JWT
# Need python 2.7, PyJWT, PyOpenSSL
JWT=`/usr/local/software/python/python2/bin/python jwttest.py $pvtkey_file $pubkey_file`

# Split parts
echo "Ignore base64 warnings..."
header=`echo -n $JWT | cut -d"." -f1 | sed 's/-/+/g' | sed 's/_/\//g' | base64 -di`
payload=`echo -n $JWT | cut -d"." -f2 | sed 's/-/+/g' | sed 's/_/\//g' | base64 -di`
signature=`echo -n $JWT | cut -d"." -f3` # decoding will be done by routines
message_to_verify="${header}.${payload}"

experiment_1 $message_to_verify $pvtkey_file $pubkey_file
experiment_2 $message_to_verify $signature $pubkey_file

解決。 愚蠢的錯誤。 我假設驗證簽名的消息是“header.payload”。 它是'b64_urlsafe(header).b64_urlsafe(payload)'。 我重新閱讀了我所指的 JWT 文章,他們確實指出了這一點。 很抱歉浪費了您的帶寬。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM