Как расшифровать строку в C#, которая зашифрована с помощью PowerShell
Можно ли расшифровать строку в C#, которая зашифрована с помощью PowerShell и как?
Строка зашифрована с помощью PowerShell, как показано ниже:
$pw = read-host "Enter Password" –AsSecureString
ConvertFrom-SecureString $pw | out-file "C:\file.txt"
Чтобы преобразовать его обратно в PowerShell, я могу использовать эти команды, которые вызывают класс C# System.Runtime.InteropServices.Marshal
,
$pwdSec = Get-Content "C:\file.txt" | ConvertTo-SecureString
$bPswd = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwdSec)
$pswd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bPswd)
Файл содержит строку, которая была преобразована в зашифрованный стандарт string("hello")
,
Так что если открыть file.txt
файл выглядит примерно так:
01000000d08c9ddf0115d1118c7a00c04fc297eb0100000052ded6c2db80e748933432e19b9de8b10000
000002000000000003660000c00000001000000016dc35885d76d07bab289eb9927cfc1e000000000480
0000a0000000100000003106cde553f45b08d13d89d11336170b280000005cc865c1ee1b57e84ed3d1a2
d3f2d0ec0f189b532e61c18d1f31444d6f119a1e8368477fd2d81f54140000000cb0262e58b08ae14f37
22c14c69684841b6b21c
1 ответ
Выходной файл из ConvertFrom-SecureString
у вас есть строка UTF-16 (пароль), защищенная ProtectedData.Protect
хранится в виде шестнадцатеричного дампа.
Отмените использование кодировки:
// Read file to string
string exportedData = File.ReadAllText(@"file.txt");
// Remove all new-lines
exportedData = exportedData.Replace(Environment.NewLine, "");
// Convert the hex dump to byte array
int length = exportedData.Length / 2;
byte[] encryptedData = new byte[length];
for (int index = 0; index < length; ++index)
{
encryptedData[index] =
byte.Parse(
exportedData.Substring(2 * index, 2),
NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
// Decrypt the byte array to Unicode byte array
byte[] data =
ProtectedData.Unprotect(encryptedData, (byte[])null, DataProtectionScope.CurrentUser);
// Convert Unicode byte array to string
string password = Encoding.Unicode.GetString(data);
Приведенный выше код работает, когда вы не указали -Key
с ConvertFrom-SecureString
, Защищенная строка затем защищается с помощью API защиты данных Windows (DPAPI). Как таковая строка должна быть декодирована на той же машине и учетной записи, в которой она была закодирована.
У меня было требование зашифровать строку в оболочке Power и расшифровать в.Net. Найдите следующую функцию для шифрования любой строки. здесь (1..16) - байтовый массив.
function EncriptStringData {
[CmdletBinding()]
param (
[string] $PlainText
)
$someSecureString = $PlainText | ConvertTo-SecureString -AsPlainText -Force
$encryptedTextThatIcouldSaveToFile = ConvertFrom-SecureString -key (1..16) -SecureString $someSecureString
return $encryptedTextThatIcouldSaveToFile
}
Теперь этот вывод строки с шифрованием я использовал в качестве ввода для моей программы.Net и получил тот же PlainText обратно в качестве вывода моей программы.Net. Найдите следующую функцию.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
namespace MyNameSpace
{
public class DecryptStringData
{
public string GetDecryptString(string EncriptData)
{
try
{
byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] asBytes = Convert.FromBase64String(EncriptData);
string[] strArray = Encoding.Unicode.GetString(asBytes).Split(new[] { '|' });
if (strArray.Length != 3) throw new InvalidDataException("input had incorrect format");
byte[] magicHeader = HexStringToByteArray(EncriptData.Substring(0, 32));
byte[] rgbIV = Convert.FromBase64String(strArray[1]);
byte[] cipherBytes = HexStringToByteArray(strArray[2]);
SecureString str = new SecureString();
SymmetricAlgorithm algorithm = SymmetricAlgorithm.Create(); //This for .Net 4.5
//Use this for .Net core // AesManaged algorithm = new AesManaged();
ICryptoTransform transform = algorithm.CreateDecryptor(key, rgbIV);
using (var stream = new CryptoStream(new MemoryStream(cipherBytes), transform, CryptoStreamMode.Read))
{
int numRed = 0;
byte[] buffer = new byte[2]; // two bytes per unicode char
while ((numRed = stream.Read(buffer, 0, buffer.Length)) > 0)
{
str.AppendChar(Encoding.Unicode.GetString(buffer).ToCharArray()[0]);
}
}
string secretvalue = convertToUNSecureString(str);
return secretvalue;
}
catch (Exception ex)
{
return ex.Message;
}
}
public static byte[] HexStringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2) bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
public static string convertToUNSecureString(SecureString secstrPassword)
{
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secstrPassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}
}