Метод ProtectedData.Unprotect не может расшифровать - PullRequest
3 голосов
/ 02 июня 2011

У нас есть процесс сборки, который должен расшифровать пароль, который он затем использует для подключения к базе данных. Мы используем 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 ]

2 голосов
/ 07 июня 2011

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

1 голос
/ 03 июня 2011

Обращаете ли вы внимание на то, как вы кодируете зашифрованный массив 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)
...