2016-11-18 2 views
1

J'essaie de crypter un texte à l'aide d'AWS KMS et de créer un script PowerShell. J'ai donc utilisé New-KMSDataKey pour crypter ma clé principale KMS qui en sortie renvoie plaintextDataKey et ciphertextblob.Comment crypter des données à l'aide de la clé KMS dans le script AWS Powershell

Maintenant, je me sers plaintextDataKey pour chiffrer mon texte en clair à l'aide Invoke-KMSEncrypt mais j'obtiens l'erreur d'opération non valide comme indiqué ci-dessous:

enter image description here

ci-dessous est mon script:

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 

Que peut Je fais pour le faire correctement? Est-ce que je fais quelque chose de mal ici? Il n'y a pas d'autres cmdlets ici pour crypter des données: http://docs.aws.amazon.com/powershell/latest/reference/Index.html

Quelqu'un peut-il aider s'il vous plaît ici? Comment puis-je utiliser la clé de données en texte brut ci-dessus pour crypter mon contenu?

Répondre

2

Le code présenté contient plusieurs des bons os pour faire partie de cet animal, mais il a plusieurs problèmes qui l'empêchent de fonctionner, y compris l'absence de certains concepts sous-jacents à KMS. L'utilisation de clés de données est une excellente façon de travailler avec KMS, mais lorsque vous faites cela, vous devez comprendre que vous devez compter sur la capacité de votre système hôte à crypter et déchiffrer les données avec les clés fournies.

Les clés de données KMS fournissent envelope encryption et le décryptage et le décryptage fournis par KMS concernent la clé elle-même et non vos données. Lorsque vous utilisez des clés de données, vous devez utiliser la clé en clair que le KMS fournit pour chiffrer vos données, puis stocker la version chiffrée de la clé fournie avec les données. Lorsqu'il est temps de décrypter votre texte chiffré, vous utilisez KMS pour déchiffrer la clé de données, puis utilisez le texte en clair dérivé de la clé de chiffrement de clé de données comme clé dans votre déchiffrement AES.

Voici un exemple d'un essai de paire travail de scripts que je Dérivée à partir du code que vous avez fourni, avec l'ID de clé KMS frotté:

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 

Et voici le chiffrement et le déchiffrement des scripts:

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 
}