Метод ProtectedData.Unprotect не может расшифровать

У нас есть процесс сборки, который должен расшифровать пароль, который он затем использует для подключения к базе данных. Мы используем API защиты данных (DPAPI) для шифрования пароля в области компьютера на сервере сборки (я вошел в систему с моей собственной учетной записью домена) с помощью PowerShell:

[Security.Cryptography.ProtectedData]::Protect( $passwordBytes, $null, [Security.Cryptography.DataProtectionScope]::LocalMachine );

Расшифровка также выполняется в сценарии PowerShell, который выполняется CruiseControl.NET и работает как наш пользователь сборки:

 [Security.Cryptography.ProtectedData]::Unprotect( $encryptedbytes, $null, [Security.Cryptography.DataProtectionScope]::LocalMachine );

Призыв к UnprotectОднако возникает ошибка со следующим сообщением: "Ключ недействителен для использования в указанном состоянии.". Согласно документации, эта ошибка может возникать при использовании олицетворения, и олицетворяющий код должен загружать профиль пользователя.

В целях безопасности пользователю сборки запрещен вход через службы терминалов. Чтобы проверить проблему, я вошел на сервер сборки как сам, а затем использовал runas, чтобы открыть приглашение PowerShell от имени пользователя сборки:

runas /profile /user:DOMAIN\BUILDUSER powershell.exe

Затем я запускаю сценарий PowerShell для снятия защиты / дешифрования пароля и получаю ту же ошибку.

Я использовал Process Monitor для наблюдения за любыми сбоями или событиями, в которых отказано в доступе, а их не было.

Я могу расшифровать пароль при входе в свою учетную запись домена.

В чем дело? Мой пользовательский профиль сборки не загружается? Есть ли где-то настройки безопасности, о которых я не знаю, чтобы включить это? Почему я не могу расшифровать пароль?

2 ответа

Решение

Ошибка разработчика. Оказывается, я шифровал в области CurrentUser, а не в LocalMachine. Я обновил свой скрипт, и теперь все работает.

Обращаете ли вы внимание на то, как вы кодируете зашифрованный массив ByteArray в своем файле. Здесь ниже я извлекаю способ, которым я делаю это на одном из моих серверов для строки подключения (я заменяю здесь введенной строкой)

Конвертировать в Base64, чтобы поместить его в файл конфигурации

Clear-Host

Add-Type -assembly System.Security

$passwordASCII = Read-Host -Prompt "Enter Password"

$bakCryptedPWD_ByteArray = [System.Security.Cryptography.ProtectedData]::Protect( $passwordASCII.tochararray(), $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine )

Set-Content -LiteralPath c:\Temp\pass.txt -Value ([Convert]::ToBase64String($bakCryptedPWD_ByteArray))

Вернуться к строке с учетом символов ANSI (может иметь специальные символы в пароле)

Clear-Host

Add-Type -assembly System.Security

$resCryptedPWD_ByteArray = [Convert]::FromBase64String((Get-Content -LiteralPath c:\Temp\pass.txt))

$clearPWD_ByteArray = [System.Security.Cryptography.ProtectedData]::Unprotect( $resCryptedPWD_ByteArray, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine )

$enc = [system.text.encoding]::Default

$enc.GetString($clearPWD_ByteArray)
Другие вопросы по тегам