2016-06-30 29 views
1

Als kurzen Überblick versuche ich einen ES256-Algorithmus -JWT-Token über C# unter Verwendung der -Bibliothek zu generieren.C# JWT laden ES256 PEM-Datei in CngKey (jose-jwt)

Als Richtungen Zustand:

ES256, ES384, ES256 ECDSA signatures requires CngKey (usually private) elliptic curve key of corresponding length. Normally existing CngKey loaded via CngKey.Open(..) method from Key Storage Provider. But if you want to use raw key material (x,y) and d, jose-jwt provides convenient helper EccKey.New(x,y,d).

Die CngKey.Open() gibt es einen vorhandenen Schlüssel öffnet, sondern von den Klängen der es sollte ich die CngKey.Import() statt verwenden? Wenn ich versuche, die CngKey.Import() aufzurufen, es gibt die folgenden Fehler:

The parameter is incorrect.

Im Grunde, was ich frage ist, was der einfachste Weg ist, eine vorhandene PEM-Datei in das CngKey Objekt zu konvertieren, die für die erforderlich ist, Jose.JWT.Encode() Funktion? Jede Hilfe würde sehr geschätzt werden. Vielen Dank!

Unten ist mein Code (für die Sicherheit, dass purposed ist nicht die wirklichen privaten Schlüssel):

public string GenerateToken(int contactID, Database _db) 
     { 
      var contact = GetContact(contactID, _db); 
      var payload = new Dictionary<string, object>() 
      { 
       {"broker", 1}, 
       {"contact_id", contact.id}, 
       {"name", contact.fname + " " + contact.lname + ""}, 
       {"iss", "www.somewhere.com"}, 
       {"iat", (DateTime.Now - UnixEpoch).TotalSeconds}, 
       {"nbf", (DateTime.Now - UnixEpoch).TotalSeconds}, 
       {"exp", (DateTime.Now.AddDays(30) - UnixEpoch).TotalSeconds} 
      };  

      string privateKey = 
      "MHcCAQEffEIIIHHHHHHHHHHHHHHHffHHHHHHHHHHHHHHHHHHHHHHHoGgCCqGSM49" + 
      "AwEHhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhI+pRkAxAb13" + 
      "77vz2Yjjjjjjjjjjjjjjjjjjjjw=="; 
      byte[] b = Convert.FromBase64String(privateKey); 

      CngKey cng = CngKey.Import(b, CngKeyBlobFormat.EccPrivateBlob); 
      string token = Jose.JWT.Encode(payload, cng, JwsAlgorithm.ES256); 
      return token; 
     } 

Antwort

0

ich das gleiche Problem mit jose-jwt hatte und habe es funktioniere meine eigene Implementierung von GetECDsaPrivateKey() verwenden. Beachten Sie, dass Ihr Projekt auf .NET 4.6.1 zielen sollte. Bitte gehen Sie folgendermaßen vor:

1.Generate ein p12X509Certificate2 mit openssl

> openssl ecparam -name prime256v1 -genkey > private-key.pem 
> openssl ec -in private-key.pem -pubout -out public-key.pem 
> openssl req -new -key private-key.pem -x509 -nodes -days 365 -out public.cer 
> winpty openssl pkcs12 -export -in public.cer -inkey private-key.pem -out publiccert.p12 

2.Generate ein JWT von privaten Schlüssel von oben generierte Zertifikat zu lesen:

var claims = new Dictionary<string, object>() 
{ 
    { "sub", "[email protected]" }, 
    { "exp", 1300819380 } 
}; 

var certificate = new X509Certificate2("publiccert.p12", "passcode"); 
string token = SignJWTWithCert(certificate, claims); 

private static string SignJWTWithCert(X509Certificate2 cert, object claims) 
{ 
     var header = new { alg = "ES256", typ = "JWT" }; 
     byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); 
     byte[] claimsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(claims, Formatting.None)); 

     using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) 
     { 
      if (ecdsa == null) 
       throw new ArgumentException("Cert must have an ECDSA private key", nameof(cert)); 

      var payload = Base64UrlEncode(headerBytes) + "." + Base64UrlEncode(claimsBytes); 
      var signature = ecdsa.SignData(Encoding.UTF8.GetBytes(payload), HashAlgorithmName.SHA256); 
      return payload + "." + Base64UrlEncode(signature); 
     } 
}