【问题标题】:Unable to read latest changes to the ProgramData无法读取 ProgramData 的最新更改
【发布时间】:2017-08-04 13:49:51
【问题描述】:

我有一个使用Process.Start() 执行可执行文件的程序。我调用的可执行文件是更新ProgramData 中的文件夹的第三方程序。一旦ProgramData 中的文件夹得到更新,我的程序中的下一组行尝试读取最新的更改。

我注意到即使在可执行文件执行后也无法读取最新的更改,但是当我从头开始再次运行我的程序时,我可以看到更改被正确读取。我假设这与AppDomain 在执行期间无法看到更改有关。

无论如何我可以在这里工作吗?

在方法HSMTransactionHandler下面的代码中,如果发生带有消息HSM_ENCRYPTION_KEY_NOT_FOUND的异常,那么我通过调用方法UpdateFromRFS执行一个exe,然后递归调用HSMTransactionHandler。 exe 的执行获得了所需的资源,但代码没有读取它。如果我在当前程序执行期间运行另一个程序,第二个程序读取资源没有任何问题。这让我想到一个进程或应用程序域是否可以在启动后看到 ProgramData 文件夹发生的更改?

只是为了让每个人都知道我正在使用 PKCS11Interop 库,它是一个围绕本机 dll 构建的托管 .net 包装器。我也不确定使用本机 dll 是否会导致这种情况。

我们将不胜感激。

下面是代码:

public sealed class KeyStoreOperations
    {
        private KeyStoreContext m_keyStoreContext;

        private static Pkcs11 m_Pkcs11;
        private static readonly object _syncLockPkcs11 = new object();
        private static readonly object _syncLockHSMLogin = new object();

        public KeyStoreOperations(KeyStoreContext keyStoreContext)
        {
            m_keyStoreContext = keyStoreContext;
            InitializePkcs11Object();
        }

        public string Encrypt(string keyName, string message)
        {
            ValidateInputs(message, "Message");
            var encryptedMessage = string.Empty;
            HSMTransactionHandler((Session session) =>
            {
                Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
                var publicKey = GetPublicKey(keyName, session);
                if (publicKey == null)
                    throw new HSMException(ErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND);
                var originalKeyBytes = EncryptionHelper.Decode(message);
                var encryptedKeyBytes = session.Encrypt(mechanism, publicKey, originalKeyBytes);
                encryptedMessage = EncryptionHelper.Encode(encryptedKeyBytes);
            });
            return encryptedMessage;
        }

        public string Decrypt(string keyName, string cipher)
        {
            ValidateInputs(cipher, "Cipher");
            var decryptedMessage = string.Empty;
            HSMTransactionHandler((Session session) =>
            {
                Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
                var privateKey = GetPrivateKey(keyName, session);
                if (privateKey == null)
                    throw new HSMException(ErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND);
                var encryptedSymmetricKeyBytes = EncryptionHelper.Decode(cipher);
                var decryptedSymmetricKeyBytes = session.Decrypt(mechanism, privateKey, encryptedSymmetricKeyBytes);
                decryptedMessage = EncryptionHelper.Encode(decryptedSymmetricKeyBytes);
            });
            return decryptedMessage;
        }

        #region Private methods  

        #region Validations

        private void ValidateInputs(string input, string name)
        {
            if (string.IsNullOrEmpty(input))
                throw new ArgumentNullException(name);
        }

        #endregion Validations

        private void HSMTransactionHandler(Action<Session> action, bool commit = false, int retrialAttempt = 5)
        {
            Slot hsmSlot = null;
            Session hsmSession = null;
            bool logggedIn = false;
            try
            {
                hsmSlot = GetSlot(m_NCipherKeyStoreContext.ModuleToken);
                hsmSession = hsmSlot.OpenSession(false);
                lock (_syncLockHSMLogin)
                {
                    hsmSession.Login(CKU.CKU_USER, m_NCipherKeyStoreContext.SecurityPin);
                    logggedIn = true;
                    action(hsmSession);
                    hsmSession.Logout();
                    logggedIn = false;
                }
                if (commit)
                    CommitToRFS();
            }
            catch (Pkcs11Exception ex)
            {
                HandleHSMErrors(ex);
            }
            catch (HSMException ex)
            {
                if (ex.Message == EncryptionKeyStoreErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND && retrialAttempt > 0)
                {
                    if (logggedIn)
                    {
                        hsmSession.Logout();
                        logggedIn = false;
                    }
                    if (!(hsmSession == null))
                        hsmSession.CloseSession();
                    UpdateFromRFS();
                    Thread.Sleep(1000);
                    HSMTransactionHandler(action, retrialAttempt: retrialAttempt - 1);
                }
                else
                    throw ex;
            }
            finally
            {
                if (logggedIn)
                    hsmSession.Logout();
                if (!(hsmSession == null))
                    hsmSession.CloseSession();
            }
        }

        private void UpdateFromRFS()
        {
            using (var rfsSyncProcess = GetRfsSyncProcess("--update"))
            {
                ExecuteRFSSyncProcess(rfsSyncProcess);
            }
        }

        private Process GetRfsSyncProcess(string args)
        {
            Process rfsSyncProcess = new Process();
            rfsSyncProcess.StartInfo.FileName = "C:\\Program Files (x86)\\nCipher\\nfast\\bin\\rfs-sync.exe";
            rfsSyncProcess.StartInfo.Arguments = args;
            return rfsSyncProcess;
        }

        private void ExecuteRFSSyncProcess(Process rfsSyncProcess)
        {
            rfsSyncProcess.Start();
            rfsSyncProcess.WaitForExit();
        }

        private ObjectHandle GetPrivateKey(string keyName, Session session)
        {
            ObjectHandle privateKey = null;
            List<ObjectHandle> foundObjects = null;
            List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
            objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
            objectAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));

            foundObjects = session.FindAllObjects(objectAttributes);
            if (foundObjects != null && foundObjects.Count > 0)
            {
                privateKey = foundObjects[0];
            }
            return privateKey;
        }

        private ObjectHandle GetPublicKey(string keyName, Session session)
        {
            ObjectHandle publicKey = null;
            List<ObjectHandle> foundObjects = null;
            List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
            objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
            objectAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));

            foundObjects = session.FindAllObjects(objectAttributes);
            if (foundObjects != null && foundObjects.Count > 0)
            {
                publicKey = foundObjects[0];
            }
            return publicKey;
        }

        private List<ObjectAttribute> CreatePublicKeyTemplate(string keyName, byte[] ckaId)
        {
            List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>();
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, Convert.ToUInt64(m_keyStoreContext.KeySize)));
            publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));

            return publicKeyAttributes;
        }

        private List<ObjectAttribute> CreatePrivateKeyTemplate(string keyName, byte[] ckaId)
        {
            List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>();
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true));
            privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));

            return privateKeyAttributes;
        }

        private Slot GetSlot(string tokenLabel)
        {
            Slot matchingSlot = null;
            List<Slot> slots = m_Pkcs11.GetSlotList(true);
            matchingSlot = slots[0];
            if (tokenLabel != null)
            {
                matchingSlot = null;
                foreach (Slot slot in slots)
                {
                    TokenInfo tokenInfo = null;
                    try
                    {
                        tokenInfo = slot.GetTokenInfo();
                    }
                    catch (Pkcs11Exception ex)
                    {
                        if (ex.RV != CKR.CKR_TOKEN_NOT_RECOGNIZED && ex.RV != CKR.CKR_TOKEN_NOT_PRESENT)
                            throw;
                    }

                    if (tokenInfo == null)
                        continue;

                    if (!string.IsNullOrEmpty(m_keyStoreContext.ModuleToken))
                        if (0 != string.Compare(m_keyStoreContext.ModuleToken, tokenInfo.Label, StringComparison.Ordinal))
                            continue;

                    matchingSlot = slot;
                    break;
                }

                if (matchingSlot == null)
                    throw new HSMException(string.Format(ErrorConstant.HSM_CONFIGURATION_ERROR_INCORRECT_SLOT, tokenLabel));
            }
            return matchingSlot;
        }

        private void InitializePkcs11Object()
        {
            if (m_Pkcs11 == null)
            {
                lock (_syncLockPkcs11)
                {
                    m_Pkcs11 = new Pkcs11(m_keyStoreContext.PKCS11LibraryPath, true);
                }
            }
        }

        private void HandleHSMErrors(Pkcs11Exception ex)
        {
            if (ex.RV == CKR.CKR_PIN_INCORRECT)
            {
                throw new HSMException(ErrorConstant.HSM_CONFIGURATION_ERROR_PIN_INCORRECT, ex);
            }
            else
            {
                throw new HSMException(ErrorConstant.HSM_CONFIGURATION_ERROR_GENERIC, ex);
            }
        }

        #endregion
    }

编辑 1: 这是对我有用的修改后的代码,请注意这里最重要的是在cknfastrc 文件中将变量CKNFAST_ASSUME_SINGLE_PROCESS 设置为0

public sealed class KeyStoreOperations
        {
            private KeyStoreContext m_keyStoreContext;

            private static Pkcs11 m_Pkcs11;
            private static readonly object _syncLockPkcs11 = new object();
            private static readonly object _syncLockHSMLogin = new object();

            public KeyStoreOperations(KeyStoreContext keyStoreContext)
            {
                m_keyStoreContext = keyStoreContext;
                InitializePkcs11Object();
            }

            public string Encrypt(string keyName, string message)
            {
                ValidateInputs(message, "Message");
                var encryptedMessage = string.Empty;
                HSMTransactionHandler((Session session) =>
                {
                    Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
                    var publicKey = GetPublicKey(keyName, session);
                    if (publicKey == null)
                        throw new HSMException(ErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND);
                    var originalKeyBytes = EncryptionHelper.Decode(message);
                    var encryptedKeyBytes = session.Encrypt(mechanism, publicKey, originalKeyBytes);
                    encryptedMessage = EncryptionHelper.Encode(encryptedKeyBytes);
                });
                return encryptedMessage;
            }

            public string Decrypt(string keyName, string cipher)
            {
                ValidateInputs(cipher, "Cipher");
                var decryptedMessage = string.Empty;
                HSMTransactionHandler((Session session) =>
                {
                    Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
                    var privateKey = GetPrivateKey(keyName, session);
                    if (privateKey == null)
                        throw new HSMException(ErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND);
                    var encryptedSymmetricKeyBytes = EncryptionHelper.Decode(cipher);
                    var decryptedSymmetricKeyBytes = session.Decrypt(mechanism, privateKey, encryptedSymmetricKeyBytes);
                    decryptedMessage = EncryptionHelper.Encode(decryptedSymmetricKeyBytes);
                });
                return decryptedMessage;
            }

            #region Private methods  

            #region Validations

            private void ValidateInputs(string input, string name)
            {
                if (string.IsNullOrEmpty(input))
                    throw new ArgumentNullException(name);
            }

            #endregion Validations

            private void HSMTransactionHandler(Action<Session> action, bool commit = false, int retrialAttempt = 5)
            {
                Slot hsmSlot = null;
                Session hsmSession = null;
                bool logggedIn = false;
                try
                {
                    hsmSlot = GetSlot(m_NCipherKeyStoreContext.ModuleToken);
                    hsmSession = hsmSlot.OpenSession(false);
                    lock (_syncLockHSMLogin)
                    {
                        hsmSession.Login(CKU.CKU_USER, m_NCipherKeyStoreContext.SecurityPin);
                        logggedIn = true;
                        action(hsmSession);
                        hsmSession.Logout();
                        logggedIn = false;
                    }
                    if (commit)
                        CommitToRFS();
                }
                catch (Pkcs11Exception ex)
                {
                    HandleHSMErrors(ex);
                }
                catch (HSMException ex)
                {
                    if (ex.Message == EncryptionKeyStoreErrorConstant.HSM_ENCRYPTION_KEY_NOT_FOUND && retrialAttempt > 0)
                    {
                        if (logggedIn)
                        {
                            hsmSession.Logout();
                            logggedIn = false;
                        }
                        if (!(hsmSession == null))
                        {
                            hsmSession.CloseSession();
                            hsmSession = null;
                        }
                        UpdateFromRFS();
                        Thread.Sleep(1000);
                        if (!m_Pkcs11.Disposed)
                        {
                            m_Pkcs11.Dispose();
                            m_Pkcs11 = null;
                        }
                        HSMTransactionHandler(action, retrialAttempt: retrialAttempt - 1);
                    }
                    else
                        throw ex;
                }
                finally
                {
                    if (logggedIn)
                        hsmSession.Logout();
                    if (!(hsmSession == null))
                        hsmSession.CloseSession();
                }
            }

            private void UpdateFromRFS()
            {
                using (var rfsSyncProcess = GetRfsSyncProcess("--update"))
                {
                    ExecuteRFSSyncProcess(rfsSyncProcess);
                }
            }

            private Process GetRfsSyncProcess(string args)
            {
                Process rfsSyncProcess = new Process();
                rfsSyncProcess.StartInfo.FileName = "C:\\Program Files (x86)\\nCipher\\nfast\\bin\\rfs-sync.exe";
                rfsSyncProcess.StartInfo.Arguments = args;
                return rfsSyncProcess;
            }

            private void ExecuteRFSSyncProcess(Process rfsSyncProcess)
            {
                rfsSyncProcess.Start();
                rfsSyncProcess.WaitForExit();
            }

            private ObjectHandle GetPrivateKey(string keyName, Session session)
            {
                ObjectHandle privateKey = null;
                List<ObjectHandle> foundObjects = null;
                List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));

                foundObjects = session.FindAllObjects(objectAttributes);
                if (foundObjects != null && foundObjects.Count > 0)
                {
                    privateKey = foundObjects[0];
                }
                return privateKey;
            }

            private ObjectHandle GetPublicKey(string keyName, Session session)
            {
                ObjectHandle publicKey = null;
                List<ObjectHandle> foundObjects = null;
                List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
                objectAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));

                foundObjects = session.FindAllObjects(objectAttributes);
                if (foundObjects != null && foundObjects.Count > 0)
                {
                    publicKey = foundObjects[0];
                }
                return publicKey;
            }

            private List<ObjectAttribute> CreatePublicKeyTemplate(string keyName, byte[] ckaId)
            {
                List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>();
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, Convert.ToUInt64(m_keyStoreContext.KeySize)));
                publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));

                return publicKeyAttributes;
            }

            private List<ObjectAttribute> CreatePrivateKeyTemplate(string keyName, byte[] ckaId)
            {
                List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>();
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true));
                privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));

                return privateKeyAttributes;
            }

            private Slot GetSlot(string tokenLabel)
            {
                Slot matchingSlot = null;
                List<Slot> slots = m_Pkcs11.GetSlotList(true);
                matchingSlot = slots[0];
                if (tokenLabel != null)
                {
                    matchingSlot = null;
                    foreach (Slot slot in slots)
                    {
                        TokenInfo tokenInfo = null;
                        try
                        {
                            tokenInfo = slot.GetTokenInfo();
                        }
                        catch (Pkcs11Exception ex)
                        {
                            if (ex.RV != CKR.CKR_TOKEN_NOT_RECOGNIZED && ex.RV != CKR.CKR_TOKEN_NOT_PRESENT)
                                throw;
                        }

                        if (tokenInfo == null)
                            continue;

                        if (!string.IsNullOrEmpty(m_keyStoreContext.ModuleToken))
                            if (0 != string.Compare(m_keyStoreContext.ModuleToken, tokenInfo.Label, StringComparison.Ordinal))
                                continue;

                        matchingSlot = slot;
                        break;
                    }

                    if (matchingSlot == null)
                        throw new HSMException(string.Format(ErrorConstant.HSM_CONFIGURATION_ERROR_INCORRECT_SLOT, tokenLabel));
                }
                return matchingSlot;
            }

            private void InitializePkcs11Object()
            {
                if (m_Pkcs11 == null)
                {
                    lock (_syncLockPkcs11)
                    {
                        m_Pkcs11 = new Pkcs11(m_keyStoreContext.PKCS11LibraryPath, true);
                    }
                }
            }

            private void HandleHSMErrors(Pkcs11Exception ex)
            {
                if (ex.RV == CKR.CKR_PIN_INCORRECT)
                {
                    throw new HSMException(ErrorConstant.HSM_CONFIGURATION_ERROR_PIN_INCORRECT, ex);
                }
                else
                {
                    throw new HSMException(ErrorConstant.HSM_CONFIGURATION_ERROR_GENERIC, ex);
                }
            }

            #endregion
        }

编辑 2:我检查并发现它甚至没有将 CKNFAST_ASSUME_SINGLE_PROCESS 设置为 0 就可以工作,因此可能只需要处理 pkcs11 对象并重新初始化它

【问题讨论】:

  • 我已经用内联代码标记 (`) 标记了函数调用和目录名称,以便于阅读。请edit您的问题并添加您的代码,以便我们准确了解您在做什么。

标签: c# .net appdomain pkcs11interop


【解决方案1】:

根据您之前的问题#1#2#3 我猜(因为您没有编写它)您正在执行 rfs-sync.exe 并且您的 PKCS#11 库仍然看不到新同步的密钥.如果是这种情况,那么您需要查阅 HSM 用户指南并查找变量(类似于 CKNFAST_FAKE_ACCELERATOR_LOGIN),这会使您的 PKCS#11 库在您每次执行搜索操作时重新读取本地 FS。如果没有那个变量 PKCS#11 库,它只会在初始化期间缓存本地 FS 的内容。

【讨论】:

  • 我可以在文档中找到名为 CKNFAST_ASSUME_SINGLE_PROCESS 的变量,我认为这一定是您所指的那个变量。即使我将其设置为 0,问题仍然存在。
  • 好吧,终于,我可以让它工作了。除了将 CKNFAST_ASSUME_SINGLE_PROCESS 设置为 0 之外,我还必须在 pkcs11 对象上调用 C_Finalize ,瞧,它就像一个魅力。感谢@jariq 的所有帮助,我真的很感激。
  • 我可以在不将 CKNFAST_ASSUME_SINGLE_PROCESS 设置为 0 的情况下使其正常工作,因此可能不是必需的,只需要处理 PKCS11 对象
  • @Aashish 你可能做错了什么,因为CKNFAST_ASSUME_SINGLE_PROCESS=0 的目的是使Pkcs11 类的重新创建实例变得不必要。
  • 我不知道它为什么会这样。你对我可以检查的事情有什么建议吗?我在上面分享了我的代码。
【解决方案2】:

Process.Start() 立即返回,即表示进程有started。也就是说,这个过程还没有结束。

通常,您应该拥有some sort of wait 才能完成该过程。

Process.WaitForExit() 或使用Process.Exited 事件。

【讨论】:

  • 虽然我在问题中没有提到,但我已经这样做了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-06
  • 2015-01-17
  • 2016-04-11
  • 2018-11-11
  • 2022-06-14
  • 2023-03-13
  • 2012-11-09
相关资源
最近更新 更多