Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ECDsa Signing in .Net Core on Linux

I'm trying to create a C# implementation to send Pushes to Apple via their HTTP/2 APNS Endpoint with .Net core in Docker. Part of this requires sending an encrypted JWT Authorization Token along with the payload. With .Net core, I can sign the token when running on Windows, but when running in the Linux Docker image, it tips over loading the Key.

When running in the .net Core Docker Image, I get a platformnotsupported Exception on loading the key.

    public static string SignES256(string privateKey, string header, string payload)
    {

        // This is the failing Call
        CngKey key = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);

        using (ECDsaCng dsa = new ECDsaCng(key))
        {
            var unsignedJwtData =
                System.Convert.ToBase64String(Encoding.UTF8.GetBytes(header)) + "." + System.Convert.ToBase64String(Encoding.UTF8.GetBytes(payload));
            var unsignedJwtDataBytes = Encoding.UTF8.GetBytes(unsignedJwtData);

            var signature =
                dsa.SignData(unsignedJwtDataBytes, 0, unsignedJwtDataBytes.Length, HashAlgorithmName.SHA256 );
            return unsignedJwtData + "." + System.Convert.ToBase64String(signature);
        }
    }

How can I do this from .Net Core on Linux?

Thanks.

like image 883
JoelHess Avatar asked May 15 '17 16:05

JoelHess


People also ask

Can Kestrel run on Linux?

Net applications run on Kestrel servers and we run Apache or Nginx server in Linux environments, which acts as a proxy server and handles the traffic from outside the machine and redirects it to the Kestrel server so we will have Apache or Nginx server as the middle layer.

Can I host ASP.NET Core on Linux?

Install the necessary dependencies and .NET Core Framework to host the ASP.NET Core application in the Linux Ubuntu server. Before installing the . NET Framework, we need to install its dependencies. Now, install the ASP.NET Core runtime network that is used to run the publishing app.

Can we deploy .NET application on Linux server?

The beauty of . Net Core is that it is cross-platform and you can run it on Windows, Linux, or MAC. So you can develop your web API on your favorite OS like Windows or MAC and host it on a Linux machine.


1 Answers

Update: As of .NET Core 3.0, cross-platform PKCS is now built into the framework.

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

Original Answer:

As others have pointed out, BouncyCastle is a cross-platform alternative to Windows CNG. None of the other examples out there were quite working for me, though. Maybe this will help someone:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
  </ItemGroup>

</Project>

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;

public class ApnsTokenProvider
{
    private readonly JwtSecurityTokenHandler _tokenHandler = new JwtSecurityTokenHandler();

    // Turn off caching so TokenHandler doesn't try to reuse disposed algorithms.
    private readonly CryptoProviderFactory _signingFactory = new CryptoProviderFactory
    {
        CacheSignatureProviders = false
    };

    public string GetToken(string teamId, string keyId, string privateKey)
    {
        using (var algorithm = GetEllipticCurveAlgorithm(privateKey))
        {
            var credentials = new SigningCredentials(new ECDsaSecurityKey(algorithm)
            {
                KeyId = keyId,
                CryptoProviderFactory = _signingFactory
            }, SecurityAlgorithms.EcdsaSha256);

            return _tokenHandler.CreateEncodedJwt(new SecurityTokenDescriptor
            {
                Issuer = teamId,
                SigningCredentials = credentials
            });
        }
    }

    private static ECDsa GetEllipticCurveAlgorithm(string privateKey)
    {
        var keyParams = (ECPrivateKeyParameters)PrivateKeyFactory
            .CreateKey(Convert.FromBase64String(privateKey));

        var q = keyParams.Parameters.G.Multiply(keyParams.D).Normalize();

        return ECDsa.Create(new ECParameters
        {
            Curve = ECCurve.CreateFromValue(keyParams.PublicKeyParamSet.Id),
            D = keyParams.D.ToByteArrayUnsigned(),
            Q =
            {
                X = q.XCoord.GetEncoded(),
                Y = q.YCoord.GetEncoded()
            }
        });
    }
}
like image 88
Kyle McClellan Avatar answered Sep 18 '22 15:09

Kyle McClellan