使用 RSA 私钥在 Powershell 中将 JSON Web 令牌加密为 RSA RS256

Posted

技术标签:

【中文标题】使用 RSA 私钥在 Powershell 中将 JSON Web 令牌加密为 RSA RS256【英文标题】:Encrypt JSON Web Token as RSA RS256 in Powershell with a RSA private key 【发布时间】:2020-01-17 23:37:43 【问题描述】:

我被卡住了,我正在尝试为 Docusign 签署一个 Json Web 令牌。 https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-jsonwebtokenDocusign 仅提供 RSA 私钥和公钥哈希。而已。 JWT 必须使用 RS256 签名。

我找到了一个 JWT 模块 https://www.powershellgallery.com/packages/JWT/1.1.0,但这需要我安装证书。但我所拥有的只是密钥哈希。

利用我发现的一些其他代码,我能够创建 JWT 令牌,尽管使用了错误的算法。 https://www.reddit.com/r/PowerShell/comments/8bc3rb/generate_jwt_json_web_token_in_powershell/ 我一直在尝试通过创建一个新对象来修改它以使用 RSACryto 提供程序,但我没有成功。

我尝试创建一个新对象并查看是否可以导入密钥以便我可以签署令牌。但我似乎无法做到这一点。

$rsa = New-Object -TypeName System.Security.Cryptography.RSACryptoServiceProvider
$keyhash = "-----BEGIN RSA PRIVATE KEY-----
XXXXXX
-----END RSA PRIVATE KEY-----"

$blob = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($keyhash))

我尝试使用 ImportCspBlob 方法,但它要求将字符串转换为字节,但我似乎也不能这样做。

我不确定我是否以正确的方式接近这种方式。我一直在出错

Exception calling "ImportCspBlob" with "1" argument(s): "Bad Version of provider.
or
Cannot convert value to type "System.Byte". Error: "Input string was not in a correct format."

编辑: 我有一个使用 Node.js 的工作,尽管 id 仍然想看看是否可以在 Powershell 中做我想做的事情。这项工作可能对某些人有用,因为似乎没有很多关于使用 Powershell 和 Docusign API 的参考资料。

我在这里找到了一个 node.JS 脚本,它使用 RS256 算法创建了一个 JWT 令牌。 https://github.com/BlitzkriegSoftware/NodejwtRSA,

我删除了所有额外的东西,因此控制台的输出只是令牌,并将相关范围添加到“有效负载数据”中,并在符号选项下更新了 sub、aud 和 iss。我的 RSA 私钥存储在系统本地的文件中。

nodejs 脚本 - 下面是我的修改版本

'use strict';

const path = require('path');
const fs = require('fs');

// https://github.com/auth0/node-jsonwebtoken
var jwt = require('jsonwebtoken');

// Private Key (must read as utf8)
var privateKey = fs.readFileSync('./rsatest.pk','utf8');
// Sample claims payload with user defined fields (this can be anything, but briefer is better):
var payload =  ;
// Populate with fields and data
payload.scope = "signature impersonation";
// Values for the rfc7519 fields
var iss = "XXXXX-XXXX-XXX-XXX-XXX";
var sub = "XXXXX-XXXX-XXX-XXX-XXX";
var aud = "account-d.docusign.com";
// Expiration timespan: https://github.com/auth0/node-jsonwebtoken#token-expiration-exp-claim
var exp = "1h";
// JWT Token Options, see: https://tools.ietf.org/html/rfc7519#section-4.1 for the meaning of these
// Notice the `algorithm: "RS256"` which goes with public/private keys
var signOptions = 
    issuer : iss,
    subject: sub,
    audience: aud,
    expiresIn: exp,
    algorithm: "RS256"
;
var token = jwt.sign(payload, privateKey, signOptions);
console.log(token)
process.exitCode = 0;

我从 Powershell 调用它并将访问令牌反馈到我的脚本中,这样我就可以获取我的访问令牌并开始进行 API 调用。

#get the JWT token
$token = & node C:\temp\nodejwt.js
# Generate Header for API calls.
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/x-www-form-urlencoded")
$body ="grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=$token"
$authuri = "https://account-d.docusign.com/oauth/token"
#send the JWT and get the access token 
$accesstoken = Invoke-RestMethod -Method post -Uri $authuri -Headers $headers -Body $body -Verbose
$getheaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$getheaders.Add("Content-Type", "application/json")
$getheaders.Add('Authorization','Bearer ' + $accesstoken.access_token)    
$geturi = "https://account-d.docusign.com/oauth/userinfo"
#use the access token to make api calls 
Invoke-RestMethod -Method get -Uri $geturi -Headers $getheaders 

【问题讨论】:

【参考方案1】:

我也遇到了同样的问题,卡住了。我用 Python 来获取 JWT。请务必安装 PyJWT 和密码库。

$ pip install PyJWT
$ pip install pyjwt[crypto]


import time
import jwt
from datetime import datetime, timedelta

private_key= b'-----BEGIN PRIVATE KEY-----
`-----END PRIVATE KEY-----\n'

encoded_jwt = jwt.encode(
    "iss":"<service account e-mail>",
    "scope":"",
    "aud":"",
    "exp":int(time.time())+3600,
    "iat":int(time.time())
    , private_key, algorithm='RS256')
encoded_jwt

【讨论】:

以上是关于使用 RSA 私钥在 Powershell 中将 JSON Web 令牌加密为 RSA RS256的主要内容,如果未能解决你的问题,请参考以下文章

RSA非对称加密,私钥用于签名公钥用于验签;公钥用于加密私钥用于解密

在 powershell 中生成 RSA 密钥对

如何在 Java 中将 OpenSSH 私钥转换为 RSA 私钥?

rsa公钥和私钥到底哪个才是用来加密,哪个用来解密?

RSA加密过程详解 | 公钥加密| 密码学| 信息安全

OpenSSL生成公私钥