1

For the communication between a c# dotnet-core application (windows and linux) and Chef.io API I need to be able to create the same signature within c# dotnet core as this call of openssl executable:

openssl rsautl -in encryption.txt -sign -inkey chefprivatekey.pem | openssl enc -base64

The first implementation (dotnet framework) was based on this https://github.com/mattberther/dotnet-chef-api:

        byte[] input = Encoding.UTF8.GetBytes(canonicalHeader);

        var pemReader = new PemReader(new StringReader(privateKey));
        AsymmetricKeyParameter key = ((AsymmetricCipherKeyPair)pemReader.ReadObject()).Private;

        ISigner signer = new RsaDigestSigner(new NullDigest());
        signer.Init(true, key);
        signer.BlockUpdate(input, 0, input.Length);
        _signature = Convert.ToBase64String(signer.GenerateSignature());

The nuget package dotnet-chef-api contains also an old version of BouncyCastle.Crypto.dll. As long as I use this dll everyting works fine but if I do an update of the dll to a newer verion by using a nuget-package for this, nothing is working any more. As a workaround I have Implemented a system-call of openssl executable to get the correct signature for the API. This works fine. But I need to get rid of the system-calls. What I have done now is to compare the system call result of openssl exe with the results I get from any signing algorythms like BouncyCastle lib. I have not been able to get the same result as the above mentioned call of openssl-exe. The implementation needs to be dotnet-core for Windows and Linux. As long as the the results between openssl exe and any c# implementation are not the same I don't neet to test the chef-api. I was able to create System.Security.Cryptography.RSACryptoServiceProvider from the pem file folloging this example: How to load the RSA public key from file in C#. with this Code I am alble to get an object of type RSACryptoServiceProvider from the pem file.

        RSACryptoServiceProvider provider = PemKeyUtils.GetRSAProviderFromPemFile(pemFile);
        var trial1 = Convert.ToBase64String(provider.SignData(Convert.FromBase64String("test"), new SHA1CryptoServiceProvider()));

The content of "trial1" is the same as "_signature" but not the same as from openssl.exe What I am doing wrong?

"openssl rsautl" by default uses PKCS#1 v1.5 could this be a problem?

TvG71
  • 21
  • 3

1 Answers1

1

Found a solution on my own. I had a look into the Unittests of BouncyCastle and got now this as a working solition:

public string Sign(byte[] input, string privateKeyPath)
    {
        asymmetricKeyParameter AsymmetricKeyParameterFromPrivateKeyInPemFile
        // Sign the hash

        IBufferedCipher c = CipherUtilities.GetCipher("RSA//PKCS1Padding");

        c.Init(true, asymmetricKeyParameter);

        var outBytes = c.DoFinal(input);
        return Convert.ToBase64String(outBytes);
    }

    public AsymmetricKeyParameter AsymmetricKeyParameterFromPrivateKeyInPemFile(string privateKeyPath)
    {
        using (TextReader privateKeyTextReader = new StringReader(File.ReadAllText(privateKeyPath)))
        {
            PemReader pr = new PemReader(privateKeyTextReader);
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
            return keyPair.Private;
        }
    }
TvG71
  • 21
  • 3