Fix ConvertTo-SecureString
with key regression due to .NET breaking change (#16068)
This commit is contained in:
parent
12dbdd9f05
commit
0d7ba2fe5a
|
@ -217,8 +217,6 @@ namespace Microsoft.PowerShell
|
|||
/// <returns>A string (see summary).</returns>
|
||||
internal static EncryptionResult Encrypt(SecureString input, SecureString key)
|
||||
{
|
||||
EncryptionResult output = null;
|
||||
|
||||
//
|
||||
// get clear text key from the SecureString key
|
||||
//
|
||||
|
@ -227,14 +225,14 @@ namespace Microsoft.PowerShell
|
|||
//
|
||||
// encrypt the data
|
||||
//
|
||||
output = Encrypt(input, keyBlob);
|
||||
|
||||
//
|
||||
// clear the clear text key
|
||||
//
|
||||
Array.Clear(keyBlob, 0, keyBlob.Length);
|
||||
|
||||
return output;
|
||||
try
|
||||
{
|
||||
return Encrypt(input, keyBlob);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(keyBlob);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -254,48 +252,46 @@ namespace Microsoft.PowerShell
|
|||
Utils.CheckSecureStringArg(input, "input");
|
||||
Utils.CheckKeyArg(key, "key");
|
||||
|
||||
byte[] encryptedData = null;
|
||||
MemoryStream ms = null;
|
||||
ICryptoTransform encryptor = null;
|
||||
CryptoStream cs = null;
|
||||
|
||||
//
|
||||
// prepare the crypto stuff. Initialization Vector is
|
||||
// randomized by default.
|
||||
//
|
||||
Aes aes = Aes.Create();
|
||||
if (iv == null)
|
||||
iv = aes.IV;
|
||||
|
||||
encryptor = aes.CreateEncryptor(key, iv);
|
||||
ms = new MemoryStream();
|
||||
|
||||
using (cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
if (iv is null)
|
||||
{
|
||||
iv = aes.IV;
|
||||
}
|
||||
|
||||
//
|
||||
// get clear text data from the input SecureString
|
||||
//
|
||||
byte[] data = GetData(input);
|
||||
try
|
||||
{
|
||||
using (ICryptoTransform encryptor = aes.CreateEncryptor(key, iv))
|
||||
using (var sourceStream = new MemoryStream(data))
|
||||
using (var encryptedStream = new MemoryStream())
|
||||
{
|
||||
//
|
||||
// encrypt it
|
||||
//
|
||||
using (var cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
sourceStream.CopyTo(cryptoStream);
|
||||
}
|
||||
|
||||
//
|
||||
// encrypt it
|
||||
//
|
||||
cs.Write(data, 0, data.Length);
|
||||
cs.FlushFinalBlock();
|
||||
|
||||
//
|
||||
// clear the clear text data array
|
||||
//
|
||||
Array.Clear(data, 0, data.Length);
|
||||
|
||||
//
|
||||
// convert the encrypted blob to a string
|
||||
//
|
||||
encryptedData = ms.ToArray();
|
||||
|
||||
EncryptionResult output = new EncryptionResult(ByteArrayToString(encryptedData), Convert.ToBase64String(iv));
|
||||
|
||||
return output;
|
||||
//
|
||||
// return encrypted data
|
||||
//
|
||||
byte[] encryptedData = encryptedStream.ToArray();
|
||||
return new EncryptionResult(ByteArrayToString(encryptedData), Convert.ToBase64String(iv));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,8 +307,6 @@ namespace Microsoft.PowerShell
|
|||
/// <returns>SecureString .</returns>
|
||||
internal static SecureString Decrypt(string input, SecureString key, byte[] IV)
|
||||
{
|
||||
SecureString output = null;
|
||||
|
||||
//
|
||||
// get clear text key from the SecureString key
|
||||
//
|
||||
|
@ -321,14 +315,14 @@ namespace Microsoft.PowerShell
|
|||
//
|
||||
// decrypt the data
|
||||
//
|
||||
output = Decrypt(input, keyBlob, IV);
|
||||
|
||||
//
|
||||
// clear the clear text key
|
||||
//
|
||||
Array.Clear(keyBlob, 0, keyBlob.Length);
|
||||
|
||||
return output;
|
||||
try
|
||||
{
|
||||
return Decrypt(input, keyBlob, IV);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(keyBlob);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -346,44 +340,33 @@ namespace Microsoft.PowerShell
|
|||
Utils.CheckArgForNullOrEmpty(input, "input");
|
||||
Utils.CheckKeyArg(key, "key");
|
||||
|
||||
byte[] decryptedData = null;
|
||||
byte[] encryptedData = null;
|
||||
SecureString s = null;
|
||||
|
||||
//
|
||||
// prepare the crypto stuff
|
||||
//
|
||||
Aes aes = Aes.Create();
|
||||
encryptedData = ByteArrayFromString(input);
|
||||
|
||||
var decryptor = aes.CreateDecryptor(key, IV ?? aes.IV);
|
||||
|
||||
MemoryStream ms = new MemoryStream(encryptedData);
|
||||
|
||||
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
|
||||
using (var aes = Aes.Create())
|
||||
{
|
||||
byte[] tempDecryptedData = new byte[encryptedData.Length];
|
||||
|
||||
int numBytesRead = 0;
|
||||
|
||||
//
|
||||
// decrypt the data
|
||||
//
|
||||
numBytesRead = cs.Read(tempDecryptedData, 0,
|
||||
tempDecryptedData.Length);
|
||||
|
||||
decryptedData = new byte[numBytesRead];
|
||||
|
||||
for (int i = 0; i < numBytesRead; i++)
|
||||
using (ICryptoTransform decryptor = aes.CreateDecryptor(key, IV ?? aes.IV))
|
||||
using (var encryptedStream = new MemoryStream(ByteArrayFromString(input)))
|
||||
using (var targetStream = new MemoryStream())
|
||||
{
|
||||
decryptedData[i] = tempDecryptedData[i];
|
||||
//
|
||||
// decrypt the data and return as SecureString
|
||||
//
|
||||
using (var sourceStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
sourceStream.CopyTo(targetStream);
|
||||
}
|
||||
|
||||
byte[] decryptedData = targetStream.ToArray();
|
||||
try
|
||||
{
|
||||
return New(decryptedData);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(decryptedData);
|
||||
}
|
||||
}
|
||||
|
||||
s = New(decryptedData);
|
||||
Array.Clear(decryptedData, 0, decryptedData.Length);
|
||||
Array.Clear(tempDecryptedData, 0, tempDecryptedData.Length);
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ Describe "SecureString conversion tests" -Tags "CI" {
|
|||
$string.ToCharArray() | ForEach-Object { $securestring.AppendChar($_) }
|
||||
}
|
||||
|
||||
It "using null arguments to ConvertFrom-SecureString produces an exception" {
|
||||
It "Using null arguments to ConvertFrom-SecureString produces an exception" {
|
||||
{ ConvertFrom-SecureString -SecureString $null -Key $null } |
|
||||
Should -Throw -ErrorId "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand"
|
||||
}
|
||||
|
||||
It "using a bad key produces an exception" {
|
||||
It "Using a bad key produces an exception" {
|
||||
$badkey = [byte[]]@(1,2)
|
||||
{ ConvertFrom-SecureString -SecureString $secureString -Key $badkey } |
|
||||
Should -Throw -ErrorId "Argument,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand"
|
||||
|
@ -27,9 +27,18 @@ Describe "SecureString conversion tests" -Tags "CI" {
|
|||
$ss | Should -BeOfType SecureString
|
||||
}
|
||||
|
||||
It "can convert back from a secure string" {
|
||||
It "Can convert back from a secure string" {
|
||||
$ss1 = ConvertTo-SecureString -AsPlainText -Force $string
|
||||
$ss2 = ConvertFrom-SecureString $ss1 | ConvertTo-SecureString
|
||||
$ss2 | ConvertFrom-SecureString -AsPlainText | Should -Be $string
|
||||
}
|
||||
|
||||
It "Can encode secure string with key" {
|
||||
$testString = '[8Chars][8Chars][Not8]'
|
||||
$key = [System.Text.Encoding]::UTF8.GetBytes("1234"*8)
|
||||
$ss1 = $testString | ConvertTo-SecureString -AsPlainText -Force
|
||||
$encodedStr = $ss1 | ConvertFrom-SecureString -Key $key
|
||||
$ss2 = $encodedStr | ConvertTo-SecureString -Key $key
|
||||
$ss2 | ConvertFrom-SecureString -AsPlainText | Should -BeExactly $testString
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue