6

I have the following problem, and cant find solution:

While consuming APN (Apple push notifications) API, i implemented tokenized authorization. It's apple's new way of authorization on their push notifications api.

Apple provides me private key, which i use to create c# CngKey object, which then i use to sign data.

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

The result is signed token, which i then use as authorization header while consuming API and sending push notifications.

It works well on my dev machine, but when i deploy it to Windows Server, when this code runs i get next:

System.ArgumentException: Keys used with the ECDsaCng algorithm must have an algorithm group of ECDsa.
Parameter name: key
   at System.Security.Cryptography.ECDsaCng..ctor(CngKey key)
   at OTTCommon.Encryption.ECDSA.SignES256(String privateKey, String header, String payload, ILog log)

I cant find solution, it is something with windows key storage or something like that....

What should i do?

MIslavMIslav
  • 93
  • 1
  • 8

1 Answers1

7

This is fixed in the .NET Framework 4.6.2, so the easiest solution would perhaps be to get the server upgraded.

A workaround that works for NIST P-256, NIST P-384, and NIST P-521 is to change the dwMagic value in the blob export. (It won't work for the Windows 10 Generic ECC, because the dwMagic values aren't aligned the same way).

byte[] blob = key.Export(CngKeyBlobFormat.EccPrivateBlob);
key.Dispose();

The first 4 bytes of this blob map to the dwMagic value in the BCRYPT_ECCKEY_BLOB structure.

BCRYPT_ECDH_PRIVATE_P256_MAGIC has value 0x324B4345, which is the Little-Endian representation of "ECK2" (Elliptic Curve Key-exchange 2). BCRYPT_ECDSA_PRIVATE_P256_MAGIC has value 0x32534345, which is the Little-Endian representation of "ECS2" (Elliptic Curve Signing 2).

// Change it from Key-exchange (ECDH) to Signing (ECDSA)
blob[1] = 0x53;

key = CngKey.Import(blob, CngKeyBlobFormat.EccPrivateBlob);

And now it sees that it's an ECDSA key, and everything is happy.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • 2
    Thanks very much on quick response! Didn't expect it so soon :) Anyhow, i got version 4.6.2 on my dev machine, and server has 4.6.1. and we will try to upgrade the server to 4.6.2 net version, and see if that solves the problem. Just as info, workaround does not work on my machine (Win7), i get "The requested operation is not supported." exception. – MIslavMIslav May 16 '17 at 06:28
  • 2
    It worked when i upgraded windows server 2012r2 .NET version to 4.6.2! Problem solved, thank you very much! – MIslavMIslav May 16 '17 at 07:43