UWP - шифрование данных с помощью перекрестного устройства

Приложение My UWP хранит данные в зашифрованном виде в локальной базе данных SQLite на устройстве. Я использую классы Windows.Security.Cryptography.DataProtection для статических данных, а также для шифрования/дешифрования потоков данных (Ref: https://docs.microsoft.com/en-us/windows/uwp/security/cryptography)

Я предоставил средство резервного копирования данных OneDrive с идеей, что пользователь может сделать резервную копию всей базы данных OneDrive с одного устройства и восстановить ее в приложении, установленном на другом устройстве. Это может помочь пользователю использовать приложение на нескольких устройствах, а также в случае приобретения пользователем нового устройства.

Я использую дескриптор "LOCAL=user" для класса DataProtectionProvider (Ref: https://docs.microsoft.com/en-us/uwp/api/windows.security.cryptography.dataprotection.dataprotectionprovider)

Я надеялся, что если я войду в систему с помощью моей учетной записи Microsoft на двух разных устройствах, и я зашифрую данные на одном устройстве, а затем восстановите данные на другом, тогда данные должны быть дешифрованы; однако этого не происходит.

Мне также не удалось получить документацию (кроме ссылок, перечисленных выше). Я также искал SO для поддержки MS, но не повезло. Может кто-нибудь помочь мне с этим?

Мое требование: данные, зашифрованные на одном (Windows) устройстве, должны быть дешифрованы на другом (Windows) устройстве (когда пользователь регистрируется с использованием той же учетной записи Microsoft на обоих устройствах).

[ОБНОВЛЕНИЕ]

Здесь пример кода:

const BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
        const string strDescriptor = "LOCAL=user";        

public static async Task<string> ProtectTextAsync(string strClearText)

    {
        DataProtectionProvider Provider = new DataProtectionProvider(strDescriptor);

        IBuffer buffMsg = CryptographicBuffer.ConvertStringToBinary(strClearText, encoding);

        IBuffer buffProtected = await Provider.ProtectAsync(buffMsg);

        return CryptographicBuffer.EncodeToBase64String(buffProtected);
    }

    public static async Task<String> UnprotectTextAsync(string strProtected)
    {
        DataProtectionProvider Provider = new DataProtectionProvider();

        IBuffer buffProtected = CryptographicBuffer.DecodeFromBase64String(strProtected);

        IBuffer buffUnprotected = await Provider.UnprotectAsync(buffProtected);

        String strClearText = CryptographicBuffer.ConvertBinaryToString(encoding, buffUnprotected);

        return strClearText;
    }

Код тривиален; однако процесс воспроизведения ошибок важен и выглядит следующим образом:

Я запустил приложение на своем Windows 10 Mobile (OS build: 10.0.14393.1770), затем выполнил резервное копирование данных на OneDrive. Мой мобильный телефон показывает, что я использую учетную запись Microsoft (например, [email protected]) в настройках → Учетные записи → Информация.

Теперь я подключился к своему ноутбуку под управлением Windows 10 (версия ОС: 15063.674 версии: 1703 с обновлением Fall Creators Update SDK), используя учетную запись [email protected], когда я запускаю приложение и Восстановите резервную копию с OneDrive. Теперь, когда я пытаюсь получить доступ к данным, я получаю ошибку в строке IBuffer buffUnprotected = await Provider.UnprotectAsync(buffProtected); метода UnprotectTextAsync. Ошибка:

System.Exception: 'The specified data could not be decrypted. (Excep_FromHResult 0x8009002C)'

Обратите внимание, что если я восстановил резервную копию данных на OneDrive с того же устройства (Mobile или Laptop), тогда этот код будет работать нормально. Таким образом, функция Backup/Restore работает корректно без изменения данных.

Ответ 1

Я попытаюсь сохранить его вкратце, но есть несколько способов, которыми вы можете это сделать, сначала сначала поговорите о UWP storage.

UWP предоставляет API-интерфейсы для хранения пользовательских настроек и настроек вместе с данными в трех типах хранения:

  • Local:. Это в основном хранение данных в виде данных приложения в локальном хранилище самого устройства. Что вы можете здесь хранить? Это для всех видов данных, которые могут быть сериализованы. Он не должен быть слишком тяжелым, иначе он подбрасывает вам Access Violation Exception. Я когда-то использовал его для хранения изображения в потоках байтов, так что он обеспечивает большую гибкость, когда дело доходит до хранения.
  • PasswordVault: Обычно это хранить учетные данные пользователя на нескольких устройствах, чтобы при использовании не было sign in для вашего приложения на каждом устройстве, если у вас есть одна и та же учетная запись Microsoft, он сразу же выйдет в систему. Вам не нужно явно шифровать данные внутри него, так как API автоматически шифрует данные для вас при передаче и хранении данных через устройства.
  • Roaming: Теперь это вас больше всего интересует. Параметры роуминга - это те, которые передаются через устройство, если вы вошли в систему с той же учетной записью Microsoft. Данные не будут зашифрованы неявно, поэтому вам придется обрабатывать аспекты безопасности для него. Он обычно используется для передачи Settings для приложения и Preferences для пользователя, если у него есть что-то (например, Тема приложения, Обои). Windows 10 OS Использует это хранилище для передачи всяких вещей при установке windows 10 на другой машине, вы можете найти полный список здесь. Это просто потрясающе.

Поиск наилучшего соответствия:

Теперь, когда мы рассмотрели наши варианты, попробуйте решить вашу проблему и как выбрать хранилище.

Поскольку вам приходится передавать данные по нескольким устройствам, хранилище Local не может быть и речи. Теперь у нас есть две опции: PasswordVault и RoamingStorage / RoamingSettings.

Вопрос в том, что вы хотите передать (для которого вы используете один диск), это всего лишь куча предпочтений? или это файлы разных размеров? или это учетные данные пользователя?

  • Если это учетные данные пользователя, PasswordVault идеально подходит. Он не только обрабатывает DataTransfer, но также обеспечивает бесшовную интегрированную signIn на всех устройствах, если пользователь использует ту же учетную запись Microsoft.
  • Если это всего лишь куча предпочтений, используйте RoamingSettings. Они передадут данные другим устройствам с помощью Microsoft APIs, и все, что вам нужно сделать, - извлечь их из контейнера RoamingStorage, и вы можете начать использовать данные.
  • Но если это куча файлов, зашифрованных и сохраненных на one drive и вы хотите расшифровать на других устройствах ниже, это решение, которое я рекомендую.

Чтение файлов с одного диска, дешифрование на других устройствах:

Подход может быть довольно простым, если у вас есть файлы, которые хранятся на one drive,

  • Когда приложение впервые регистрируется в приложении, проверьте, присутствует ли roamSettings для этой учетной записи Microsoft для вашего приложения или нет, так как он не вернет вам null. В таком случае создайте RoamingStorage и перейдите к шагу 2.

  • Создайте keys, который понадобится для шифрования. (объясняется в подробно в следующем разделе ниже)

  • Теперь, когда у вас есть keys, вы выполняете все операции, чтобы получить данные, которые необходимо записать в файлы.

  • Зашифруйте данные с помощью keys для encryption и как только данные будут зашифрованы, запишите их в файл и загрузите в oneDrive.

  • Сохраните keys (см. следующий раздел ниже) в roaming storage для этой учетной записи Microsoft.

  • Теперь, когда пользователь заходит в приложение с помощью другого устройства, как в point 1, проверьте, существует ли RoamingSettings. Только на этот раз он не будет пустым, и вы получите пользователя RoamingSettings для приложения на другое устройство. извлеките сохраненный key оттуда и сохраните его в variable.

  • Загрузите файлы из oneDrive и прочитайте их содержимое как string.

  • Используйте key, хранящийся в переменной (пункт 6), чтобы дешифровать данные файла

  • Теперь у вас есть фактические данные, возобновите поток приложений.

Быстрый просмотр шифрования

Шифрование выходит за рамки этого вопроса, поэтому я просто объясню его базовую схему, и если какая-либо помощь понадобится, используйте раздел комментариев.

Вышеупомянутое решение также будет зависеть от типа шифрования, который вы используете здесь, если его

  • Symmetric: Если вы используете симметричный (например, AES), то вы создаете encryption key и InitializationVector (также называемые IV) на первое устройство, как только пользователь войдет в систему и сохранит их в RoamingSettings

  • Asymmetric: Если вы используете асимметричный (например, RSA), вы создадите набор ключей publicKey и privateKey, используя publicKey зашифровать данные и затем сохранить их на one drive, а затем сохранить privateKey в настройках роуминга.

Не рекомендуется делиться личными ключами по сети с использованием асимметричного шифрования, но это немного необычно, но вы используете установленные API Microsoft для передачи данных (которые, по их утверждению, являются безопасными), что уменьшит риск.

Пожалуйста, дайте мне знать, если я что-то пропустил.

Изменить комментарий:

Если честно, так как вы упоминали один key, вы говорите о AES-256. Теперь, если вы не хотите, чтобы developer имел доступ к ключу, он вроде бы по умолчанию, вы бы использовали Cryptography APIs для Microsoft для AES. Таким образом, я таким образом вы вызываете API, который даст вам ключ, и вы будете звонить другому API, который будет шифровать данные. Самое главное. API будет вызываться в runtime, так что любой из них не имеет доступа к нему.

Но если ваш запрос заключается в том, что разработчик не должен даже знать, какое шифрование и где он хранится, тогда в этом случае я рекомендую вам использовать Factory Pattern, где в вас abstract выполнить реализацию данных который получает encrypted, вы просто передаете данные, что класс обрабатывает все создание ключа, шифрование данных и сохранение ключа в роуминге, а затем возвращает зашифрованные данные.


Литература: