MECHANISM_INVALID error thrown by the PKCS#11 library

8/22/2014 10:36:13 AM
Gravatar
Total Posts 12

MECHANISM_INVALID error thrown by the PKCS#11 library

Hi,

I have downloaded NCryptoki trial version. We would like to sign a string with Mechanism SHA256. However when the SignInit method is executed we receive this expection saying MECHANISM_INVALID.

 

Can you give us idea where should we look for the mistake?

 

at Net.Sf.Pkcs11.Wrapper.Pkcs11Module.checkCKR(CKR retVal) in ....\pkcs11Wrapper\Pkcs11\Wrapper\Pkcs11Module.cs:line 851
   at Net.Sf.Pkcs11.Wrapper.Pkcs11Module.SignInit(UInt32 hSession, CK_MECHANISM pMechanism, UInt32 hKey) in ....\pkcs11Wrapper\Pkcs11\Wrapper\Pkcs11Module.cs:line 723
   at Net.Sf.Pkcs11.Session.SignInit(Mechanism signingMechanism, PrivateKey key) in ....\pkcs11Wrapper\Pkcs11\Session.cs:line 180
 

 

Best Regards

8/22/2014 12:03:26 PM
Gravatar
Total Posts 300
Ugo Chirico http://www.ugochirico.com

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

Hei! you are not using our NCryptoki library. The sample code you posted is not from NCryptoki but comes from our competitors!

Why you said you are using NCryptoki? 

Please use NCryptoki instead!

 

Anyway, SHA256 is not a signing algorithm. SHA256 is an hashing algorithm that calculates the digest of the input string.

This is why SignInit returns MECHANISM_INVALID.

SHA256 must be used with DigestInit function to generate the digest that will be signed by SignInit using RSA_PKCS.

There is also the special mechanism that computes both SHA256 and RSA_PKCS

8/22/2014 12:49:05 PM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

I am really sorry. We have made experiments with several library. I will post the related stack trace for your records. Please accept my apologies.

 

BR

8/25/2014 1:19:57 PM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

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.  

8/25/2014 4:19:39 PM
Gravatar
Total Posts 300
Ugo Chirico http://www.ugochirico.com

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

You are trying to make an XML digital signature.

In the field SignedData your should put the Signature computed over the DigestInfo of the input data.

You forgot to generate to DigestInfo data.

The steps are:

1) compute the sha1 hash

2) generate the DigestInfo of the sha1 hash

3) sign the DIgestInfo using RSA_PKCS algo

 

The DigestInfo must be computed as described here:

http://tools.ietf.org/html/rfc2313

8/25/2014 11:59:21 PM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

Hi,

Infact i intercept a SOAP message and calculate digest for time stamp and body fields. I am requested to use sha256 hashing algorithm to create the digest info.

 

As you point out

 

1) I calculate digest value and reference back to both fields (body and timestamp) in the SignedInfo.

2) We again get the hash value of the SignedInfo element (sha256 maybe this should be sha1?). 

3) Sign the hash of SignedInfo element with NCryptotoki with RSA_PKCS

 

Do i understand you correctly, what am i missing?

 

BR

8/26/2014 12:01:17 AM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

I forgot the adding step number 4) i put the calculated signature into SignatureValue element in the soap envelope.

 

Thanks at advance.

8/26/2014 9:14:50 AM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

If i may highlight one point that. I send same hash to both method. SignLocal and  SignMessage both uses same certificate pair. However, results are vary.

 

PS. Please read last 3 messages together including this.

8/26/2014 12:44:07 PM
Gravatar
Total Posts 12

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

Any help is appreciated.

8/26/2014 5:20:29 PM
Gravatar
Total Posts 300
Ugo Chirico http://www.ugochirico.com

Re: MECHANISM_INVALID error thrown by the PKCS#11 library

As I said in my previous post you should create the DigestInfo structure that includes the hash.

than you will pass the DigestInfo to the Sign method to obtain the same result you got from SignLocal.

I mean DigestInfo, not SignedInfo as you (I guess) misunderstood.

 

1) calculate the digest value and reference back to both fields (body and timestamp) in the SignedInfo.

2) get the hash SHA256 value of the SignedInfo element.

3) calculate the DigestInfo using the hash at item 2), specifing as digest algo SHA256

4) Sign the hash of DigestInfo with NCryptotoki with RSA_PKCS