【问题标题】:System.Security.Cryptography.CryptographicException: The requested operation is not supported. windows server 2012System.Security.Cryptography.CryptographicException:不支持请求的操作。窗口服务器 2012
【发布时间】:2017-12-31 12:31:28
【问题描述】:

我厌倦了生成用于调用 apns 的 jwt 令牌。这是我的代码:

    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);

代码在我的机器上运行得很好,但是在服务器上它在GetApnsPrivateKey 方法上抛出了这个异常:

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

在论坛上进行少量搜索后,我发现它是因为 CNG 密钥存储提供商:https://msdn.microsoft.com/en-us/library/windows/desktop/aa376242.aspx?f=255&MSPPError=-2147217396 现在我想知道有什么办法可以解决这个问题吗?

【问题讨论】:

  • EccKey.New 不是 NetFx 方法,那么它从何而来/它的实现方式是什么?
  • 你好亲爱的@bartonjs。 EccKey.New 是 Cryptography 库方法。这是方法的完整路径:Security.Cryptography.EccKey.New(x, y, d);

标签: c# encryption cryptography public-key-encryption cng


【解决方案1】:

异常的来源是 jose-jwt 中的 System.Security.Cryptography 库,因此请避免使用它。 由于 BouncyCastle 库已在此处使用,请使用它进行签名。 另外,我使用 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();
}

【讨论】:

    【解决方案2】:

    感谢 Natalya 的帖子。我可以这样解决问题:

            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);
    

    【讨论】:

    • 嗨,这个例子中的 authKey 是什么?我有与您相同的代码,但不确定如何更改为您在此处显示的内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-24
    • 2019-03-20
    相关资源
    最近更新 更多