Как зашифровать данные в одном экземпляре 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.

0 ответов

Другие вопросы по тегам