提示されたコードには、この動物の一部として適切なボーンが多数含まれていますが、KMS を支える概念の一部が欠落しているなど、動作を妨げるいくつかの問題があります。データ キーの使用は KMS を操作する優れた方法ですが、その場合は、提供されたキーを使用してデータを暗号化および復号化するホスト システムの機能に依存する必要があることを理解する必要があります。
KMS データ キーは、エンベロープ暗号化のサポートを提供します。KMS が提供する暗号化と復号化は、データではなくキー自体に対して行われます。データ キーを使用する場合は、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
}