Ncrytoki错误n 48& 224

时间:2017-11-03 21:34:43

标签: c# wcf smartcard pkcs#11 hsm

我有wcf网络服务,当我的网站提出请求时签署pdf文件。在开发过程中,一切都在本地工作,试图签署少量文档。

一旦我的代码部署到生产环境,它工作正常几个小时但突然我开始收到错误n 48后跟n 224.

  

消息:错误n。 48   资料来源:NCryptoki   堆栈跟踪:在Cryptware.NCryptoki.Session.Sign(字节[]数据)      在iTextSharp.text.pdf.security.MakeSignature.SignDetached(PdfSignatureAppearance sap,IExternalSignature externalSignature,ICollection 1 chain, ICollection 1 crlList,IOcspClient ocspClient,ITSAClient tsaClient,Int32 estimatedSize,CryptoStandard sigtype)

     

消息:错误n。 224   资料来源:NCryptoki   堆栈跟踪:在Cryptware.NCryptoki.Session.Sign(字节[]数据)      在iTextSharp.text.pdf.security.MakeSignature.SignDetached(PdfSignatureAppearance sap,IExternalSignature externalSignature,ICollection 1 chain, ICollection 1 crlList,IOcspClient ocspClient,ITSAClient tsaClient,Int32 estimatedSize,CryptoStandard sigtype)

我努力了解可能发生的事情以及如何在本地复制此问题,以便我可以尝试修复它。我认为这可能是加载问题,但根据日志服务器只签署了每分钟4-5个请求。

以下是我的签名代码的摘要。

1)WCF SOAP Action

    public void TestSignPDF()
    {

        string fileName = Guid.NewGuid().ToString();
        String src = @"C:\tmp\singlepage.pdf";
        String DEST = string.Format(@"C:\tmp\{0}.pdf", fileName);

        MemoryStream ms = new MemoryStream();

        FileStream file = new FileStream(src, FileMode.Open, FileAccess.Read);
        byte[] bytes = new byte[file.Length];
        file.Read(bytes, 0, (int)file.Length);
        ms.Write(bytes, 0, (int)file.Length);
        file.Close();
        ms.Seek(0, SeekOrigin.Begin);

        HSMSignDocument x = new HSMSignDocument();
        Stream result = x.SignDocument(ms, "334", fileName);

        if (result != null)
        {
            FileStream file2 = new FileStream(DEST, FileMode.Create, System.IO.FileAccess.Write);
            byte[] bytes2 = new byte[result.Length];
            result.Read(bytes2, 0, (int)result.Length);
            file2.Write(bytes2, 0, bytes2.Length);
            file2.Close();
            result.Close();
        }

        ms.Close();
    }

2。)HSMSignDocument类(静态)

public class HSMSignDocument :  IDisposable
{
    private static Cryptoki cryptoki = null;
    private static Session session = null;
    private static NLogger LOGGER = new NLogger();
    private static readonly string HSMPartitionPwd = ConfigurationManager.AppSettings["HSMPartitionPassword"];

    private string TIME_STAMPING_SERVER_URL = "xx";
    private string TIME_STAMPING_SERVER_ACCOUNT = "xx"; 
    private string TIME_STAMPING_SERVER_PASSWORD = "xx"; 


    static HSMSignDocument()
    {
        Cryptoki.Licensee = "xxx";
        Cryptoki.ProductKey = "xxx";

        if (cryptoki == null)
        {
            cryptoki = new Cryptoki();
            cryptoki.Attach(@"C:\Program Files\SafeNet\LunaClient\cryptoki.dll");
            cryptoki.Initialize();
        }

        if (session == null)
        {
            // Reads the set of slots containing a token
            SlotList slots = cryptoki.Slots;
            if (slots.Count == 0)
            {
                LOGGER.Error("slots.Count == 0, no slots available");
                return;
            }

            // Gets the first slot available
            Slot slot = slots[0];
            if (!slot.IsTokenPresent)
            {
                LOGGER.Error("!slot.IsTokenPresent, no tokens present");
                return;;
            }

            // Gets the first token available
            Token token = slot.Token;

            // Opens a read/write serial session
            session = token.OpenSession(Session.CKF_SERIAL_SESSION | Session.CKF_RW_SESSION, null, null);

            int nRes = session.Login(Session.CKU_USER, HSMPartitionPwd);
            if (nRes != 0)
            {
                LOGGER.Error("Could not login to Session");
            }
        }
    }

    private  IList<Org.BouncyCastle.X509.X509Certificate> GetKeyChain()
    {
        //Private key pointers have been installed in 
        X509Store x509Store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

        x509Store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection certificates = x509Store.Certificates;
        IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
        X509Certificate2 pk = null;

        string HSMCertSerialNumber = ConfigurationManager.AppSettings["HSMCertificateSerialNumber"];

        if (certificates.Count > 0)
        {
            foreach (X509Certificate2 mCert in x509Store.Certificates)
            {
                //GETS THE KEY WE ARE LOOKING - Private key for HSM
                if (String.Compare(mCert.SerialNumber, HSMCertSerialNumber, true) == 0) 
                {
                    pk = mCert;
                    break;
                }
            }

            X509Chain x509chain = new X509Chain();
            x509chain.Build(pk);

            foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
            {
                // Build up root chain
                chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)); 
            }
        }

        x509Store.Close();

        return chain; 
    }

    public bool ApplySignatureDetails(Session session, String alias, Stream inputFile, string tempWorkingFile)
    {
        IList<Org.BouncyCastle.X509.X509Certificate> chain = GetKeyChain();

        // creates a TSA client(Time Stampingserver)
        ITSAClient timeStampingClient = new TSAClientBouncyCastle(TIME_STAMPING_SERVER_URL, TIME_STAMPING_SERVER_ACCOUNT, TIME_STAMPING_SERVER_PASSWORD);

        IOcspClient ocspClient = new OcspClientBouncyCastle(); // Online Certificate Status Protocol  -  adobe requirement
        List<ICrlClient> crlList = new List<ICrlClient>(); //revocation list -  adobe requirement
        crlList.Add(new CrlClientOnline(chain));

        return PKCS11Signer.Sign(inputFile, String.Format(tempWorkingFile, alias), chain, session, alias, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Doc Signed", "My Company", crlList, ocspClient, timeStampingClient, 0);
    }


    void IDisposable.Dispose()
    {
        if (session != null)
        {
            session.Logout();
            session.Close();
            session = null;
        }
        if (cryptoki != null)
        {
            cryptoki.Finalize(IntPtr.Zero);
            cryptoki = null;
        }
    }
}

3。)PKCS11Signer Class

class PKCS11Signer
{
    private static NLogger LOGGER = new NLogger();

    private static Semaphore Bouncer { get; set; }

    public static bool Sign(Stream inputFile, String dest, ICollection<Org.BouncyCastle.X509.X509Certificate> chain, Session session, String alias,
                     String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
                     ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
    {

        // Creating the reader and the stamper
        PdfReader reader = null;
        PdfStamper stamper = null;
        FileStream outputStream = null;

        try
        {

            if (Bouncer ==  null)
            {
                Bouncer = new Semaphore(1, 1);
            }

            Bouncer.WaitOne();
            LOGGER.Info("Start Actual Signing");
            reader = new PdfReader(inputFile);

            outputStream = new FileStream(dest, FileMode.Create, FileAccess.Write);
            stamper = PdfStamper.CreateSignature(reader, outputStream, '\0');
            LOGGER.Info("PDFStamper Created");

            // Creating the appearance
            PdfSignatureAppearance appearance = stamper.SignatureAppearance;

            LOGGER.Info("PdfSignatureAppearance Created");

            appearance.Reason = reason;
            appearance.Location = location;

            //Uncomment to show signiture text
            //appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(56, 128, 164, 160), 1, "signature");


            appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED;
            LOGGER.Info("PdfSignatureAppearance Created");

            // Creating the signature
            IExternalSignature pks = new PrivateKeySignature(session, alias);
            LOGGER.Info("Encryption algorithm " + pks.GetEncryptionAlgorithm());
            LOGGER.Info("Hash algorithm " + pks.GetHashAlgorithm());
            LOGGER.Info("Hash code " + pks.GetHashCode());
            LOGGER.Info("pks : " + pks.ToString());


            LOGGER.Info("IExternalSignature Created perform sign");
            MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
            //System.Threading.Thread.Sleep(1000); //Globalsign requirement

            LOGGER.Info("MakeSignature.SignDetached Completed");
        }
        catch (Exception ex)
        {
            LOGGER.Error(ex);
            throw ex;
        }
        finally
        {
             Bouncer.Release();
            if (stamper != null)
                stamper.Close();
            if (reader != null)
                reader.Close();
            if (outputStream != null)
                outputStream.Close();
            if (inputFile != null)
                inputFile.Close();
        }
        return true;
    }
}

}

4.)PrivateKeySignature Class

class PrivateKeySignature : IExternalSignature
{

    private static NLogger LOGGER = new NLogger();
    private static ObjectCache cache = MemoryCache.Default;

    private readonly Session session;
    RSAPrivateKey privateKey;

    public PrivateKeySignature(Session session, String alias)
    {
        string HSMPrivateKeyCertReq = ConfigurationManager.AppSettings["HSMPrivateKeyCertReq"];
        this.session = session;
        LOGGER.Info("Starting to get PrivateKeySignature");
        CryptokiCollection pkobjects = findTarget(session, HSMPrivateKeyCertReq);

        LOGGER.Info("Search session for private key using template");

        foreach(var keyObject in pkobjects)
        {
            LOGGER.Info("RSA/CertReq:" + HSMPrivateKeyCertReq);
            privateKey = (RSAPrivateKey)keyObject;
        }

        if (privateKey == null)
        {
            throw new Exception("privateKey not found");
        }

        LOGGER.Info("Private Key Found");
    }

    public String GetHashAlgorithm()
    {
        return "SHA1";
    }

    public String GetEncryptionAlgorithm()
    {
        return "RSA";
    }

    public byte[] Sign(byte[] message)
    {
        LOGGER.Info("Start apply Private Key");
        session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
        LOGGER.Info("End apply Private Key");
        return session.Sign(message);
    }

    public CryptokiCollection findTarget(Session session, string label)
    {
        if (cache.Contains(label))
        {
            return (CryptokiCollection)cache.Get(label);
        }
        else
        {
            CryptokiCollection template = new CryptokiCollection();

            template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, label));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));

            var pk = session.Objects.Find(template, 1);

            // Store data in the cache
            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy();
            cacheItemPolicy.SlidingExpiration = TimeSpan.FromHours(4);
            cache.Add(label, pk, cacheItemPolicy);

            return pk;
        }
    }
}

}

1 个答案:

答案 0 :(得分:1)

NCryptoki返回底层PKCS#11模块的错误。

此处提供了PKCS#11错误列表:

http://wiki.ncryptoki.com/How-NCryptoki-manages-PKCS-11-errors.ashx

在你的情况下48(0x30)表示: CKR_DEVICE_ERROR

而224(0xE0)表示: CKR_TOKEN_NOT_PRESENT

似乎您的生产HSM存在配置问题