Hash X509 certificate with SHA 256 in c# - c#

I work on an EBICS implementation in C# and I need to send to my bank the hash of my three certificates in SHA256 format in order to enable EBICS link with it.
I generated them in C# with BouncyCastle and now I have a X509Certificate2 object.
So to hash my certificate I used the following code :
String HashCertificate = Certificat.GetCertHashString();
And he return me the following result :
21952A5F79CA3232A656794EE4532BECF5AE3960
But the length don't match with the lenght of the hash of the bank certificate :
57436AD3D09989ED74F4FCCDBF7668C43F8BF87C933F90B065ED442A22E5B0BF
So I think the GetCertHashString() function return the hash of the certificate in SHA1 format and I have no idea how I can hash it in SHA256.
Can you help me please ?
Thank you in advance

As MSDN says GetCertHashString method always
Returns the SHA1 hash value for the X.509v3 certificate as a hexadecimal string.
regardless of signature algorithm since it is Windows specific thumbprint used internally in certifcates store.
You can calculate any other hash by accessing certificate content from its RawData property, e.g. for SHA256:
using (var hasher = SHA256.Create())
{
var hash = hasher.ComputeHash(cert.RawData);
Console.WriteLine(BitConverter.ToString(hash));
}

Related

Verifying a RSA signature made by Crypto Node.JS in C#

I'm trying to build a web service using Express/NodeJS which signs a piece of information. The signed data is received and verified by a client written in C#. You'll have to forgive my inexperience in cryptography and its associated technologies.
First off, I generate a certificate for the C# client and a private key for the NodeJS application using OpenSSL;
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days
365
In the NodeJS application, I have the following code;
const crypto = require('crypto')
const fs = require('fs')
var pem = fs.readFileSync('./keys/key.pem');
var key = pem.toString('ascii');
var privateKey = crypto.createPrivateKey({
'key': key,
'format': 'pem',
'passphrase': '<PASSPHRASE>',
});
function sign(identifier){
var sign = crypto.createSign('RSA-SHA256');
sign.update(identifier);
var sig = sign.sign(privateKey, 'base64');
return sig;
}
exports.sign = sign;
In this case, the parameter identifier is the data to be signed. The client will receive this, and the signature generated, sig.
In the C# client I have the following snippet;
X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(pub));
using (var sha256 = SHA256.Create())
{
using (var rsa = cert.GetRSAPublicKey())
{
bool results = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Console.WriteLine(results.ToString());
}
}
The pub is the generated certificate in Base64, it is stored in a const string. The data contains the same information as identifier in the NodeJS application, but it's converted to bytes using Convert.FromBase64String(...), and likewise the signature is the data returned from sig in the NodeJS application, only converted from Base64 to byte data.
When all information is inserted, VerifyData() returns false, this leads me to believe that there's some kind of missmatch between the cryptographic configurations of the web service and the client.
Any ideas?
As pointed out in the comments, the problem was that data in the C# client was converted to from Base64 when the data in the NodeJS application read from UTF-8.
The solution was to convert the string using Encoding.UTF8.GetBytes()
Thanks for the quick response!

Encrypt the content using AES and mimekit

I looked at several questions on stackoverflow and I'm not able to find answer pertaining to my requirement. So I'm posting this question:
My requirement says:
The content must be encrypted using AES in FIPS Publication 197 (incorporated by reference in provision 6 of this Standard), and RFC 3565 (incorporated by reference in provision 6 of this Standard).
And it should be signed with RSA algorithm specified in RFC 4056.
I saw this post: MimeKit encrypt Message with AES
CmsRecipient CmsRecipient = new CmsRecipient("mail.cer");
CmsRecipient.EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.AES256 };
to1.Add(CmsRecipient);
var signed = MultipartSigned.Create(ctx, signer, multipart);
var encrypted = ApplicationPkcs7Mime.Encrypt(ctx, to1, signed);
message.Body = MultipartSigned.Create(ctx, signer, encrypted);
It seems like in the above code, we expect the AES key to be part of the "mail.cer" certificate?
How do we encrypt the mail content using AES key and mimekit libraries, provided I've a secret key in the form of a string?

How To verify signature in C# without passing a padding algorithm

I receive a digital signature signed with this algorithm sha256WithRSAEncryption and I want to verify it against a data the only valid way that. I found this:
var x509 = new X509Certificate2(File.ReadAllBytes("cer.cer"));
using (var rsa = x509.GetRSAPublicKey()){
Console.WriteLine(rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
}
But there is no padding used in the signing, so is there is another way to verify the signature without providing a padding?

Encrypting the X509Certificate public Key

All, I am working on IDP initiated web sso for a project and the Service Provider has this requirement to RSA encrypt the AES-128 symmetric key(ECB with PKCS1 padding) and Base64 encode that before adding this to the AttributeStatement section of SAML 2.0 response .My understanding is RSA encryption is asymmetric and the key we have to encrypt is the Service Providers public key.But we dont have SP's public certificate ,so I decided to RSA encrypt our X509Certicate's public key
This is the code I have and it throws a Bad Length Cryptographic exception on calling the Encrypt method on RSACryptoServiceProvider class.Does anyone know what the issue?
using(var rsa = cert.PublicKey.Key as RSACryptoServiceProvider)
{
rsa.KeySize = 1024;
byte[] encryptedKey = rsa.Encrypt(cert.GetPublicKey(),false);
encodedPublicKey = Convert.ToBase64String(encryptedKey);
}
The amount of data that you are able to encrypt using RSA public key must be (I don't know the exact equation) less than the length of the public key.
In case of encrypting AES-128 you will be encrypting 128 bits.

Windows server 2012 "Invalid algorithm specified."

When I try to sign data it always says Invalid algorithm specified. I am using following code:
Here is my Certificate Details.
Please Help me, Thanks.
Instead of
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey;
return csp.SignHash(hash, CryptoConfig.MapNameToOid("SHA256"));
use
using (RSA privateKey = cert.GetRSAPrivateKey())
{
return privateKey.SignHash(hash, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
(Requires .NET 4.6+)
The problem is your RSACryptoServiceProvider object is using the CAPI PROV_RSA_FULL provider, which predates SHA-2. SHA-2 signatures (from the software provider) require the key be in PROV_RSA_AES, a fact mostly controlled by the key creation / PFX import.
There's a workaround you can do for rebinding the provider type to still use the soft-deprecated RSACryptoServiceProvider, but particularly in code like this (where the object does not leave the method) you should switch to using cert.GetRSAPrivateKey() and avoid casting the returned RSA object beyond the algorithm base class.

Categories