How to do signature using SHA256withRSA algorithm in C#
Asked Answered
M

3

6

I tried search solution to my query, I couldn't able find match I am looking for, this is very basic, but to my better understanding I am posting below query.

I want to encode and do signature for my string using "SHA256withRSA" algorithm. I could able to see lot of sample code in java using "SHA256withRSA" but in C# I could see first we are hashed data using SHA256 then we are sign hash using RSACryptoServiceProvider.

My questions are:

  1. In C# we have separate algorithm of "SHA256withRSA", If yes, help with sample code.

  2. If no then what would be better approach to achieve it in C#?

Mig answered 9/9, 2019 at 9:52 Comment(0)
C
6

Do not use RSACryptoServiceProvider unless you are doing interop with CAPI, like opening a named key.

To do RSA signing with SHA-(2-)256:

byte[] signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

You can get the RSA object from a cert:

using (RSA rsa = cert.GetRSAPrivateKey())
{
    ...
}

Or you can make one up from existing RSA parameters:

using (RSA rsa = RSA.Create(rsaParameters))
{
   ...
}

Or you can make up a new key from nothing:

using (RSA rsa = RSA.Create(2048))
{
    // you’ll need to save the parameters somewhere to have a stable key
    rsaParameters = rsa.ExportParameters(true));
    ...
}
Coloratura answered 9/9, 2019 at 20:29 Comment(1)
I am having trouble connecting all the dots here. Could someone please provide the full solution all in one file?Queenhood
N
7

First of all, you need a key pairs. To generate a key pairs you can do as the following and using OpenSSL:

  1. Generate a private key

    openssl genrsa -out my-private-key.pem 2048

  2. Generate a public cert

    openssl req -new -key my-private-key.pem -x509 -days 36500 -out my-public-cert.pem

  3. Generate a p12 file

    openssl pkcs12 -export -in my-public-cert.pem -inkey my-private-key.pem -out my-key-pairs.p12

Now you can use the following sample code in C#.NET to create a digital signature and verify a digital signature

    public static string SignData(byte[] data, string pkcs12File, string pkcs12Password)
    {
        X509Certificate2 signerCert = new X509Certificate2(pkcs12File, pkcs12Password, X509KeyStorageFlags.Exportable);
        RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider();
        rsaCSP.FromXmlString(signerCert.PrivateKey.ToXmlString(true));
        var SignedData = rsaCSP.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
        return Convert.ToBase64String(SignedData);
    }

    public static bool VerifySignature(byte[] data, string signature, string publicCert)
    {
        X509Certificate2 partnerCert = new X509Certificate2(publicCert);
        RSACryptoServiceProvider rsaCSP = (RSACryptoServiceProvider)partnerCert.PublicKey.Key;
        return rsaCSP.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), Convert.FromBase64String(signature));
    }

Remember that your project need to add reference to System.Security

Nugent answered 4/3, 2021 at 9:53 Comment(0)
C
6

Do not use RSACryptoServiceProvider unless you are doing interop with CAPI, like opening a named key.

To do RSA signing with SHA-(2-)256:

byte[] signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

You can get the RSA object from a cert:

using (RSA rsa = cert.GetRSAPrivateKey())
{
    ...
}

Or you can make one up from existing RSA parameters:

using (RSA rsa = RSA.Create(rsaParameters))
{
   ...
}

Or you can make up a new key from nothing:

using (RSA rsa = RSA.Create(2048))
{
    // you’ll need to save the parameters somewhere to have a stable key
    rsaParameters = rsa.ExportParameters(true));
    ...
}
Coloratura answered 9/9, 2019 at 20:29 Comment(1)
I am having trouble connecting all the dots here. Could someone please provide the full solution all in one file?Queenhood
S
0
public static string EncryptMessage(string message, string keyLocation) 
{ 
    byte[] encryptedData; 
    using (System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider()) 
    { 
        using (var stream = File.OpenRead(keyLocation)) 
            { 
                using (var reader = new PemUtils.PemReader(stream)) 
                { 
                System.Security.Cryptography.RSAParameters rsaParameters = reader.ReadRsaKey(); 
                rsa.ImportParameters(rsaParameters); 
                } 
            } 
        byte[] dataToEncrypt = System.Text.Encoding.UTF8.GetBytes(message); 
        encryptedData = rsa.SignData(dataToEncrypt, new System.Security.Cryptography.SHA256CryptoServiceProvider()); 
    }
    return Convert.ToBase64String(encryptedData); 
}
Sharondasharos answered 14/2, 2023 at 15:15 Comment(2)
Please, add some explanations, to help future reader to understand how your snippet may solve the issue.Wader
Sorry, I thought it’s pretty much self-explanatory. So, the function returns Base64 encrypted string - result of locking message with the .pse key based on the some location (function receives message (which should be encrypted) and key location (which will be used for ‘locking’. Also, nuget package Pem Util is being used.Sharondasharos

© 2022 - 2024 — McMap. All rights reserved.