如何在 AWS Powershell 脚本中使用 KMS 密钥加密数据

2024-02-18

我正在尝试使用 AWS KMS 加密文本并创建 powershell 脚本。所以我用了New-KMSDataKey加密我的 KMS 主密钥,该密钥在输出中返回plaintextDataKey and ciphertextblob.

现在我正在使用plaintextDataKey使用加密我的明文Invoke-KMSEncrypt但我收到无效操作错误,如下所示:

下面是我的脚本:

param([string]$zonesecret, [string]$KMSKey, [string]$Keyspec, [string]$region= 'us-east-1', [string]$AccessKey, [string]$SecretKey)

# splat
$splat = @{KeyId=$KMSKey; KeySpec=$Keyspec; Region=$region}
# generate a data key 
$datakey = New-KMSDataKey @splat

$plaintextDataKey = [Convert]::ToBase64String($datakey.Plaintext.ToArray())
$encryptedDataKey = [Convert]::ToBase64String($datakey.CiphertextBlob.ToArray())
Write-Host $plaintextDataKey
Write-Host $encryptedDataKey

#encrypt using aes-256; pass zonesecret and plaintextDataKey
# memory stream
[byte[]]$byteArray = [System.Text.Encoding]::UTF8.GetBytes($zonesecret)
$memoryStream = New-Object System.IO.MemoryStream($byteArray,0,$byteArray.Length)

$splat = @{Plaintext=$memoryStream; KeyId=$plaintextDataKey; Region=$region;}
if(![string]::IsNullOrEmpty($AccessKey)){$splat += @{AccessKey=$AccessKey;}}
if(![string]::IsNullOrEmpty($SecretKey)){$splat += @{SecretKey=$SecretKey;}}

# encrypt
**$encryptedMemoryStream = Invoke-KMSEncrypt @splat** # ERROR: 
Write-Host $encryptedMemoryStream

$base64encrypted = [System.Convert]::ToBase64String($encryptedMemoryStream.CiphertextBlob.ToArray())
Write-Host $base64encrypted

我能做些什么来纠正它?我在这里做错了什么吗?这里没有其他 cmdlet 来加密数据:http://docs.aws.amazon.com/powershell/latest/reference/Index.html http://docs.aws.amazon.com/powershell/latest/reference/Index.html

有人可以帮忙吗?如何使用上述明文数据密钥来加密我的内容?


所提供的代码包含许多成为该动物一部分的正确骨骼,但它存在一些阻碍其工作的问题,包括缺少一些支撑 KMS 的概念。使用数据密钥是使用 KMS 的好方法,但是当您这样做时,您必须了解您需要依赖主机系统使用提供的密钥加密和解密数据的能力。

KMS 数据密钥提供信封加密 http://docs.aws.amazon.com/kms/latest/developerguide/workflow.htmlKMS 提供的支持以及加密和解密是针对密钥本身,而不是您的数据。使用数据密钥时,您必须使用 KMS 提供的明文密钥来加密您的数据,然后将提供的密钥的密文版本与数据一起存储。当需要解密您的密文时,您可以使用 KMS 来解密数据密钥然后使用从数据密钥密文密钥派生的明文作为 AES 解密中的密钥。

以下是从我从您提供的代码中派生的工作脚本对进行测试运行的示例,其中 KMS 密钥 ID 已被删除:

PS C:\Users\Administrator> $kmskey =  'abcdef01-2345-6789-0123-0123456789ab'
PS C:\Users\Administrator> ./encrypt.ps1 "This is a test" -KMSKey $kmskey | ConvertTo-Json > message.json
PS C:\Users\Administrator> type message.json
{
    "encryptedDataKey":      "AQEDAHix3RkObJxNv8rJGn2Oyy0bRR9GOvSOFTHR2OQ6SBt76wAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDGui8Ycxf+XoJkAkuQIBEIA7R6eiM6PREoJdnaNA5gaeZfcSA3fC3UlRYGE6Epo96U+SqYPYzyXKOEyqB+1+3pCHz2zgZZlbcgzThrs=",
    "ciphertext":  "76492d1116743f0423413b16050a5345MgB8AGwANgBEAEwAaQB5AFQAOQByAGgAYgBPAGcAagBKAGIAQQBBAEwAQgBkAEEAPQA9AHwAMgAzADIAYgA0AGEAYgBlADgAMAA5AGQAZABkADEAOQBlADkAYgBjADgAZgA2ADgAMAA0ADgAZABhADQANQA5ADYAMABiAGIAYQAxADQANABiADAAOAA2ADYANgBlAGYANwAxADkANQA2ADEAMgBjAGEANQBjADAAYgBjAGMANAA=\r\n"
}
PS C:\Users\Administrator> ConvertFrom-JSON $(Get-Content .\message.json | Out-String) | .\decrypt.ps1 -KMSKey $kmskey

plaintext
---------
This is a test

PS C:\Users\Administrator> ./encrypt.ps1 "Super Secret Stuff" -KMSKey $kmskey | .\decrypt.ps1 -KMSKey $kmskey

plaintext
---------
Super Secret Stuff

这是加密和解密脚本:

加密.ps1

param(
    [Parameter(Mandatory=$True)]
    [string]$secret,

    [Parameter(Mandatory=$True)]
    [string]$KMSKey,

    [string]$Keyspec = 'AES_256',

    [string]$region = 'us-east-1'
)

# generate a data key
$datakey = New-KMSDataKey -KeyId $KMSKey -KeySpec $Keyspec -Region $region

[byte[]]$plaintextDataKey = $datakey.Plaintext.ToArray()
[byte[]]$encryptedDataKey = $datakey.CiphertextBlob.ToArray()

# Encrypt using AES using Powershell's SecureString facilities
# Any AES encryption method would do, this is just the most convenient
# way to do this from Powershell.
#
# Note that trying to use the Invoke-KMSEncrypt method is not what you want
# to do when using Data Keys and envelope encryption.
$encrypted = ConvertTo-SecureString $secret -AsPlainText -Force `
    | ConvertFrom-SecureString -key $plaintextDataKey `
    | Out-String

# Thanks to http://stackoverflow.com/a/24778625/424301 
# for the tip on using psobject return values and
# ValueFromPipelineByPropertyName parameters (see decrypt.ps1)
return New-Object psobject -property @{ 
    "ciphertext" = $encrypted;
    "encryptedDataKey" = $([Convert]::ToBase64String($encryptedDataKey))
}

解密.ps1

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true,
        Position=0,
        ValueFromPipelineByPropertyName=$true)]
    [string]$ciphertext,

    [Parameter(Mandatory=$true,
        Position=1,
        ValueFromPipelineByPropertyName=$true)]
    [string]$encryptedDataKey,

    [Parameter(Mandatory=$true,
        Position=2,
        ValueFromPipelineByPropertyName=$true)]
    [string]$KMSKey
)

[byte[]]$bytes = $([Convert]::FromBase64String($encryptedDataKey))
$stream = new-object System.IO.MemoryStream (,$bytes)

# decrypt the data key 
$response = Invoke-KMSDecrypt -CiphertextBlob $stream
if ($response.HttpStatusCode -eq 200) {
    $dataKey = $response.Plaintext.ToArray()
} else {
    throw "KMS data key decrypt failed: $(ConvertTo-Json $response)"
}
# Now AES decrypt the ciphertext and emit the plaintext
$secureString = ConvertTo-SecureString $ciphertext -key $dataKey
$plaintext =  [Runtime.InteropServices.Marshal]::PtrToStringAuto( `
    [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString))
return  New-Object psobject -property @{
    "plaintext" = $plaintext
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 AWS Powershell 脚本中使用 KMS 密钥加密数据 的相关文章

随机推荐