Signing data with private key in c#

2019-01-15 18:02发布

问题:

I need to sign some data with one private key using Algorithm SHA1RSA ,Rsa Key length 2048 with 64 base encoding.My code is like this

       string sPayload = "";
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("URI");
        httpWebRequest.ContentType = "application/json; charset=utf-8";
        httpWebRequest.Method = WebRequestMethods.Http.Post;

        using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            sPayload = "{\"id\":\"14123213213\"," +
                         "\"uid\":\"teller\"," +
                         "\"pwd\":\"abc123\"," +
                         "\"apiKey\":\"2343243\"," +

                          "\"agentRefNo\":\"234324324\"}";

          httpWebRequest.Headers.Add("SIGNATURE", Convert.ToBase64String(new System.Security.Cryptography.SHA1CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(sPayload))));

            streamWriter.Write(sPayload);
            streamWriter.Flush();
            streamWriter.Close();
        }
        System.Net.ServicePointManager.Expect100Continue = false;

        HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

        using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            string result = streamReader.ReadToEnd();
        }

In the Header name Signature i need to pass the signed data(sPayload) using the private key.But using above code an error is getting as "invalid signature" from third party and i'am not sure whether the Encryption part is correct or not.

httpWebRequest.Headers.Add("SIGNATURE", Convert.ToBase64String(new System.Security.Cryptography.SHA1CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(sPayload))));

Third party had provide one certificate(cert,sha1) and key.should i refer that to the code?

回答1:

You have computed the SHA-1 hash of sPayload, not the RSA-SHA1 signature.

If you have an X509Certificate2:

using (RSA rsa = cert.GetRSAPrivateKey())
{
    return rsa.SignData(sPayload, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
}

If you already have a raw RSA key then just leave off the using statement.

If you have to compute the hash of sPayload for some other reason you can do it like

byte[] hash;
byte[] signature;

using (HashAlgorithm hasher = SHA1.Create())
using (RSA rsa = cert.GetRSAPrivateKey())
{
    hash = hasher.ComputeHash(sPayload);
    signature = rsa.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
}

SignHash still requires the HashAlgorithmName value because the algorithm identifier is embedded within the signature.