0

I have to sign messages for a web service. The service uses OpenSSL MD5 signatures. I generate the OpenSSL one from a PEM private key file:

openssl.exe dgst -md5 -hex -out signature.txt -sign privKey.pem textToSign.txt

Which generates the following signature:

7078388bd081d4b805feb020ab47352320919e4638e36b59d66a684c9bb12a745aaf172e4da2686c3e3750bf627c980a19700f6d8bbd0b62d8714a965a34be2e9f4147ac054c4af1050cdcebd9b475f0ef28e520681b0d67104b8e633ee592bb3ec2c517fb8cf7b13bd86424f00c89518e063d55e7922adab7cf607c85920862

I want to implement this in my code. My actual code looks like (the private key in the pfx file is the same as the one in the pem file):

private static string Sign(string stringToSign)
{
    X509Certificate2 cert = new X509Certificate2("keys.pfx", "", X509KeyStorageFlags.Exportable);
    byte[] data = Encoding.UTF8.GetBytes(stringToSign);
    byte[] signedData;
    using (MD5 hasher = MD5.Create())
    using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey)
    {
        signedData = rsa.SignData(data, hasher);
    }
    return Convert.ToBase64String(signedData);
}

This code produces the following signature...

cHg4i9CB1LgF/rAgq0c1IyCRnkY442tZ1mpoTJuxKnRarxcuTaJobD43UL9ifJgKGXAPbYu9C2LYcUqWWjS+Lp9BR6wFTErxBQzc69m0dfDvKOUgaBsNZxBLjmM+5ZK7PsLFF/uM97E72GQk8AyJUY4GPVXnkirat89gfIWSCGI=

...which does not match the OpenSLL one. What should I do to match the OpenSSL one? Also I tried to use OpenSSL.NET, but I did not find any resources/tutoral for signing.

SOLVED

The correct code is:

    private static string Sign(string stringToSign)
    {
        X509Certificate2 cert = new X509Certificate2("#02299991.pfx", "#02299991", X509KeyStorageFlags.Exportable);
        byte[] data = Encoding.UTF8.GetBytes(stringToSign);
        byte[] signedData;
        using (MD5 hasher = MD5.Create())
        using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey)
        {
            signedData = rsa.SignData(data, hasher);
        }
        return ByteArrayToString(signedData); //Convert.ToBase64String(signedData);
    }

    public static string ByteArrayToString(byte[] signedBytes)
    {
        StringBuilder hex = new StringBuilder(signedBytes.Length * 2);
        foreach (byte b in signedBytes)
            hex.AppendFormat("{0:x2}", b);
        return hex.ToString();
    }
Arszi
  • 27
  • 10
  • Consider replacing MD5 with SHA-2. The collision attacks against MD5 can lead to practical attacks against digital signatures building on top of MD5. – CodesInChaos Jun 23 '14 at 16:42
  • It is not my choice, I have to cooperate with a "legacy" service. – Arszi Jun 24 '14 at 08:36

1 Answers1

3

Your OpenSSL output is a hex string:

openssl.exe dgst -md5 -hex -out signature.txt -sign privKey.pem textToSign.txt
                       ^

While your C# output is in Base64:

return Convert.ToBase64String(signedData);
               ^

Convert your byte[] output to a hex string:

Community
  • 1
  • 1
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328