2017-12-31 99 views
1

Ich ermüde, um das JWT-Token für den Aufruf von Apns zu generieren. hier ist mein Code:System.Security.Cryptography.CryptographicException: Die angeforderte Operation wird nicht unterstützt. Windows Server 2012

var header = new Dictionary<string, object>() 
    { 
     { "kid" , keyID } 
    }; 
    var payload = new Dictionary<string, object>() 
    { 
     { "iss", teamID }, 
     { "iat", DateTimeOffset.Now.ToUnixTimeSeconds().ToString() } 
    }; 

    var privateKey = GetApnsPrivateKey(authKeyPath); 
    var token = JWT.Encode(payload, privateKey, JwsAlgorithm.ES256, header); 
public static CngKey GetApnsPrivateKey(string authKeyPath) 
{ 
    using (var reader = new StreamReader(new FileStream(authKeyPath, FileMode.Open, FileAccess.Read, FileShare.Read))) 
    { 
     var ecPrivateKeyParameters = (ECPrivateKeyParameters)new PemReader(reader).ReadObject(); 
     var x = ecPrivateKeyParameters.Parameters.G.AffineXCoord.GetEncoded(); 
     var y = ecPrivateKeyParameters.Parameters.G.AffineYCoord.GetEncoded(); 
     var d = ecPrivateKeyParameters.D.ToByteArrayUnsigned(); 
     return EccKey.New(x, y, d); 

Code auf meinem Rechner funktioniert nur gut, aber im Server werfen sie diese Ausnahme auf GetApnsPrivateKey Methode:

System.Security.Cryptography.CryptographicException: The requested operation is not supported 

nach wenig Suche im Forum i seinen wegen herausgefunden CNG Key Storage Provider: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376242.aspx?f=255&MSPPError=-2147217396 Jetzt frage ich mich, gibt es eine Möglichkeit, das Problem zu lösen?

+0

'EccKey.New' ist keine NetFx-Methode, also woher kam es/was ist seine Implementierung? – bartonjs

+0

Hallo liebe @ Bartonjs. EccKey.New ist die Cryptography-Bibliotheksmethode. Hier ist der vollständige Pfad der Methode: Security.Cryptography.EccKey.New (x, y, d); – David

Antwort

1

Die Quelle der Ausnahme ist System.Security.Cryptography-Bibliothek in der jose-jwt, also vermeiden Sie es. Da die BouncyCastle-Bibliothek bereits verwendet wird, verwenden Sie sie zum Signieren. Außerdem verwende ich Newtonsoft.Json.JsonConvert (..).

public string GetApnsToken(string authKeyPath, 
Dictionary<string, object> payload, 
Dictionary<string, object> header) 
{ 
    ECPrivateKeyParameters ecPrivateKeyParameters; 
    using (var reader = new StreamReader(new FileStream(authKeyPath, FileMode.Open, FileAccess.Read, FileShare.Read))) 
    { 
     ecPrivateKeyParameters = (ECPrivateKeyParameters)new PemReader(reader).ReadObject(); 
    } 
    byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header)); 
    byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload)); 
    byte[] bytesToSign = Encoding.UTF8.GetBytes(ConcatTokenPartsWithEncoding(headerBytes, payloadBytes)); 

    var signer = new DsaDigestSigner(new ECDsaSigner(), new Sha256Digest()); 
    signer.Init(true, ecPrivateKeyParameters); 
    signer.BlockUpdate(bytesToSign, 0, bytesToSign.Length); 
    byte[] signBytes = signer.GenerateSignature(); 

    return ConcatTokenPartsWithEncoding(headerBytes, payloadBytes, signBytes); 

} 

public static string ConcatTokenPartsWithEncoding(params byte[][] parts) 
{ 
var builder = new StringBuilder(); 
foreach (var part in parts) 
{ 
//encode base64 for Url 
var base64Str = Convert.ToBase64String(part); 
base64Str = base64Str.Split('=')[0]; // Remove any trailing '='s 
base64Str = base64Str.Replace('+', '-'); 
base64Str = base64Str.Replace('/', '_'); 
builder.Append(base64Str).Append("."); 
} 
builder.Remove(builder.Length - 1, 1); 
return builder.ToString(); 
} 
0

Dank Natalyas Beitrag. Ich könnte das Problem so lösen:

 var dateTime = DateTimeOffset.Now; 
     var privateKeyAsBytes = Convert.FromBase64String(authKey); 
     var privateKey = CngKey.Import(privateKeyAsBytes, CngKeyBlobFormat.Pkcs8PrivateBlob); 
     var header = new Dictionary<string, object>() { { "kid", keyID } }; 
     var payload = new Dictionary<string, object>() { { "iss", teamID }, { "iat", dateTime.ToUnixTimeSeconds().ToString() } }; 
     var token = JWT.Encode(payload, privateKey, JwsAlgorithm.ES256, header); 
Verwandte Themen