【问题标题】:Sign a JWT Token with RS256 with a PEM private Key in .NET 4.0在 .NET 4.0 中使用带有 PEM 私钥的 RS256 签署 JWT 令牌
【发布时间】:2017-07-04 12:21:10
【问题描述】:

我需要与 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

还有以下 Result 示例:

Status: 201 Created
{
  "token": "v1.1f699f1069f60xxx",
  "expires_at": "2016-07-11T22:14:10Z",
  "on_behalf_of": null
}

【问题讨论】:

    标签: .net-4.0 rsa jwt github-api pem


    【解决方案1】:

    能够使用 .net 4.0 上的以下 nuget 包成功地与此身份验证 API 交互

    • BouncyCastle1.8.1
    • jose-jwt2.1.0
    • Newtonsoft.Json9.0.1
    • FSharp.Data2.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)
    

    【讨论】:

      猜你喜欢
      • 2016-12-12
      • 2019-08-27
      • 2019-05-26
      • 2018-09-24
      • 2019-05-13
      • 2017-06-20
      • 2018-11-25
      • 2021-02-06
      • 2019-10-18
      相关资源
      最近更新 更多