Как зашифровать данные в одном экземпляре Windows и расшифровать в другом экземпляре ОС, работающем в той же системе?
Это расширение статьи Как зашифровать данные в одном приложении и расшифровать их в другом приложении Windows с ключами RSA, привязанными к локальной системе?.
Из связанного вопроса выше я смог зашифровать/расшифровать данные между несколькими приложениями в одном экземпляре ОС (например, Windows10). Затем я загружаюсь во второй экземпляр Windows 10 в той же системе в рамках настройки двойной загрузки. Приложению по ссылке выше не удалось расшифровать данные. Мне нравится выполнять шифрование/дешифрование между приложениями, работающими в разных экземплярах Windows 10, работающих в одной физической системе. Я думал, что сохранение ключа сохранит ключ в TPM, и приложение из другого экземпляра ОС сможет получить тот же ключ и использовать его.
Позволяет ли стек TPM или CNG в Windows10 создавать запечатанные ключи TPM или закрытые ключи, которые существуют только в TPM, но к которым можно получить доступ из любого экземпляра ОС Windows, работающего в той же системе?
03.08.2022:
Обновлен фрагмент кода на основе предложения @bartonjs ниже. Теперь он не может расшифровать, выдавая исключение, что операция не поддерживается.
using System;
using System.IO;
using System.Security.Cryptography;
namespace TPMCrypto
{
class Program
{
static byte[] data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
static byte[] privateKey;
private static byte[] encrypted;
private static byte[] decrypted;
static void Main(string[] args)
{
const string MyKey = "MyRSAKey";
CngKey cngKey = null;
string cmd = args.Length > 0 ? args[0] : "";
try
{
CngProvider theTPMProvider = new CngProvider("Microsoft Platform Crypto Provider");
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
ExportPolicy = CngExportPolicies.None,
KeyUsage = CngKeyUsages.AllUsages,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Provider = theTPMProvider,
Parameters =
{
new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.Persist),
},
};
if (!CngKey.Exists(MyKey, theTPMProvider, CngKeyOpenOptions.MachineKey))
{
Console.WriteLine("Creating rsaKey");
cngKey = CngKey.Create(CngAlgorithm.Rsa, MyKey, cng);
}
else
{
Console.WriteLine("Opening rsaKey");
cngKey = CngKey.Open(MyKey, theTPMProvider, CngKeyOpenOptions.MachineKey);
}
RSACng rsaKey = new RSACng(cngKey);
//privateKey = rsaKey.Key.Export(CngKeyBlobFormat.GenericPrivateBlob);
//string prvResult = ByteArrayToHexString(privateKey, 0, privateKey.Length);
//Console.WriteLine("\nPrivate key - length = " + privateKey.Length + "\n" + prvResult + "\n");
const string FILE_PATH = @"\temp\tpmtests\encryptedblob.dat";
// Encrypt / decrypt
if (cmd == "readfromfile")
{
Directory.CreateDirectory(Path.GetDirectoryName(FILE_PATH));
encrypted = File.ReadAllBytes(FILE_PATH);
}
else if (cmd == "deletekey")
{
cngKey.Delete();
return;
}
else
{
encrypted = Encrypt(rsaKey, data);
Console.WriteLine("The encrypted blob: ");
Console.WriteLine(ByteArrayToHexString(encrypted, 0, encrypted.Length));
File.WriteAllBytes(FILE_PATH, encrypted);
}
decrypted = Decrypt(rsaKey, encrypted);
bool result = ByteArrayCompare(data, decrypted);
if (result)
Console.WriteLine("Encrypt / decrypt works");
else
Console.WriteLine("Encrypt / decrypt fails");
}
catch (Exception e)
{
Console.WriteLine("Exception " + e.Message);
}
finally
{
if (cngKey != null)
cngKey.Dispose();
}
Console.ReadLine();
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1.Length != a2.Length)
return false;
for (int i = 0; i < a1.Length; i++)
if (a1[i] != a2[i])
return false;
return true;
}
public static string ByteArrayToHexString(byte[] bytes, int start, int length)
{
string delimitedStringValue = BitConverter.ToString(bytes, start, length);
return delimitedStringValue.Replace("-", "");
}
public static byte[] Sign512(byte[] data, byte[] privateKey)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
return crypto.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static bool VerifySignature512(byte[] data, byte[] signature, byte[] publicKey)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
return crypto.VerifyData(data, signature, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static byte[] Encrypt(byte[] publicKey, byte[] data)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
var result = Encrypt(crypto, data);
return result;
}
public static byte[] Encrypt(RSACng crypto, byte[] data)
{
if (null == crypto)
return null;
var result = crypto.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
return result;
}
public static byte[] Decrypt(byte[] privateKey, byte[] data)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
var result = Decrypt(crypto, data);
return result;
}
public static byte[] Decrypt(RSACng aKey, byte[] data)
{
if (null == aKey)
return null;
var result = aKey.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
return result;
}
}
}
Обновление от 04.08.22
С изменением заполнения выше на SHA256 я смог зашифровать/расшифровать данные с использованием ключей TPM в рамках одного сеанса ОС, а также отдельных сеансов ОС одного и того же экземпляра ОС.
Затем я загрузил систему, используя другой экземпляр ОС Windows на USB-накопителе. Запустил приложение. Это не удалось со следующим стеком вызовов.
>TPMCrypto.exe readfromfile
Exception Message: Unknown error "-1073741275".
Exception stack: System.Security.Cryptography.CryptographicException: Unknown error "-1073741275".
at System.Security.Cryptography.NCryptNative.OpenStorageProvider(String providerName)
at System.Security.Cryptography.CngKey.Exists(String keyName, CngProvider provider, CngKeyOpenOptions options)
at TPMCrypto.Program.Main(String[] args) in TPMCrypto\Program.cs:line 37
Приложению не удается открыть TPM KSM, и приложение работает с правами администратора. То же приложение с «Microsoft Software Storage Provider» смогло открыть KSP, это TPM, который не может открыть KSP.
Непонятно, что означает код ошибки -1073741275.