Dear Ugo,
I have been struggling for long time to get my soap message signature is validated. Below you can see my input which is SHA256 hash of my data.
7/X3PTLCL0QU/vU6/ZlHn58Z7AfD1dPsa2hB+7B2khA=
Below the method signs the hash with the local certificate.
private static string SignLocal(byte[] data)
{
X509Certificate2 certificate = X509Certificate2_Cryptographer.LoadCertificate(StoreLocation.CurrentUser, "CN=e-Fatura Deneme A.Ş., SERIALNUMBER=9999999999, OU=e-Fatura Deneme A.Ş.");
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(certificate.PrivateKey.ToXmlString(true));
//byte[] signed = key.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
byte[] signed = key.SignHash(data, CryptoConfig.MapNameToOID("SHA256"));
//if (!key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), signed))
// throw new CryptographicException();
return Convert.ToBase64String(signed);
}
This method returns the result below and this results is validated successfully by the recipient.
NhTAmthbcI1HlGiaGEgmj2qj1/gDJcqZInPwwuMkZFVKIHL3mhxvwUBd7EPYGGeTq4fAr+oNXzYBZYwXHWReoO872I9FeyJlBfZg7VwmbXkMcCAtfkFualbxw+VGcX00w3zH1eOo4tNlXukIuhaBqzLIEuu7kke5rAEpdxMCF3mSTe9EtTc/Mzk4uY1Qo2D1heV8Wv1GUJf3X2azTwxAL8oM3VcI4i4PyC6BgyStczecLtFaNFmPVGQKqCxu1nDMaNBUDIcP69rq1qJ4iFuzOk2DuwsG1WJnacrr914aPQHb10MfoQRM35rTQMEHkB4wvkKNfFqZAGWWPorBg9RhUg==
In second method below NCyrptoki Library is used. We can validate the result locally and please check the result just under the code. (Excuse me for the messy code! It is just for debugging purposes)
using Cryptware.NCryptoki;
using System;
using System.Collections.Generic;
using System.Text;
namespace DigestTest
{
public class SignerNCryptoki : IDisposable
{
public byte[] INPUT;
public byte[] OUTPUT;
//String moduleName = "akisp11.dll";
String moduleName = "vcki.dll";
Cryptoki module;
Session session = null;
public string SignMessage(byte[] s)
{
try
{
module = new Cryptoki(moduleName);
int nRet = module.Initialize();
if (nRet != 0)
{
return "";
}
INPUT = s;
if (module.Slots.Count == 0)
{
Console.WriteLine("No slot with present token found!");
throw new Exception("No token found!");
}
Slot selectedSlot = module.Slots[0];
Token token = selectedSlot.Token;
TokenInfo tokenInfo = token.Info;
session = token.OpenSession(Session.CKF_SERIAL_SESSION | Session.CKF_RW_SESSION, null, null);
var ret = session.Login(Session.CKU_USER, "123456");
if (ret != 0 || !session.IsLoggedIn) throw new Exception("Login başarısız. Pinlock e dikkat!.....");
// Searchs for an RSA private key object
// Sets the template with its attributes
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_SIGN, true));
// Launchs the search specifying the template just created
CryptokiCollection objects = session.Objects.Find(template, 10);
RSAPrivateKey privateKey = null;
// If the private keys is found continue
if (objects.Count > 0)
{
privateKey = (RSAPrivateKey)objects[0];
}
template.Clear();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PUBLIC_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
// Launchs the search specifying the template just created
objects = session.Objects.Find(template, 10);
RSAPublicKey publicKey = null;
// If the private keys is found continue
if (objects.Count > 0) publicKey = (RSAPublicKey)objects[0];
Mechanism m = new Mechanism(Mechanism.CKM_SHA256,null);
session.DigestInit(m);
// initialize for signing
session.SignInit(Mechanism.RSA_PKCS, privateKey);
// sign the data to be signed
OUTPUT = session.Sign(INPUT);
session.VerifyInit(Mechanism.RSA_PKCS, publicKey);
var verify = session.Verify(INPUT, OUTPUT);
//var nRes = session.VerifyInit(Mechanism.RSA_PKCS, publicKey);
//nRes = session.Verify(text, signature);
//if (nRes == 0)
// Console.Write("Verify " + nRes);
return Convert.ToBase64String(OUTPUT);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public bool VerifyMessage(byte[] input, byte[] output)
{
// Searchs for an RSA private key object
// Sets the template with its attributes
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PUBLIC_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
// Launchs the search specifying the template just created
CryptokiCollection objects = session.Objects.Find(template, 10);
RSAPublicKey publicKey = null;
// If the private keys is found continue
if (objects.Count > 0) publicKey = (RSAPublicKey)objects[0];
session.VerifyInit(Mechanism.RSA_PKCS, publicKey);
var verify = session.Verify(input, output);
return (verify == 0);
}
public void Dispose()
{
if (session != null)
{
session.Close();
session = null;
}
if (module != null) module.Finalize(IntPtr.Zero);
}
}
}
Second Result with the same hash and certificate. This time certificate is in virtual HSM and NCryptoki is used.
dbncErlpz1liL3yJoIldbkhX3f5vUzAlCxkgBkU41/XXzeL83eolqOKv2lQz/Ri0nXwijHHiIhkxFejA2mADEB7+YZYIcNX9Y8TpyGp0jF8h30SsTBmnPOI58ec6SOk24QX17MC1nefBdIUs5n5uvUUPTjfNHUC7zfE92Zu2j+on4ZyPk7RqeM0/aNEbdET3R8lmbAWVRrtcY2JnnhN2XkOGABFfzcWxbAWuNXabDEZppf8Wkj8J4Xgfwjsc8Pc/QXUWGYGFr2YYqiZcw8SnpOi1V7v1NETmUQ+ZKswbakM6xgBt+YAf7P80HotQNWnPi6bh+FwipDSjSPQbNPxtNA==
Could you please tell my why we get decryptor or signature is invalid. I can confirm that the body of the message except the signature value is different.