Как получить доступ к сертификатам X.509, хранящимся в учетной записи службы?

Я пытаюсь подписать PDF-документ цифровой подписью с помощью Syncfusion PDF 10.4, например:

PdfLoadedDocument document = new PdfLoadedDocument(inputStream);
PdfCertificate certificate = PdfCertificate.FindBySubject(certificateStoreType, certificateSubjectName);

PdfSignature signature = new PdfSignature(document, document.Pages[0], certificate, "Signatur");
signature.Bounds = new RectangleF(new PointF(5, 5), new SizeF(100, 100));

Это отлично работает для моей локальной учетной записи пользователя после установки подходящего сертификата с помощью MMC (добавление оснастки Certificates для Моя учетная запись пользователя и сохранение ее в Personal ), но не для службы (на этот раз выбрав Учетная запись службы и выбрав мою службу). Выполнение того же кода приводит к тому, что подходящий сертификат не найден, т. Е. certificate имеет значение null. Кроме того, PdfCertificate.GetCertificates() выдает AccessViolationException, что, как я полагаю, является ошибкой на стороне Syncfusion.

Однако я могу воспроизвести ту же проблему без кода Syncfusion:

var store = new System.Security.Cryptography.X509Certificates.X509Store("My");
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
foreach (var item in store.Certificates)
{
    …
}

При запуске от имени моего собственного пользователя сертификат отображается (как и все остальные, показанные в MMC в разделе Personal), но если я отлажу службу (запустив ее, а затем вызвав System.Diagnostics.Debugger.Launch()), я получу только Сертификат "CN = LOCAL SERVICE", который вообще не отображается в MMC.

Я предполагаю, что мне нужно: A) сообщить ему об открытии правильного хранилища сертификатов или B) изменить что-то в способе установки или запуска службы, например, присвоить ей другой идентификатор, включить UserInteraction и т. Д. В настоящее время он работает с использованием LocalService и с отключенным UserInteraction.


person Sören Kuklau    schedule 20.12.2012    source источник


Ответы (3)


Насколько я помню, учетные записи компьютеров Windows (например, LocalService) используют хранилище сертификатов компьютера. Это означает, что в вашем коде вы должны получить доступ к магазину с StoreLocation.LocalMachine.

var store = 
   new System.Security.Cryptography.X509Certificates.X509Store(StoreLocation.LocalMachine);

Обратите внимание, что если вы решите запустить службу под определенным идентификатором, вам лучше сначала войти в систему как идентификатор, затем импортировать сертификат в личное хранилище, а затем использовать StoreLocation.CurrentUser.

person Wiktor Zychla    schedule 20.12.2012

Кажется, что .NET не поддерживает доступ к хранилищам сертификатов сервисных учетных записей без P / Invoke и т.п.

Я не думаю, что какой-либо из .NET API разрешает доступ к хранилищу сертификатов служб.

Однако вы можете установить сертификат в хранилище CurrentUser учетной записи, под которой работает служба.

Я изменил службу, чтобы она работала под собственным пользователем (которому не требуются права администратора), запустил mmc.exe от имени этого пользователя с помощью runas и импортировал сертификат в личное хранилище этого пользователя.

person Sören Kuklau    schedule 24.12.2012

Я столкнулся с этой проблемой, и для ее решения пришлось разрешить учетной записи «Local Service» доступ к хранилищу сертификатов «Local Computer» с помощью инструмента WinHttpCertCfg.

Подробно это описано здесь:

https://support.microsoft.com/en-us/help/901183/how-to-call-a-web-service-by-using-a-client-certificate-for-authentication-in-an-asp-net-web-application

person user1898139    schedule 23.05.2017