如何编码 JWT 以进行 APN 标记化(.NET、C#)
How to encode JWT for APN tokenization (.NET, C#)
我正在尝试通过标记化将推送通知发送到 APN。我尝试使用一些库,如 jose-jwt 和 Microsot Jwt class 来创建 JWT 令牌,但我无法理解它。
我在创建 JWT 并使用私钥签名时卡住了。
为了与证书通信,我使用了 PushSharp,它工作得很好。任何人都可以帮我解决一个类似的工作示例但使用令牌吗?
示例代码:我最接近的是这样的,但我不知道如何正确创建 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;
}
我正在尝试通过标记化将推送通知发送到 APN。我尝试使用一些库,如 jose-jwt 和 Microsot Jwt class 来创建 JWT 令牌,但我无法理解它。
我在创建 JWT 并使用私钥签名时卡住了。
为了与证书通信,我使用了 PushSharp,它工作得很好。任何人都可以帮我解决一个类似的工作示例但使用令牌吗?
示例代码:我最接近的是这样的,但我不知道如何正确创建 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;
}