2011-06-02 66 views
3

我们有一个构建过程需要解密密码,然后用它连接到数据库。我们使用数据保护API(DPAPI)来加密在构建服务器上的机器范围的密码使用PowerShell(我登录我自己的域帐户):ProtectedData.Unprotect方法无法解密

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

解密也在做PowerShell脚本,这是由CruiseControl.NET执行运行作为我们构建用户:

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

的调用Unprotect,然而,失败,出现以下消息:“关键不适于在指定状态下使用。” According to the docs,使用模拟可能发生此错误,并且模拟代码应加载用户的配置文件。

出于安全考虑,构建用户被拒绝通过终端服务登录权限。为了测试这个问题,我登录到构建服务器为我自己,然后使用运行方式来打开PowerShell提示符作为构建用户:

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

我然后运行PowerShell脚本来取消/解密密码,并获得同样的错误。

我用Process Monitor观察任何失败或拒绝访问事件,并没有任何。

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

发生了什么事?我的编译用户的配置文件没有被加载?有什么安全设置我不知道要启用它吗?为什么我无法解密密码?

回答

2

开发人员错误。原来我在CurrentUser范围内进行加密,而不是LocalMachine范围。我更新了我的脚本,现在一切正常。

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) 
+0

这不是问题。如果你传入一个无法解密的字节数组,你会得到与我不同的错误。 – 2011-06-06 20:27:22