Невозможно прочитать последние изменения в ProgramData

У меня есть программа, которая выполняет исполняемый файл, используя Process.Start(), Исполняемый файл, который я вызываю, является сторонней программой, которая обновляет папку в ProgramData, После того, как папка в ProgramData обновляется следующий набор строк в моей программе, попробуйте прочитать последние изменения.

Я заметил, что последние изменения не могут быть прочитаны даже после выполнения исполняемого файла, однако, когда я снова запускаю свою программу с самого начала, я вижу, что изменения читаются правильно. Я предполагаю, что это как-то связано с AppDomain не может видеть изменения во время исполнения.

Могу ли я заставить все работать здесь?

В приведенном ниже коде внутри метода HSMTransactionHandler если исключение с сообщением HSM_ENCRYPTION_KEY_NOT_FOUND происходит, затем я выполняю exe, вызывая метод UpdateFromRFS а затем вызвать HSMTransactionHandler рекурсивно. Выполнение exe получает требуемый ресурс, но код не читает его. Если я запускаю другую программу во время выполнения текущей программы, вторая программа считывает ресурс без проблем. Что заставляет меня задуматься, может ли процесс или домен приложения увидеть изменения, которые происходят с ProgramData папка после запуска?

Просто чтобы все знали, что я использую PKCS11Interop библиотека, которая является управляемой .net обертка построена вокруг родной dll. Я также не уверен, может ли использование родной 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: Вот модифицированный код, который работал для меня, и обратите внимание, что самое важное здесь, это установить переменную CKNFAST_ASSUME_SINGLE_PROCESS до 0 в cknfastrc файл

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 и повторно инициализировать его

2 ответа

Решение

Исходя из ваших предыдущих вопросов № 1, № 2 и № 3, я предполагаю (потому что вы не написали это), что вы выполняете rfs-sync.exe и ваша библиотека PKCS#11 все еще не видит недавно синхронизированные ключи. Если это так, то вам нужно обратиться к руководству пользователя HSM и найти переменную (аналогично CKNFAST_FAKE_ACCELERATOR_LOGIN), которая заставляет вашу библиотеку PKCS#11 перечитывать локальную FS каждый раз, когда вы выполняете операцию поиска. Без этой переменной библиотека PKCS#11 просто кэширует содержимое локальной FS во время ее инициализации.

Process.Start() возвращается немедленно, т. е. это означает, что процесс начался. Другими словами, это означает, что процесс НЕ закончен.

Как правило, вам нужно подождать, пока процесс завершится.

т.е. Process.WaitForExit() или использовать Process.Exited событие.

Другие вопросы по тегам