假设您使用AWS,并且想通过Cognito使用基于ID的身份验证。
然后aws
为您提供一个公共密钥,您可以使用该公共密钥来验证认知负载。
我们还假设您不希望或无法使用任何像jose这样的精美库,因为您被锁定在高度受限的环境中。
要走的路是使用BASH脚本,该脚本可以使旧的 Brian Kernighan
骄傲。
您必须先了解编码。
Base64Url
需要转换为Base64。
这是通过使用填充字符=
实现的
如果字符数可被4
整除,则无需填充。
这涉及二进制数字表示。
处理完后,您可以将Base64
转换为binary
。
但是如何仅使用BASH和BASH程序将JWKS/JWT
转换为PEM
文件呢?
答案 0 :(得分:1)
这是我遵循下面列出的官方文档和资源提供的解决方案。
https://aws.amazon.com/premiumsupport/knowledge-center/decode-verify-cognito-json-token/
请修改输入网址或直接使用json令牌,并确保已安装jq
。
该功能以注释形式提供描述性帮助。
自2020年4月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 Oparin https://www.yuryoparin.com/2014/05/base64url-in-bash.html
塞德里克·德尔泰(CédricDeltheil) https://github.com/Moodstocks/moodstocks-api-clients/blob/master/bash/base64url.sh
唐vis https://gist.github.com/alvis/89007e96f7958f2686036d4276d28e47
答案 1 :(得分:0)
以下是一些选择:
要么忽略base64 -d
抱怨输入被截断:
<<<'SGVsbG8geW91Cg' base64 -d 2>/dev/null ||:
或在解码之前使用Bash修复base64填充:
base64URL='SGVsbG8geW91Cg'
printf -v pad_space '%*s' $((${#base64URL}%4)) ''
padded_base64="$base64URL${pad_space// /=}"
<<<"$padded_base64" base64 -d