如何编码 JWT 以进行 APN 标记化(.NET、C#)

How to encode JWT for APN tokenization (.NET, C#)

我正在尝试通过标记化将推送通知发送到 APN。我尝试使用一些库,如 jose-jwt 和 Microsot Jwt class 来创建 JWT 令牌,但我无法理解它。

我在创建 JWT 并使用私钥签名时卡住了。

为了与证书通信,我使用了 PushSharp,它工作得很好。任何人都可以帮我解决一个类似的工作示例但使用令牌吗?

编辑:在此处遵循 Apple 文档:https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1

示例代码:我最接近的是这样的,但我不知道如何正确创建 CngKey

var payload = new Dictionary<string, object>()
            {
                { "iss", issuer },
                { "iat", DateTime.UtcNow }
            };

var headers = new Dictionary<string, object>()
            {
                 { "kid", keyIdentifier}
            };

CngKey key = CngKey.Create(CngAlgorithm.ECDsaP256); //how to create this CngKey

string token = Jose.JWT.Encode(payload, key, JwsAlgorithm.ES256, headers);

这是我使用的:

var privateKeyContent = System.IO.File.ReadAllText(AUTHKEYFILE);
var privateKey = privateKeyContent.Split('\n')[1];
var secretKeyFile = Convert.FromBase64String(privateKey);
var secretKey = CngKey.Import(secretKeyFile,CngKeyBlobFormat.Pkcs8PrivateBlob);

感谢您的回答,必须联系许多支持人员才能完成这项工作。这是最终结果的样子。

/// <summary>
    /// Method returns ECDSA signed JWT token format, from json header, json payload and privateKey (pure string extracted from *.p8 file - PKCS#8 format)
    /// </summary>
    /// <param name="privateKey">ECDSA256 key</param>
    /// <param name="header">JSON header, i.e. "{\"alg\":\"ES256\" ,\"kid\":\"1234567899"\"}"</param>
    /// <param name="payload">JSON payload, i.e.  {\"iss\":\"MMMMMMMMMM"\",\"iat\":"122222222229"}"</param>
    /// <returns>base64url encoded JWT token</returns>
    public static string SignES256(string privateKey, string header, string payload)
    {
        CngKey key = CngKey.Import(
            Convert.FromBase64String(privateKey), 
            CngKeyBlobFormat.Pkcs8PrivateBlob);

        using (ECDsaCng dsa = new ECDsaCng(key))
        {
            dsa.HashAlgorithm = CngAlgorithm.Sha256;
            var unsignedJwtData = 
                Url.Base64urlEncode(Encoding.UTF8.GetBytes(header)) + "." + Url.Base64urlEncode(Encoding.UTF8.GetBytes(payload));
            var signature = 
                dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
            return unsignedJwtData + "." + Url.Base64urlEncode(signature);
        }
    }

这是我用的;

public static string getAppleJWT(string privateKeyPath, string teamId, string keyId)
{

    var private_key = getPrivateKey(privateKeyPath);

    var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    var issueTime = DateTime.Now;

    var payload = new Dictionary<string, object>()
        {
            { "iss", teamId },
            { "iat", (int)issueTime.Subtract(utc0).TotalSeconds }
        };

    var headers = new Dictionary<string, object>()
        {
             { "alg", "ES256"},
             { "kid", keyId}
        };


    return Jose.JWT.Encode(payload, private_key, JwsAlgorithm.ES256, headers);
}

public static CngKey getPrivateKey(string privateKeyPath)
{
    var privateKeyLines = System.IO.File.ReadAllLines(privateKeyPath).ToList();
    privateKeyLines.RemoveAt(privateKeyLines.Count - 1);
    privateKeyLines.RemoveAt(0);

    var privateKey = string.Join("", privateKeyLines);
    var secretKeyFile = Convert.FromBase64String(privateKey);
    var secretKey = CngKey.Import(secretKeyFile, CngKeyBlobFormat.Pkcs8PrivateBlob);
    return secretKey;
}

如果您想 运行 在 MacOS 或 linux 中使用您的应用程序,则不能使用 CngKey 在这种情况下你可以使用 编码JWT的ECDsa算法

private ECDsa encoder(string privateKey)
{
 var result = ECDsa.Create();
 result.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out _);
 return result;
}