3

I'm trying to generate a JWT token using Jose.JWT.encode(payload, secretKey, JwsAlgorithm.ES256, header) (see https://github.com/dvsekhvalnov/jose-jwt) to use with Apple's new token-based APNs system.

The JWT encode method requires the secretKey to be in CngKey format. Here's my code converting the .p8 file from Apple to a CngKey object:

        var privateKeyContent = System.IO.File.ReadAllText(authKeyPath);
        var privateKey = privateKeyContent.Split('\n')[1];

        //convert the private key to CngKey object and generate JWT

        var secretKeyFile = Convert.FromBase64String(privateKey);
        var secretKey = CngKey.Import(secretKeyFile, CngKeyBlobFormat.Pkcs8PrivateBlob);

However, on the last line, the following error is thrown.

System.Security.Cryptography.CryptographicException was unhandled by user code
  HResult=-2146885630
  Message=An error occurred during encode or decode operation.

  Source=System.Core
  StackTrace:
       at System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle provider, Byte[] keyBlob, String format)
       at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, String curveName, CngKeyBlobFormat format, CngProvider provider)
       at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat format)
       at tokenauthapi.App_Start.TokenInitSendMessage.<send>d__0.MoveNext() in C:\token-push-prototype\token-auth-api\token-auth-api\App_Start\TokenInitSendMessage.cs:line 31
  InnerException: 

The input isn't in the wrong format as there's a separate error for that (that appears when I change the blob type).

This code is running in a .NET WebApi v4.6.

I've searched high and low but haven't been able to decipher what this error is referring to. Any help would be greatly appreciated. Thank you.

Helen
  • 727
  • 8
  • 13

3 Answers3

6

The security key (p8) provided by Apple for DeviceCheck also contained newlines. I used the following to get a valid CngKey:

var privateKeyContent = File.ReadAllText("pathToApplePrivateKey.p8");
var privateKeyList = privateKeyContent.Split('\n').ToList();
var privateKey = privateKeyList.Where((s, i) => i != 0 && i != privateKeyList.Count - 1)
                                   .Aggregate((agg, s) => agg + s);

CngKey key = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
Scott Wood
  • 364
  • 5
  • 11
2

Turns out the .p8 file I was using had newlines in the middle of it for some reason. Possible that notepad added it (and saved it?). I was splitting by newlines to get the private key and therefore it was truncating the key. Once I removed the newlines it worked fine.

If you get the error occurred during encode or decode operation error, check whether your .p8 (or other) private key is malformed and is the right length.

Helen
  • 727
  • 8
  • 13
1

I met the same issue. I use this:

var privateKey = privateKeyContent.Split('\n')[1];

Then I analyze token file downloaded from Apple. I found there are more \n in the file. I am not sure where this format is different or apple changed. Then I use the following codes to load the token, works. Actually, we can directly use this token string.

var privateKeyContent = System.IO.File.ReadAllText(authKeyPath);
var privateKeyList = privateKeyContent.Split('\n');
int upperIndex = privateKeyList.Length;
StringBuilder sb = new StringBuilder();
for(int i= 1; i< upperIndex - 1; i++ )
{
    sb.Append(privateKeyList[i]);
    Debug.WriteLine(privateKeyList[i]);
}
dferenc
  • 7,918
  • 12
  • 41
  • 49
Frank Yan
  • 371
  • 2
  • 8