4

我们有一个构建过程,需要解密密码,然后使用该密码连接到数据库。我们正在使用数据保护 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来监视任何失败或访问被拒绝事件,但没有任何事件。

当我使用自己的域帐户登录时,我能够解密密码。

这是怎么回事?我的构建用户的配置文件没有被加载吗?是否有一些我不知道的安全设置可以启用它?为什么我不能解密密码?

4

2 回答 2

3

开发者错误。事实证明,我是在 CurrentUser 范围内加密,而不是 LocalMachine 范围内。我更新了我的脚本,现在一切正常。

于 2011-06-06T20:38:44.463 回答
1

您是否注意在文件中对加密的 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)
于 2011-06-03T14:20:36.740 回答