2016-11-18 45 views
1

我試圖使用AWS KMS加密文本並創建PowerShell腳本。所以我用New-KMSDataKey來加密我的KMS主密鑰,它在輸出中返回plaintextDataKeyciphertextblob如何使用AWS Powershell腳本中的KMS密鑰加密數據

我現在用的plaintextDataKey使用Invoke-KMSEncrypt加密我的明文,但我得到無效的操作錯誤,如下圖所示:

enter image description here

下面是我的腳本:

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

任何人都可以請幫忙嗎?我如何使用上面的明文數據密鑰來加密我的內容?

回答

2

提出的代碼有許多正確的骨頭,它是這個動物的一部分,但它有幾個問題阻止它的工作,包括缺少支持KMS的一些概念。使用數據密鑰是使用KMS的好方法,但是當您這樣做時,您必須瞭解您需要依賴主機系統使用提供的密鑰來加密和解密數據的能力。

KMS數據密鑰提供envelope encryption,KMS提供的解密和解密僅用於密鑰本身,而不是數據。使用數據密鑰時,您必須使用KMS提供的明文密鑰來加密您的數據,然後存儲您在數據旁邊提供的密鑰的密文版本。當需要解密密文時,可以使用KMS解密數據密鑰,然後使用從數據密鑰密文密鑰導出的明文作爲AES解密中的密鑰。

下面是工質對,我從你提供的代碼導出腳本的測試運行的一個例子,與擦洗KMS密鑰ID:

PS C:\Users\Administrator> $kmskey = 'abcdef01-2345-6789-0123-ab' 
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 

這裏是加密和解密的腳本:

encrypt.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)) 
} 

decrypt.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 
} 
相關問題