PowerShell 技能连载 - 加密文本(第 2 部分)

这是我们的加密解密系列的第二部分。在第一部分中您学到了如何在一台计算机中安全地加密文本。现在我们来关注解密部分。

要正确地解密文本,必须指定加密时使用的相同编码。基于您的加密参数,您必须指定相同的密码。并且基于 -Scope 设置,解密将只能针对您和/或仅在您加密文本的同一机器上工作。

以下是 Unprotect-Text 函数。我们也从上一个技能中复制了 Protect-Text 函数,这样您可以方便地使用这两种功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
function Protect-Text
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[String]
$SecretText,

[string]
$Password='',

[string]
[ValidateSet('CurrentUser','LocalMachine')]
$scope = 'CurrentUser',

[string]
[ValidateSet('UTF7','UTF8','UTF32','Unicode','ASCII','Default')]
$Encoding = 'Default',

[Switch]
$ReturnByteArray

)
begin
{
Add-Type -AssemblyName System.Security
if ([string]::IsNullOrEmpty($Password))
{
$optionalEntropy = $null
}
else
{
$optionalEntropy = [System.Text.Encoding]::$Encoding.GetBytes($Password)
}
}
process
{
try
{
$userData = [System.Text.Encoding]::$Encoding.GetBytes($SecretText)
$bytes = [System.Security.Cryptography.ProtectedData]::Protect($userData, $optionalEntropy, $scope)
if ($ReturnByteArray)
{
$bytes
}
else
{
[Convert]::ToBase64String($bytes)
}
}
catch
{
throw "Protect-Text: Unable to protect text. $_"
}
}
}



function Unprotect-Text
{
[CmdletBinding(DefaultParameterSetName='Byte')]
param
(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="Text", Position=0)]
[string]
$EncryptedString,

[Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="Byte", Position=0)]
[Byte[]]
$EncryptedBytes,

[string]
$Password='',

[string]
[ValidateSet('CurrentUser','LocalMachine')]
$scope = 'CurrentUser',

[string]
[ValidateSet('UTF7','UTF8','UTF32','Unicode','ASCII','Default')]
$Encoding = 'Default'

)
begin
{
Add-Type -AssemblyName System.Security

if ([string]::IsNullOrEmpty($Password))
{
$optionalEntropy = $null
}
else
{
$optionalEntropy = [System.Text.Encoding]::$Encoding.GetBytes($Password)
}
}
process
{
try
{
if ($PSCmdlet.ParameterSetName -eq 'Text')
{
$inBytes = [Convert]::FromBase64String($EncryptedString)
}
else
{
$inBytes = $EncryptedBytes
}
$bytes = [System.Security.Cryptography.ProtectedData]::Unprotect($inBytes, $optionalEntropy, $scope)
[System.Text.Encoding]::$Encoding.GetString($bytes)
}
catch
{
throw "Unprotect-Text: Unable to unprotect your text. Check optional password, and make sure you are using the same encoding that was used during protection."
}
}
}

以下是如何使用它的示例:

1
2
3
4
5
$text = "This is my secret"

$a = Protect-Text -SecretText $text -scope CurrentUser -Password zumsel

Unprotect-Text -EncryptedString $a -scope CurrentUser -Password zumsel

Protect-Text 创建了一个 Base64 编码的字符串,它可以用 Unprotect-Text 函数来解密。如果您不希望额外的密码,那么只能使用基于 -Scope 的缺省的保护。

要节省空间,您可以使用字节数组来代替 Base64 编码的字符串:

1
2
$b = Protect-Text -SecretText $text -scope CurrentUser -ReturnByteArray
Unprotect-Text -EncryptedBytes $b -scope CurrentUser
评论