如何使用BASH对Base64Url解码AWS JWKS JWT并通过openssl ASN1转换为公钥PEM文件

问题描述 投票:-1回答:1

base64Url如何使用BASH解码JWT?

bash amazon-web-services openssl jwt urlencode
1个回答
0
投票

链接到官方JWKS JWK AWS文档:

https://aws.amazon.com/premiumsupport/knowledge-center/decode-verify-cognito-json-token/

请修改输入网址或直接使用json令牌,并确保已安装jq

描述性帮助在功能中作为注释提供。

已成功测试截至2020-04-28在Ubuntu 18.04和AmazonLinux2(CentOS)上运行

#!/usr/bin/env bash
set -e

# FUNCTIONS
decodeBase64UrlUInt() { #input:base64UrlUnsignedInteger
    local binaryDigits paddedStr
    case $(( ${#1} % 4 )) in
        2) paddedStr="$1=="   ;;
        3) paddedStr="$1="    ;;
        *) paddedStr="$1"     ;;
    esac
    binaryDigits=$(             \
        echo -n "$paddedStr"    \
        | tr '_-' '/+'          \
        | openssl enc -d -a -A  \
        | xxd -b -g 0           \
        | cut -d ' ' -f 2       \
        | paste -s -d ''        \
    )
    echo "ibase=2; obase=A; $binaryDigits" | bc
    # openssl   enc:encoding; -d=decrypt; -a=-base64; -A=singleLineBuffer
    # xxd       "make-hexdump": -b=bits; -g=groupsize
    # cut       -d=delimiter; -f=field
    # paste     -s=serial|singleFile; -d=delimiter
}

base64UrlToHex() { #input:base64UrlString
    local hexStr paddedStr
    case $(( ${#1} % 4 )) in
        2) paddedStr="$1=="   ;;
        3) paddedStr="$1="    ;;
        *) paddedStr="$1"     ;;
    esac
    hexStr=$(                   \
        echo -n "$paddedStr"    \
        | tr '_-' '/+'          \
        | base64 -d             \
        | xxd -p -u             \
        | tr -d '\n'            \
    )
    echo "$hexStr"
    # base64    -d=decode
    # xxd       -p=-plain=continuousHexDump; -u=upperCase
    # tr        -d=delete
}

asn1Conf() { #input:hexStrPlainUpperCase
    local e="$1"
    local n="$2"
    echo "
        asn1 = SEQUENCE:pubkeyinfo
        [pubkeyinfo]
        algorithm = SEQUENCE:rsa_alg
        pubkey = BITWRAP,SEQUENCE:rsapubkey
        [rsa_alg]
        algorithm = OID:rsaEncryption
        parameter = NULL
        [rsapubkey]
        n = INTEGER:0x$n
        e = INTEGER:0x$e
    " | sed '/^$/d ; s/^ *//g'              \
    | openssl asn1parse                     \
        -genconf    /dev/stdin              \
        -out        /dev/stdout             \
    | openssl rsa                           \
        -pubin                              \
            -inform     DER                 \
            -outform    PEM                 \
            -in         /dev/stdin          \
            -out        /dev/
    # sed       /^$/d=removeEmptyLines; /^ */=removeLeadingSpaces
}

main() {
    local e n hexArr
    local jwksUrl="$1"
    local jwkJson=$(curl -sSSL $jwksUrl)
    local kidList=$(jq -r '.keys[].kid' <<< "$jwkJson")
    for keyId in $kidList; do
        n=$(jq -r ".keys[] | select(.kid == \"$keyId\") | .n" <<< "$jwkJson")
        e=$(jq -r ".keys[] | select(.kid == \"$keyId\") | .e" <<< "$jwkJson")
        echo -e "\n$keyId"
        # decodeBase64UrlUInt "$e"
        # decodeBase64UrlUInt "$n"
        asn1Conf $(base64UrlToHex "$e") $(base64UrlToHex "$n")
    done
}

# MAIN
main 'https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json'
exit 0

特别感谢:

Yury Oparinhttps://www.yuryoparin.com/2014/05/base64url-in-bash.html

CédricDeltheilhttps://github.com/Moodstocks/moodstocks-api-clients/blob/master/bash/base64url.sh

唐Alhttps://gist.github.com/alvis/89007e96f7958f2686036d4276d28e47

© www.soinside.com 2019 - 2024. All rights reserved.