【问题标题】:AES encryption on files using PowerShell使用 PowerShell 对文件进行 AES 加密
【发布时间】:2019-03-29 11:40:39
【问题描述】:

我能够使用此脚本here,使用 Windows 10,PowerShell 版本 5.1 成功地对文件进行 AES 加密。

当我尝试在 Windows 7 PowerShell v2.0 上运行它时,我收到一个错误:

New-CryptographyKey :您不能在空值表达式上调用方法。 在 C:\Users\IEUser\Desktop\enc.ps1:399 char:27 + $key = New-CryptographyKey

如何让它发挥作用?或者是否有另一种使用 Powershell 进行 AES 文件加密的交叉兼容解决方案?

编辑:

我可能已经找到了使用 openSSL 的解决方案,但我仍然尝试了@Mike Twc 的解决方案,得到了以下输出:

PS C:\Users\IEUser\Desktop> .\bouncy.ps1

TEST:

message: Some secret message
key: 9JODwRWWHp6+uACUiydFXNXPmWDHbcObhgqR/cvZ9zg=
IV (base64): U29tZV9QYXNzd29yZA==
IV (utf8): Some_Password
message bytes: 83 111 109 101 32 115 101 99 114 101 116 32 109 101 115 115 97 10
3 101
encrypted message bytes: 178 172 14 98 228 38 129 136 217 25 129 96 46 177 75 62
 50 5 190 46 51 108 81 38 90 74 197 166 44 96 120 252
encrypted message: sqwOYuQmgYjZGYFgLrFLPjIFvi4zbFEmWkrFpixgePw=
decrypted bytes: 83 111 109 101 32 115 101 99 114 101 116 32 109 101 115 115 97
103 101 0 0 0 0 0 0 0 0 0 0 0 0 0
decrypted message: Some secret message

【问题讨论】:

  • 当您运行 $key = New-CryptographyKey -AsPlainText 时,您是否遇到任何错误?也许发布你正在运行的脚本
  • 错误表示路径无效,并且没有加载该 dll。它还在吗?我想你之前可以加载它
  • 对不起。我使用环境变量设置了 dll 的路径,但由于某种原因它失败了。现在我设置绝对路径。
  • 现在我该怎么办?我将 iv 和密钥提供给 openssl 什么的?
  • 那么它就可以工作了。不,这是独立实施。您可以将其包装为一个模块或一组函数(用于 KeyGen、加密、解密)。

标签: powershell encryption powershell-2.0


【解决方案1】:

您可以尝试使用 BouncyCastle 库。下面是该库的 AES 加密/解密实现。它在我的版本 2 模式下工作。

从这里下载最新编译的程序集 (BouncyCastle.Crypto.dll): https://www.bouncycastle.org/csharp/index.html

将该 dll 解压到任意文件夹(比如 C:\temp),右键单击它,然后选中“取消阻止”

运行此代码:

Add-Type -path "C:\stack\BouncyCastle.Crypto.dll"

$secRandom =  new-object Org.BouncyCastle.Security.SecureRandom

$message = "Some secret message"
$messageBytes = [System.Text.Encoding]::UTF8.GetBytes($message)

# if using files do this: 
# $messageBytes = [System.IO.File]::ReadAllBytes("C:\stack\out.txt")

#==== Key generation =====#

$keyBytes = New-Object byte[] 32
$secRandom.NextBytes($keyBytes) 
#$generator = [Org.BouncyCastle.Security.GeneratorUtilities]::GetKeyGenerator("AES")
$generator = New-Object Org.BouncyCastle.Crypto.CipherKeyGenerator 
$keyGenParam = new-object Org.BouncyCastle.Crypto.KeyGenerationParameters $keyBytes, 256
$generator.Init($keyGenParam)
$key = $generator.GenerateKey()
#or retreive from base64 string:
$key = [System.Convert]::FromBase64String("9JODwRWWHp6+uACUiydFXNXPmWDHbcObhgqR/cvZ9zg=")


#==== initialization vector (optional) =====#
#IV is a byte array, should be same as AES block size. By default 128 bit or 16 bytes (or less)

$IV = New-Object byte[] 16  
# below are some random IVs to play around, if IV parameter is not provided by user just keep it is array of 0s
$secRandom.NextBytes($IV) | Out-Null  #random generated 16 bytes
$IV = [System.Text.Encoding]::UTF8.GetBytes("Some_Password") #or use some random phrase


#==== Cipher set up =====#
#specify cipher type (typically CFB or CBC) and padding (use NOPADDING to skip). Check all possible values: 
#https://github.com/neoeinstein/bouncycastle/blob/master/crypto/src/security/CipherUtilities.cs

$cipher = [Org.BouncyCastle.Security.CipherUtilities]::GetCipher("AES/CFB/PKCS7")
$aesKeyParam = [Org.BouncyCastle.Security.ParameterUtilities]::CreateKeyParameter("AES", $key)
$keyAndIVparam = New-Object Org.BouncyCastle.Crypto.Parameters.ParametersWithIV $aesKeyParam, $IV


#==== Encrypt  =====#
#$cipher.Init($true,$aesKeyParam) 
$cipher.Init($true,$keyAndIVparam)
$dataSize = $cipher.GetOutputSize($messageBytes.Length)
$encMessageBytes = New-Object byte[]  $dataSize
$len = $cipher.ProcessBytes($messageBytes , 0, $messageBytes.Length, $encMessageBytes, 0)
$cipher.DoFinal($encMessageBytes, $len) | Out-Null

$encMessage = [System.Convert]::ToBase64String($encMessageBytes)

#if using files
#[System.IO.File]::WriteAllText("C:\stack\out.txt.aes", $encMessage)
#$encMessageBytes = [System.Convert]::FromBase64String([System.IO.File]::ReadAllText("C:\stack\out.txt.aes"))

#==== Decrypt =====#
#$cipher.Init($false,$aesKeyParam)
$cipher.Init($false,$keyAndIVparam)
$dataSize = $cipher.GetOutputSize($encMessageBytes.Length)
$decMessageBytes = New-Object byte[]  $dataSize
$len = $cipher.ProcessBytes($encMessageBytes , 0, $encMessageBytes.Length, $decMessageBytes, 0)
$cipher.DoFinal($decMessageBytes, $len) | Out-Null

$decMessage = [System.Text.Encoding]::UTF8.GetString($decMessageBytes).Trim([char]0)

#==== TEST =====#
Write-Host "`nTEST:`n"
Write-Host "message: $message"
Write-Host "key: $([System.Convert]::ToBase64String($key))"
Write-Host "IV (base64): $([System.Convert]::ToBase64String($IV))"
Write-Host "IV (utf8): $([System.Text.Encoding]::UTF8.GetString($IV))"
Write-Host "message bytes: $messageBytes"
Write-Host "encrypted message bytes: $encMessageBytes"
Write-Host "encrypted message: $encMessage"
Write-Host "decrypted bytes: $decMessageBytes"
Write-Host "decrypted message: $decMessage"

【讨论】:

  • 它生成一个密钥,以及一些错误。请查看我在问题中添加的错误。
  • 好的,可能需要使用 new-object vs ::new()。试试这个 $params = new-object Org.BouncyCastle.Crypto.KeyGenerationParameters -argumentlist ($keyBytes, 256)
  • 谢谢,成功了。现在我生成密钥时没有错误,而且密钥也更长了。但是 Protect-File 的错误仍然存​​在。
  • 我所做的是下载加密模块并将其转换为 ps1 并顺便运行它。我刚刚删除了底部的导出模块命令。它适用于 Win10 pshell v5.1
  • 是的,它不能解决你原来的问题,只是想测试一下那个库是否可以工作。由于 sn-p 工作,您很有可能可以基于该库实现加密。我会尝试一下并将我的发现添加到帖子中。
【解决方案2】:

根据您说您正在使用的链接到的代码的源信息,它在设计时并未考虑到 PowerShell v2。因此,它失败的事实是可以预料的,因为如果内存服务,Export-ModuleMember 直到 PowerShellv3 才引入。

Get-Command -Name Export-moduleMember

CommandType     Name                  Version    Source
-----------     ----                  -------    ------
Cmdlet          Export-ModuleMember   3.0.0.0    Microsoft.PowerShell.Core

不过,我的环境中没有任何 PowerShellv2 可供严格检查。

那么,至于这个..

如何让它发挥作用?

.. 将您的 PowerShell 版本升级到 3 - 5x。

至于这个……

另一种用于 AES 文件加密的交叉兼容解决方案,使用 电源外壳?

甚至 PowerShell 的唯一跨平台版本是 PowerShell Core (PowerShell v6)。 如果您指的是此模块的跨平台版本,则由作者提供或由您编写。

如果您要求通用跨平台 AES 工具(即使您指向的链接也只是 Windows - 所以如果您需要跨平台 Win/OSX/Linux,那么这无论如何都行不通),那真的不是 PowerShell 问题但是软件推荐,并且这些问题有一个单独的板。 Software Recommendations StackExchange,但您可以在使用 PowerShell 时使用 PGP。

如果您说的是适用于所有 Windows PowerShell 版本的 AES 文件加密版本,您需要为此使用 .Net 命名空间。具体来说,NET 的 FileStream 和 CryptoStream 类使用 AES 加密整个文件,正如通过此脚本下载演示的那样。

PowerShell Encryption Examples 5 个不同技术示例,可用于使用 PowerShell 安全加密(并且在大多数情况下共享)机密数据。

具体例子3

或者使用这个模块。

Share encrypted data between users and computers with PowerShell

附加的 zip 文件包含一个模块,该模块可以轻松地使用 PowerShell 加密数据,这样任何计算机上的其他授权用户都可以对其进行解密。它通过利用数字证书来做到这一点。

【讨论】:

  • 您可以通过以 v2 模式 (powershell.exe -version 2) 启动 PowerShell 并运行尝试实例化算法对象的语句来在其他 PowerShell 版本上重现该问题:[System.Security.Cryptography.SymmetricAlgorithm]::Create('AES')
  • 同意,这是已知的,thx,但 PSv2 已被策略删除/禁用,并且 corpsec 受到监控,因此,我的笔记。我想我本可以等待并在我的家庭系统上进行健全性检查,或者建立一个单独的 VM,但是,我并没有真正看到那时需要这样做。
【解决方案3】:

您使用的模块至少需要 PowerShell v3,否则声明

$Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm)

在您尝试调用的函数中不会创建算法对象,这反过来会导致

$Crypto.GenerateKey()

因您观察到的错误而失败。

将您的 Windows 7 系统升级到 PowerShell v3 或更高版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    • 2017-08-28
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多