在 .NET 4.0 中使用 PEM 私钥使用 RS256 签署 JWT 令牌
Sign a JWT Token with RS256 with a PEM private Key in .NET 4.0
我需要与 GitHub 集成 API 交互,但具体来自 .NET 4.0,所以我无法使用 Octokit。
基本上我得到了一个 PEM
格式的私有 rsa 密钥(标准 .NET API 不支持)并且必须发送一个 RS256 jwt 令牌来获得一个授权令牌来与 API.
提供了以下 ruby 示例代码:
# Private key contents
private_pem = File.read(path_to_pem)
private_key = OpenSSL::PKey::RSA.new(private_pem)
# Generate the JWT
payload = {
# issued at time
iat: Time.now.to_i,
# JWT expiration time
exp: 1.minute.from_now.to_i,
# Integration's GitHub identifier
iss: 42
}
jwt = JWT.encode(payload, private_key, "RS256")
以下面的curl为例
curl -i -X POST \
-H "Authorization: Bearer $JWT" \
-H "Accept: application/vnd.github.machine-man-preview+json" \
https://api.github.com/installations/:installation_id/access_tokens
以及以下结果示例:
Status: 201 Created
{
"token": "v1.1f699f1069f60xxx",
"expires_at": "2016-07-11T22:14:10Z",
"on_behalf_of": null
}
能够在 .net 4.0
上使用以下 nuget 包成功地与此身份验证 API 交互
BouncyCastle
1.8.1
jose-jwt
2.1.0
Newtonsoft.Json
9.0.1
FSharp.Data
2.3.2
F#代码:
open System
open System.Security.Cryptography
open Jose
open Org.BouncyCastle.Crypto
open Org.BouncyCastle.Security
open Org.BouncyCastle.OpenSsl
open Org.BouncyCastle.Crypto.Parameters
open Newtonsoft.Json
open FSharp.Data
let integrationID = 42 //sample
let installID = 10 // sample
let appUserAgent = "My-App-Name" //sample
//Result Format
type InstallToken = { token:string; expires_at:DateTime ; on_behalf_of: string}
let apiBase = "https://api.github.com"
let instBase = apiBase + sprintf "/installations/%i" installID
//.Net 4.0 doesn't have a method for seconds from Epoch
let epochSeconds (date:DateTime) =
date.ToUniversalTime().Subtract(new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc)).TotalSeconds |> Convert.ToInt64
let createBotToken (pemPath:string) =
//Parse PEM file with BouncyCastle
use streamRead = new StreamReader(pemPath)
let pemRead = PemReader(streamRead)
let bcRSA:AsymmetricCipherKeyPair = downcast (pemRead.ReadObject())
//Convert to .NET RSA object with Bouncy Castle
let dnRSA = bcRSA.Private :?> RsaPrivateCrtKeyParameters |> DotNetUtilities.ToRSAParameters
use key = new RSACryptoServiceProvider()
key.ImportParameters(dnRSA)
//JWT needs literal Dictionary<string,obj> type
let payload= dict [
"iat", (DateTime.Now |> epochSeconds) :> obj ;
"exp", (DateTime.Now.AddMinutes(1.0) |> epochSeconds) :> obj;
"iss", integrationID :> obj;
]
|> Dictionary<string,obj>
//Create token with JWT
let bearer = JWT.Encode(payload, key, JwsAlgorithm.RS256)
//Send Request with FSharp.Data
let iresult = Http.RequestString( instBase + "/access_tokens", httpMethod=HttpMethod.Post ,
headers=[HttpRequestHeaders.Authorization (sprintf "Bearer %s" bearer);
HttpRequestHeaders.UserAgent appUserAgent;
HttpRequestHeaders.Accept "application/vnd.github.machine-man-preview+json";
])
//Use Newtonsoft.Json to convert to obj
JsonConvert.DeserializeObject<InstallToken>(iresult)
我需要与 GitHub 集成 API 交互,但具体来自 .NET 4.0,所以我无法使用 Octokit。
基本上我得到了一个 PEM
格式的私有 rsa 密钥(标准 .NET API 不支持)并且必须发送一个 RS256 jwt 令牌来获得一个授权令牌来与 API.
提供了以下 ruby 示例代码:
# Private key contents
private_pem = File.read(path_to_pem)
private_key = OpenSSL::PKey::RSA.new(private_pem)
# Generate the JWT
payload = {
# issued at time
iat: Time.now.to_i,
# JWT expiration time
exp: 1.minute.from_now.to_i,
# Integration's GitHub identifier
iss: 42
}
jwt = JWT.encode(payload, private_key, "RS256")
以下面的curl为例
curl -i -X POST \
-H "Authorization: Bearer $JWT" \
-H "Accept: application/vnd.github.machine-man-preview+json" \
https://api.github.com/installations/:installation_id/access_tokens
以及以下结果示例:
Status: 201 Created
{
"token": "v1.1f699f1069f60xxx",
"expires_at": "2016-07-11T22:14:10Z",
"on_behalf_of": null
}
能够在 .net 4.0
上使用以下 nuget 包成功地与此身份验证 API 交互BouncyCastle
1.8.1jose-jwt
2.1.0Newtonsoft.Json
9.0.1FSharp.Data
2.3.2
F#代码:
open System
open System.Security.Cryptography
open Jose
open Org.BouncyCastle.Crypto
open Org.BouncyCastle.Security
open Org.BouncyCastle.OpenSsl
open Org.BouncyCastle.Crypto.Parameters
open Newtonsoft.Json
open FSharp.Data
let integrationID = 42 //sample
let installID = 10 // sample
let appUserAgent = "My-App-Name" //sample
//Result Format
type InstallToken = { token:string; expires_at:DateTime ; on_behalf_of: string}
let apiBase = "https://api.github.com"
let instBase = apiBase + sprintf "/installations/%i" installID
//.Net 4.0 doesn't have a method for seconds from Epoch
let epochSeconds (date:DateTime) =
date.ToUniversalTime().Subtract(new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc)).TotalSeconds |> Convert.ToInt64
let createBotToken (pemPath:string) =
//Parse PEM file with BouncyCastle
use streamRead = new StreamReader(pemPath)
let pemRead = PemReader(streamRead)
let bcRSA:AsymmetricCipherKeyPair = downcast (pemRead.ReadObject())
//Convert to .NET RSA object with Bouncy Castle
let dnRSA = bcRSA.Private :?> RsaPrivateCrtKeyParameters |> DotNetUtilities.ToRSAParameters
use key = new RSACryptoServiceProvider()
key.ImportParameters(dnRSA)
//JWT needs literal Dictionary<string,obj> type
let payload= dict [
"iat", (DateTime.Now |> epochSeconds) :> obj ;
"exp", (DateTime.Now.AddMinutes(1.0) |> epochSeconds) :> obj;
"iss", integrationID :> obj;
]
|> Dictionary<string,obj>
//Create token with JWT
let bearer = JWT.Encode(payload, key, JwsAlgorithm.RS256)
//Send Request with FSharp.Data
let iresult = Http.RequestString( instBase + "/access_tokens", httpMethod=HttpMethod.Post ,
headers=[HttpRequestHeaders.Authorization (sprintf "Bearer %s" bearer);
HttpRequestHeaders.UserAgent appUserAgent;
HttpRequestHeaders.Accept "application/vnd.github.machine-man-preview+json";
])
//Use Newtonsoft.Json to convert to obj
JsonConvert.DeserializeObject<InstallToken>(iresult)