linux - 如何使用 OpenSSL shell 命令创建 Json Web Token (JWT)?

标签 linux bash openssl jwt hmac

我正在尝试使用 MacOS 上的命令行实用程序创建一个 JSON Web token (JWT),并在签名部分遇到了障碍。

这个要点给了我很大的启发:https://gist.github.com/indrayam/dd47bf6eef849a57c07016c0036f5207

对于我的 JWT,我有
标题:

{"alg":"HS256","typ":"JWT"}

有效载荷:
{"email":"jordan@example.com"}

我的 hmac 秘诀是:
bigsecretisveryhardtoguessbysneakypeopleright

或者在 base64 中:
Ymlnc2VjcmV0aXN2ZXJ5aGFyZHRvZ3Vlc3NieXNuZWFreXBlb3BsZXJpZ2h0Cg==

我使用以下网站进行验证:
https://jwt.io/

我发现如果我使用 base64 版本的 key 将所有这些输入到站点中,它会生成以下 JWT,该 JWT 成功地验证了我正在测试的站点:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpvcmRhbkBleGFtcGxlLmNvbSJ9.C3MVjfmnul8dLNIgiv6Dt3jSefD07Y0QtDrOZ5oYSXo

在 bash 我试过这个:
jwt_header=$(echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)

payload=$(echo -n '{"email":"jordan@example.com"}' | base64 | sed s/\+/-/g |sed 's/\//_/g' |  sed -E s/=+$//)

hmac_signature=$(echo -n "${jwt_header}.${payload}" | openssl dgst -sha256 -hmac "${key}" -binary | openssl base64 -e -A | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)

jwt="${jwt_header}.${payload}.${hmac_signature}"

这产生了以下内容:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpyZWVkQGV4dG9sZS5jb20ifQ.o426f0XDnsUwActVt14Cr3X3IUqPwfv6yaN5nRaZhew

我发布到的网站不接受这是有效的。所以我不确定我在没有获得有效 HS256 签名的 openssl 命令中做错了什么。

最佳答案

我能够从 https://jwt.io/ 重新创建 JWT

在您的示例中,用户 secret 上有一个隐藏的换行符。 .所以在下面,我还添加了该换行符,纯粹是为了重新创建所需的输出。
此外,您的有效负载中的电子邮件地址不一致,因此在下面我使用了 jordan@example.com .

我对 hmac 步骤采取了稍微不同的方法。我将用户 secret 转换为十六进制字节并将其用作 key (使用 HMAC 的 hexkey 选项)。

# Construct the header
jwt_header=$(echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)

# ans: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

# Construct the payload
payload=$(echo -n '{"email":"jordan@example.com"}' | base64 | sed s/\+/-/g |sed 's/\//_/g' |  sed -E s/=+$//)

# ans: eyJlbWFpbCI6ImpvcmRhbkBleGFtcGxlLmNvbSJ9

# Store the raw user secret (with example of newline at end)
secret=$'bigsecretisveryhardtoguessbysneakypeopleright\n'

# Note, because the secret may have newline, need to reference using form $"" 
echo -n "$secret"

# Convert secret to hex (not base64)
hexsecret=$(echo -n "$secret" | xxd -p | paste -sd "")

# ans: 62696773656372657469737665727968617264746f67756573736279736e65616b7970656f706c6572696768740a

# For debug, also display secret in base64 (for input into https://jwt.io/)
echo -n "$secret" | base64

# ans: Ymlnc2VjcmV0aXN2ZXJ5aGFyZHRvZ3Vlc3NieXNuZWFreXBlb3BsZXJpZ2h0Cg==

# Calculate hmac signature -- note option to pass in the key as hex bytes
hmac_signature=$(echo -n "${jwt_header}.${payload}" |  openssl dgst -sha256 -mac HMAC -macopt hexkey:$hexsecret -binary | base64  | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)

# Create the full token
jwt="${jwt_header}.${payload}.${hmac_signature}"

# ans: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImpvcmRhbkBleGFtcGxlLmNvbSJ9.C3MVjfmnul8dLNIgiv6Dt3jSefD07Y0QtDrOZ5oYSXo

关于linux - 如何使用 OpenSSL shell 命令创建 Json Web Token (JWT)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59002949/

相关文章:

ssl - 如何解决 nginx SSL 错误?

c - 构建执行作为参数传递的程序的简单 shell 脚本

OpenSSL Base64 解码

c++ - 发送较少字节数的 TCP 套接字

linux - 在 rpc 中登录的用户数

linux - Jenkins JNLP slave FitNesse 插件总是尝试连接到本地主机

c - 在 CentOS 上从 C 中的信号处理程序中调用时,localtime_r 卡在了锁上

bash - 如何使用 logger 命令登录到 linux 中的特定文件?

python - IF 语句 : Shell to python

c - 如何使用 API 并正确初始化 openssl?