sign a request using SHA1 and private.key

MaxPlatinum

Member
Joined
Aug 4, 2023
Messages
18
Programming Experience
1-3
Hello, I have private key like:
C#:
string privateKey = @"-----BEGIN PRIVATE KEY-----
MIICd...............................
hqhPg==
-----END PRIVATE KEY-----";
And request like:
C#:
string request = "<?xml version=\"1.0\" encoding=\"windows-1251\"?><request>...............</request>";
.

I need to write code in C# based on Openssl commands:
Rich (BB code):
openssl dgst –sha1 -out request.sign –sign private.key request.txt
openssl base64 -in request.sign –out request.enc

How to code these commands in C#? I tried a lot of exmaples and didnt get result. Could anyone code it please? How to read private key?
 
Never store private keys in code. There is a high probability that you will check-in that code into a public repository, or you may backup your code in some unsecured location.

Furthermore, never store private keys as strings in code. If you do, someone can jump dump your binaries and find those strings.

Anyway, I recommend using a PEM file or a PFX file, and then use one of the following:
C#:
X509Certificate2.CreateFromPemFile()
X509Certificate2.CreateFromEncryptedPemFile()
X509Certificate2Collection.Import()
and never check-in the .PEM or .PFX file into source control. Or if you do checking in certificates, make sure that you only check-in the public key, or ensure that the there is a password associated with the file that has the private key. (And obviously don't check-in code with the password hardcoded.)
 
Never store private keys in code. There is a high probability that you will check-in that code into a public repository, or you may backup your code in some unsecured location.

Furthermore, never store private keys as strings in code. If you do, someone can jump dump your binaries and find those strings.

Anyway, I recommend using a PEM file or a PFX file, and then use one of the following:
C#:
X509Certificate2.CreateFromPemFile()
X509Certificate2.CreateFromEncryptedPemFile()
X509Certificate2Collection.Import()
and never check-in the .PEM or .PFX file into source control. Or if you do checking in certificates, make sure that you only check-in the public key, or ensure that the there is a password associated with the file that has the private key. (And obviously don't check-in code with the password hardcoded.)

Thank you so much for an advice. I will keep key out of code.
X509Certificate2.CreateFromPemFile()
X509Certificate2.CreateFromEncryptedPemFile()
X509Certificate2Collection.Import() - these are for calling file yes?
And how about to sign request based on private key?
 
You'll have to emulate what `openssl dgst` does. For that you'll need to read the documentation, and also perhaps dig into the openssl source code to see exactly what it does. For example, the documentation says it outputs in hexadecimal, but it makes no mention if the data in hexadecimal is Little Endian or Big Endian. Once you figure out exactly what it does, you can see if there are already built in classes/methods that can do some of the steps at best, or port major parts of OpenSsl into your code at worse.

 
You'll have to emulate what `openssl dgst` does. For that you'll need to read the documentation, and also perhaps dig into the openssl source code to see exactly what it does. For example, the documentation says it outputs in hexadecimal, but it makes no mention if the data in hexadecimal is Little Endian or Big Endian. Once you figure out exactly what it does, you can see if there are already built in classes/methods that can do some of the steps at best, or port major parts of OpenSsl into your code at worse.


Alright? let me read and figure out. Thank you!
 
You'll have to emulate what `openssl dgst` does. For that you'll need to read the documentation, and also perhaps dig into the openssl source code to see exactly what it does. For example, the documentation says it outputs in hexadecimal, but it makes no mention if the data in hexadecimal is Little Endian or Big Endian. Once you figure out exactly what it does, you can see if there are already built in classes/methods that can do some of the steps at best, or port major parts of OpenSsl into your code at worse.

I read and understand but no idea how to do in coding? Could you help for it please?
 
If you understand, then you should have a general idea of how to write an implementation. Show us your code and tell us where you are currently stuck so that we can point you in a direction to get you unstuck.
 
If you understand, then you should have a general idea of how to write an implementation. Show us your code and tell us where you are currently stuck so that we can point you in a direction to get you unstuck.
I tried following, but didnt get same result as Openssl generate it: (.Net Framework 4.5)

C#:
class Program
    {
        static void Main(string[] args)
        {
            string privateKey = "-----BEGIN PRIVATE KEY-----
                KEY.........
                -----END PRIVATE KEY-----";

            string requestData = "<?xml version=\"1.0\" encoding=\"windows-1251\"?><request>...............</request>";

          
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
            
                byte[] queryBytes = Encoding.UTF8.GetBytes(requestData + privateKey);
                byte[] signature = rsa.SignData(queryBytes, new SHA1CryptoServiceProvider());

                string signatureBase64 = Convert.ToBase64String(signature);

                Console.WriteLine("Sign (Base64): " + signatureBase64);
                Console.ReadLine();
            }
        }

    }
 
If you understood the documentation, then why are you using base-64? Base-64 is not hexadecimal.
 
They why are you surprised about the result you are getting if you new the documentation says output should be in hexadecimal, but the code you are trying to use is outputting in base-64? It's like looking at all the Ferarris, and then going to your Honda dealership to buy a Honda and wondering why you don't hava Ferrari.
 
They why are you surprised about the result you are getting if you new the documentation says output should be in hexadecimal, but the code you are trying to use is outputting in base-64? It's like looking at all the Ferarris, and then going to your Honda dealership to buy a Honda and wondering why you don't hava Ferrari.

Hhh, u r right. I am new in coding that’s why just did copy-past
 
Hhh, u r right. I am new in coding that’s why just did copy-past

They why are you surprised about the result you are getting if you new the documentation says output should be in hexadecimal, but the code you are trying to use is outputting in base-64? It's like looking at all the Ferarris, and then going to your Honda dealership to buy a Honda and wondering why you don't hava Ferrari.


Could you help for code please?
 
.Net Framework 4.5 was retired in 2016. You should upgrade.

The private key format you have posted is PEM, starting with .Net 5 this is supported. With this code I get same signed data (request.sign) and base64 string as those two openssl commands in post 1:
C#:
using (var rsa = RSA.Create())
{
    rsa.ImportFromPem(privateKey); // privateKey is a string here, read from PEM file
    var data = System.Text.Encoding.UTF8.GetBytes(requestData);
    var signed = rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
    var b64 = Convert.ToBase64String(signed);
 
}
If you have or can create a PFX from the key and certificate, you should be able to do this in .Net Framework 4.5 (I only tested with 4.8 though)
C#:
using (var cert = new X509Certificate2(@"X:\Cert.pfx")) // args (path, pass) if pfx has password
using (var rsa = (RSACryptoServiceProvider)cert.PrivateKey)
{
    var data = System.Text.Encoding.UTF8.GetBytes(requestData);
    var signed = rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
    var b64 = Convert.ToBase64String(signed);
   
}
 
[I
.Net Framework 4.5 was retired in 2016. You should upgrade.

The private key format you have posted is PEM, starting with .Net 5 this is supported. With this code I get same signed data (request.sign) and base64 string as those two openssl commands in post 1:
C#:
using (var rsa = RSA.Create())
{
    rsa.ImportFromPem(privateKey); // privateKey is a string here, read from PEM file
    var data = System.Text.Encoding.UTF8.GetBytes(requestData);
    var signed = rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
    var b64 = Convert.ToBase64String(signed);
 
}
If you have or can create a PFX from the key and certificate, you should be able to do this in .Net Framework 4.5 (I only tested with 4.8 though)
C#:
using (var cert = new X509Certificate2(@"X:\Cert.pfx")) // args (path, pass) if pfx has password
using (var rsa = (RSACryptoServiceProvider)cert.PrivateKey)
{
    var data = System.Text.Encoding.UTF8.GetBytes(requestData);
    var signed = rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
    var b64 = Convert.ToBase64String(signed);
 
}

Hello, Thank you for reply.
"Create a PFX from the key and certificate", which certificate do you mean, and how to create it? So, to code in 4.5 Framework I have create a pfx, and there is not any other way?
 
Back
Top Bottom