このガイドでは、アプリケーションで使用するためにエクスポートされた Recall スナップショットを復号化する方法を開発者に示します。 すぐに実装できる作業コード サンプルを使用して、完全な復号化プロセスについて学習します。
Recallスナップショットのエクスポートは、欧州経済地域 (EEA) のデバイスでのみサポートされます。 Recall スナップショットのエクスポートは、ユーザーが開始するプロセスであり、ユーザーごとに行われます。 エクスポートされたスナップショットは暗号化されます。
Recallスナップショットをエクスポートする方法の詳細、またはこの AI に基づく機能の動作の詳細については、Recallの概要を参照してください。
[前提条件]
Recallスナップショットをエクスポートするオプションは、最新の Windows Insider Program プレビュー ビルドを実行しているヨーロッパ経済地域 (EEA) の Copilot+ PC デバイスでのみ使用できます。
開始する前に、次のものが必要です。
- エクスポートされたスナップショット: ユーザーは、最初 にスナップショット Recall エクスポート し、保存先のフォルダー パスを指定する必要があります。
- エクスポート コード: スナップショット のエクスポート中に提供される 32 文字 Recall エクスポート コード。
- 出力フォルダー: エクスポートされたスナップショットに関連付けられている復号化された .jpg ファイルと .json ファイルが保存される宛先フォルダー パス。
エクスポートされた Recall スナップショットの暗号化を解除する方法
Recallでエクスポートされたスナップショットを復号化するためのサンプル コードを使用します。 復号化のしくみを理解するには、以下の手順に従います。
エクスポートキーを計算する
ユーザーは、最初のRecallセットアップ時に保存するように求められたRecallエクスポート コードに加えて、エクスポートされたRecallスナップショットが保存されている場所 (フォルダー パス) を指定する必要があります。
Recallエクスポート コードは次のようになります。0a0a-0a0a-1111-bbbb-2222-3c3c-3c3c-3c3c
まず、ダッシュを削除して、32 文字の文字列を作成します。 0a0a0a0a1111bbbb22223c3c3c3c3c3c
std::wstring UnexpandExportCode(std::wstring code)
{
if (code.size() > 32)
{
code.erase(std::remove(code.begin(), code.end(), ' '), code.end()); // Remove spaces
code.erase(std::remove(code.begin(), code.end(), '-'), code.end()); // Remove hyphens
}
if (code.size() != 32)
{
std::wcout << L"The export code has incorrect number of characters."<< std::endl;
}
return code;
}
次に、16 進数の各ペアのバイト値を含む配列を作成します。
std::vector<uint8_t> HexStringToBytes(const std::wstring& hexString)
{
std::vector<uint8_t> bytes;
if (hexString.length() % 2 != 0)
{
throw std::invalid_argument("Hex string must have an even length");
}
for (size_t i = 0; i < hexString.length(); i += 2)
{
std::wstring byteString = hexString.substr(i, 2);
uint8_t byte = static_cast<uint8_t>(std::stoi(byteString, nullptr, 16));
bytes.push_back(byte);
}
return bytes;
}
次に、その配列を取得し、SHA256 ハッシュを計算します。その結果、エクスポート キーである 32 バイトの値になります。 これで、結果のエクスポート キーを使用して任意の数のスナップショットを復号化できるようになりました。
std::vector<uint8_t> exportKeyBytes(c_keySizeInBytes);
THROW_IF_NTSTATUS_FAILED(BCryptHash(
BCRYPT_SHA256_ALG_HANDLE,
nullptr,
0,
exportCodeBytes.data(),
static_cast<ULONG>(exportCodeBytes.size()),
exportKeyBytes.data(),
c_keySizeInBytes));
暗号化されたスナップショットの暗号化を解除する
スナップショットのレイアウト (リトル エンディアン形式): | uint32_t version | uint32_t encryptedKeySize | uint32_t encryptedContentSize | uint32_t contentType | uint8_t[KeySIze] encryptedContentKey | uint8_t[ContentSize] encryptedContent |
まず、4 つの uint32_t値を読み取ります。
EncryptedSnapshotHeader header{};
reader.ByteOrder(winrt::ByteOrder::LittleEndian);
header.Version = reader.ReadUInt32();
header.KeySize = reader.ReadUInt32();
header.ContentSize = reader.ReadUInt32();
header.ContentType = reader.ReadUInt32();
次に、バージョンの値が 2 であることを確認します。
if (header.Version != 2)
{
throw std::runtime_error("Insufficient data header version.");
}
次に、encryptedKeyContent を読み取る。
std::vector<uint8_t> keybytes(header.KeySize);
reader.ReadBytes(keybytes);
encryptedKeyContent の暗号化を解除する
wil::unique_bcrypt_key DecryptExportKey(BCRYPT_KEY_HANDLE key, std::span<uint8_t const> encryptedKey)
{
THROW_HR_IF(E_INVALIDARG, encryptedKey.size() != c_totalSizeInBytes);
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO AuthInfo{};
BCRYPT_INIT_AUTH_MODE_INFO(AuthInfo);
AuthInfo.pbNonce = const_cast<uint8_t*>(encryptedKey.data());
AuthInfo.cbNonce = c_nonceSizeInBytes;
AuthInfo.pbTag = const_cast<uint8_t*>(encryptedKey.data() + c_nonceSizeInBytes + c_childKeySizeInBytes);
AuthInfo.cbTag = c_tagSizeInBytes;
uint8_t decryptedKey[c_childKeySizeInBytes] = { 0 };
ULONG decryptedByteCount{};
THROW_IF_FAILED(HResultFromBCryptStatus(BCryptDecrypt(
key,
const_cast<uint8_t*>(encryptedKey.data() + c_nonceSizeInBytes),
c_childKeySizeInBytes,
&AuthInfo,
nullptr,
0,
decryptedKey,
sizeof(decryptedKey),
&decryptedByteCount,
0)));
wil::unique_bcrypt_key childKey;
THROW_IF_NTSTATUS_FAILED(
BCryptGenerateSymmetricKey(BCRYPT_AES_GCM_ALG_HANDLE, &childKey, nullptr, 0, decryptedKey, c_childKeySizeInBytes, 0));
return childKey;
}
exportKey の使用
wil::unique_bcrypt_key exportKey;
THROW_IF_NTSTATUS_FAILED(BCryptGenerateSymmetricKey(
BCRYPT_AES_GCM_ALG_HANDLE, &exportKey, nullptr, 0, exportKeyBytes.data(), static_cast<ULONG>(exportKeyBytes.size()), 0));
contentKey を取得するには (暗号化アルゴリズムはAES_GCM)
wil::unique_bcrypt_key contentKey = DecryptExportKey(exportKey.get(), keybytes);
encryptedContent を読み取る
std::vector<uint8_t> contentbytes(header.ContentSize);
reader.ReadBytes(contentbytes);
encryptedContent の暗号化を解除する
std::vector<uint8_t> DecryptPackedData(BCRYPT_KEY_HANDLE key, std::span<uint8_t const> payload)
{
THROW_HR_IF(E_INVALIDARG, payload.size() < c_tagSizeInBytes);
const auto dataSize = payload.size() - c_tagSizeInBytes;
const auto data = payload.data();
uint8_t zeroNonce[c_nonceSizeInBytes] = { 0 };
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo{};
BCRYPT_INIT_AUTH_MODE_INFO(authInfo);
authInfo.pbNonce = zeroNonce;
authInfo.cbNonce = c_nonceSizeInBytes;
authInfo.pbTag = const_cast<uint8_t*>(payload.data() + dataSize);
authInfo.cbTag = c_tagSizeInBytes;
std::vector<uint8_t> decryptedContent(dataSize);
ULONG decryptedSize = 0;
const auto result = BCryptDecrypt(
key, const_cast<uint8_t*>(data), static_cast<ULONG>(dataSize), &authInfo, nullptr, 0, decryptedContent.data(), static_cast<ULONG>(dataSize), &decryptedSize, 0);
decryptedContent.resize(decryptedSize);
THROW_IF_FAILED(HResultFromBCryptStatus(result));
return decryptedContent;
}
contentKey を使用する (暗号化アルゴリズムはAES_GCM)
std::vector<uint8_t> decryptedContent = DecryptPackedData(contentKey.get(), contentbytes);
暗号化解除された Recall スナップショットコンテンツを、対応する .json メタデータを持つ .jpg イメージの形式で指定されたフォルダー パスに出力します
void WriteSnapshotToOutputFolder(winrt::StorageFolder const& outputFolder, winrt::hstring const& fileName, winrt::IRandomAccessStream const& decryptedStream)
予想される出力には、次のものが含まれます。
- 復号化されたスナップショットは、.jpg ファイルとして保存されます。
- .json ファイルとして保存された対応するメタデータ。
どちらのファイルの種類も同じファイル名を共有し、指定された出力フォルダーにあります。
詳細情報 Recall
- Windows Recallの詳細を確認します。
- エクスポート コードを使用してスナップショット Recall エクスポートする
- IT 管理者向けのガイダンスとして、Recall の管理: Recall とスナップショット情報のエクスポートを許可する方法について、社内のユーザー向けの Recall 設定を管理する方法を説明します。スナップショットデータをエクスポートする機能を含みます。
- Windows AI の構成サービス プロバイダー (CSP) ポリシー: Recall を許可するエクスポート: スナップショット データのエクスポートを有効にするポリシーを含め、エンド ユーザーがデバイスでオプションの Recall 機能を有効にできるかどうかを決定するポリシー設定を確立するための IT 管理者向けのガイダンス。
Windows developer