I have a smartcard and I need to sign a file with this. That is a big problem as I see in stackover.
I couldnt use RSACryptoServiceProvider, bkz it doesnt support RSA-SHA256 alogrithm.
At First I used CAPICOM.dll , like code bellow,
SignedData sed = new SignedData();
sed.Content = "a"; // data to sign
Signer ser = new Signer();
ser.Certificate = cc;
string singnn = sed.Sign(ser, false, CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);
But there isnt a public key to validate my signature value,, I couldnt get a validate key from capicom.dll.
And after ,
I used X509Certificate2 , and RSACryptoServiceProvider like code below,
X509Certificate2 certificate = new X509Certificate2();
// Access Personal (MY) certificate store of current user
X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
my.Open(OpenFlags.ReadOnly);
// Find the certificate we'll use to sign
RSACryptoServiceProvider csp = null;
foreach (X509Certificate2 cert in my.Certificates)
{
if (cert.Subject.Contains(certSubject))
{
// We found it.
// Get its associated CSP and private key
certificate = cert;
csp = (RSACryptoServiceProvider)cert.PrivateKey;
}
}
if (csp == null)
{
throw new Exception("No valid cert was found");
}
// Hash the data
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
//byte[] data = Encoding.UTF8.GetBytes(text);
//HashAlgorithm sha = new SHA256Managed();
//byte[] hash = sha.TransformFinalBlock(data, 0, data.Length);
string key = csp.ToXmlString(false);
// Sign the hash
csp.PersistKeyInCsp = true;
byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
string signbase64 = Convert.ToBase64String(response);
It works , but I need to sign with RSA-SHA256 algorithm. When I changw hash algorithm like this
byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
I m getting an
error : "unspecified error".
Thats my problem, What is the sollution , or which library should I use ??
Thanks for any advice..
SHA 256 converts data into fixed-length, virtually irreversible hash values, and is mainly used to verify the authenticity data. As we mentioned earlier, no one has been able to crack SHA 256 to date, and it's used in some of the most secure networks in the world.
While SHA-256 has valid use cases, it is not really meant to be used in hashing passwords. While collisions have not been proven, and unique salts can make rainbow tables ineffective, high-end hardware can still generate billions of SHA-256 hashes every minute.
About Signature Hashing There are three supported algorithms: SHA-1 - The default hashing algorithm applied to each signature item in the configuration. SHA-256 - A more complex, but slower hashing algorithm when compared with SHA-1. Adler-32 - A lighter weight hashing algorithm when compared to SHA-1.
RSACryptoServiceProvider does work with SHA2-based signatures, but you have to invest some effort into it.
When you use a certificate to get your RSACryptoServiceProvider it really matters what's the underlying CryptoAPI provider. By default, when you create a certificate with 'makecert', it's "RSA-FULL" which only supports SHA1 hashes for signature. You need the new "RSA-AES" one that supports SHA2.
So, you can create your certificate with an additional option: -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (or an equivalent -sy 24) and then your code would look like (in .NET 4.0):
var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
//
byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));
If you are unable to change the way your certificate is issued, there is a semi-ligitimate workaround that is based on the fact that by default RSACryptoServiceProvider is created with support for SHA2. So, the following code would also work, but it is a bit uglier: (what this code does is it creates a new RSACryptoServiceProvider and imports the keys from the one we got from the certificate)
var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
// Create a new RSACryptoServiceProvider
RSACryptoServiceProvider rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
rsaClear.ImportParameters(rsa.ExportParameters(true));
byte[] signature = rsaClear.SignData(data, CryptoConfig.CreateFromName("SHA256"));
Hope you find this helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With