Как преобразовать JSON Web Key Set (JWKS) publi c ключи в файл PEM, используя BASH? - PullRequest
0 голосов
/ 29 апреля 2020

Допустим, вы используете AWS и хотите использовать аутентификацию на основе идентификатора с использованием Cognito.

Затем aws предоставляет вам ключ publi c, с которым вы можете проверить полезную нагрузку cognito.

Давайте также предположим, что вы не хотите или не можете использовать какие-либо необычные библиотеки, такие как jose, поскольку вы заблокированы в сильно ограниченном окружении.

Путь к go - это BASH скрипт, который бы сделать старый добрый Брайан Керниган гордый. Вы должны сначала понять кодировку. Base64Url необходимо перевести на Base64.

Это достигается с помощью символов заполнения = Если количество символов делится на 4, вам не нужно заполнять символы. Это относится к двоичному представлению di git. После этого вы можете перевести Base64 в binary.

Но как мне преобразовать JWKS/JWT в PEM файл, используя только программы BASH и BASH

Ответы [ 2 ]

0 голосов
/ 29 апреля 2020

Вот несколько вариантов:

Либо игнорировать base64 -d жалобы на усеченный ввод:

<<<'SGVsbG8geW91Cg' base64 -d 2>/dev/null ||:

Или исправить base64 с помощью Bash перед декодированием:

base64URL='SGVsbG8geW91Cg'

printf -v pad_space '%*s' $((${#base64URL}%4)) ''

padded_base64="$base64URL${pad_space// /=}"

<<<"$padded_base64" base64 -d
0 голосов
/ 29 апреля 2020

Это решение, которое я придумал, следуя официальной документации и источникам, перечисленным ниже.

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

Пожалуйста, измените URL-адрес ввода или используйте json напрямую и убедитесь, что у вас установлено jq.

Описательная помощь предоставляется в виде комментариев.

Успешно протестировано в Ubuntu 18.04 и AmazonLinux2 (CentOS) по состоянию на 2020-04-28

#!/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

Особая благодарность:

Юрий Опарин https://www.yuryoparin.com/2014/05/base64url-in-bash.html

Cédri c Deltheil https://github.com/Moodstocks/moodstocks-api-clients/blob/master/bash/base64url.sh

Алвис Тан https://gist.github.com/alvis/89007e96f7958f2686036d4276d28e47

...