快速入门:使用 MIP SDK 加密/解密文本 (C++)

本快速入门介绍如何使用更多 MIP 保护 SDK。 使用在上一个快速入门中列出的保护模板之一,可以使用保护处理程序来加密临时文本。 保护处理程序类公开用于应用/删除保护的各种操作。

先决条件

如果尚未完成,请确保先完成以下先决条件,然后再继续:

  • 首先完成快速入门:列出保护模板 (C++),它会构建一个入门级 Visual Studio 解决方案,以列出经过身份验证的用户可用的保护模板。 此“加密/解密文本”快速入门建立在上一个快速入门的基础之上。
  • 可选:查看 MIP SDK 概念中的保护处理程序

实现观察程序类来监视保护处理程序对象

与在“应用程序初始化”快速入门中实现的观察程序(针对保护配置文件和引擎)类似,现在为保护处理程序对象实现观察程序类。

通过扩展 SDK 的 mip::ProtectionHandler::Observer 类,为保护处理程序观察程序创建基本实现。 观察程序被实例化并稍后使用,以监视保护处理程序操作。

  1. 打开在前文“快速入门:列表保护模板 (C++)”中使用的 Visual Studio 解决方案。

  2. 将新类添加到项目,这将会生成 header/.h 和 implementation/.cpp 文件:

    • 在“解决方案资源管理器”中,再次右键单击项目节点,选择“添加”,然后选择“类”
    • 在“添加类”对话框中:
      • 在“类名”字段中,输入“handler_observer”。 请注意,系统会根据输入的名称自动填充“.h 文件”和“.cpp 文件”字段。
      • 完成后,单击“确定”按钮。
  3. 为类生成 .h 文件和 .cpp 文件后,这两个文件都会在编辑器组选项卡中打开。 现在更新每个文件,实现新的观察程序类:

    • 通过选择/删除生成的 handler_observer 类来更新“handler_observer.h”。 不要删除上一步生成的预处理器指令(#pragma、#include)。 然后,将以下源复制/粘贴到文件中的任何现有预处理器指令之后:

      #include <memory>
      #include "mip/protection/protection_engine.h"
      using std::shared_ptr;
      using std::exception_ptr;
      
      class ProtectionHandlerObserver final : public mip::ProtectionHandler::Observer {
           public:
           ProtectionHandlerObserver() { }
           void OnCreateProtectionHandlerSuccess(const shared_ptr<mip::ProtectionHandler>& protectionHandler, const shared_ptr<void>& context) override;
           void OnCreateProtectionHandlerFailure(const exception_ptr& Failure, const shared_ptr<void>& context) override;
           };
      
      
    • 通过选择/删除生成的 handler_observer 类实现来更新“handler_observer.cpp”。 不要删除上一步生成的预处理器指令(#pragma、#include)。 然后,将以下源复制/粘贴到文件中的任何现有预处理器指令之后:

      #include "handler_observer.h"
      using std::shared_ptr;
      using std::promise;
      using std::exception_ptr;
      
      void ProtectionHandlerObserver::OnCreateProtectionHandlerSuccess(
           const shared_ptr<mip::ProtectionHandler>& protectionHandler,const shared_ptr<void>& context) {
                auto createProtectionHandlerPromise = static_cast<promise<shared_ptr<mip::ProtectionHandler>>*>(context.get());
                createProtectionHandlerPromise->set_value(protectionHandler);
                };
      
      void ProtectionHandlerObserver::OnCreateProtectionHandlerFailure(
           const exception_ptr& Failure, const shared_ptr<void>& context) {
                auto createProtectionHandlerPromise = static_cast<promise<shared_ptr<mip::ProtectionHandler>>*>(context.get())
                createProtectionHandlerPromise->set_exception(Failure);
                };
      
      
  4. 使用 Ctrl+Shift+B(生成解决方案)运行解决方案的测试编译/链接,以确保在继续之前成功完成生成。

添加逻辑以加密和解密临时文本

使用保护引擎对象添加逻辑以加密和解密临时文本。

  1. 使用“解决方案资源管理器”,打开项目中包含 main() 方法实现的 .cpp 文件。

  2. 在该文件顶部将以下 #include 和 using 指令添加到相应的现有指令之下:

      #include "mip/protection/protection_descriptor_builder.h"
      #include "mip/protection_descriptor.h"
      #include "handler_observer.h"
    
      using mip::ProtectionDescriptor;
      using mip::ProtectionDescriptorBuilder;
      using mip::ProtectionHandler;
    
  3. Main() 主体的末尾(你在上一个快速入门中离开的位置),插入以下代码:

    //Encrypt/Decrypt text:
    string templateId = "<Template-ID>";//Template ID from previous QuickStart e.g. "bb7ed207-046a-4caf-9826-647cff56b990"
    string inputText = "<Sample-Text>";//Sample Text
    
    //Refer to ProtectionDescriptor docs for details on creating the descriptor
    auto descriptorBuilder = mip::ProtectionDescriptorBuilder::CreateFromTemplate(templateId);
    const std::shared_ptr<mip::ProtectionDescriptor>& descriptor = descriptorBuilder->Build();
    
    //Create Publishing settings using a descriptor
    mip::ProtectionHandler::PublishingSettings publishingSettings = mip::ProtectionHandler::PublishingSettings(descriptor);
    
    //Create a publishing protection handler using Protection Descriptor
    auto handlerObserver = std::make_shared<ProtectionHandlerObserver>();
    engine->CreateProtectionHandlerForPublishingAsync(publishingSettings, handlerObserver, pHandlerPromise);
    auto publishingHandler = pHandlerFuture.get();
    
    std::vector<uint8_t> inputBuffer(inputText.begin(), inputText.end());
    
    //Show action plan
    cout << "Applying Template ID " + templateId + " to: " << endl << inputText << endl;
    
    //Encrypt buffer using Publishing Handler
    std::vector<uint8_t> encryptedBuffer;
    encryptedBuffer.resize(static_cast<size_t>(publishingHandler->GetProtectedContentLength(inputText.size(), true)));
    
    publishingHandler->EncryptBuffer(0,
                          &inputBuffer[0],
                          static_cast<int64_t>(inputBuffer.size()),
                          &encryptedBuffer[0],
                          static_cast<int64_t>(encryptedBuffer.size()),
                          true);
    
    std::string encryptedText(encryptedBuffer.begin(), encryptedBuffer.end());
    cout << "Encrypted Text :" + encryptedText;
    
    //Show action plan
    cout << endl << "Decrypting string: " << endl << endl;
    
    //Generate publishing licence, so it can be used later to decrypt text.
    auto serializedPublishingLicense = publishingHandler->GetSerializedPublishingLicense();
    
    //Use same PL to decrypt the encryptedText.
    auto cHandlerPromise = std::make_shared<std::promise<std::shared_ptr<ProtectionHandler>>>();
    auto cHandlerFuture = cHandlerPromise->get_future();
    shared_ptr<ProtectionHandlerObserver> cHandlerObserver = std::make_shared<ProtectionHandlerObserver>();
    
    //Create consumption settings using serialised publishing licence.
    mip::ProtectionHandler::ConsumptionSettings consumptionSettings = mip::ProtectionHandler::ConsumptionSettings(serializedPublishingLicense);
    engine->CreateProtectionHandlerForConsumptionAsync(consumptionSettings, cHandlerObserver, cHandlerPromise);
    
    auto consumptionHandler = cHandlerFuture.get();
    
    //Use consumption handler to decrypt the text.
    std::vector<uint8_t> decryptedBuffer(static_cast<size_t>(encryptedText.size()));
    
    int64_t decryptedSize = consumptionHandler->DecryptBuffer(
         0,
         &encryptedBuffer[0],
         static_cast<int64_t>(encryptedBuffer.size()),
         &decryptedBuffer[0],
         static_cast<int64_t>(decryptedBuffer.size()),
         true);
    
    decryptedBuffer.resize(static_cast<size_t>(decryptedSize));
    
    std::string decryptedText(decryptedBuffer.begin(), decryptedBuffer.end());
    
    // Output decrypted content. Should match original input text.
    cout << "Decrypted Text :" + decryptedText << endl;
    
    
  4. main() 的末尾,找到在第一个快速入门中创建的应用程序关闭块,并添加以下行以释放处理程序资源:

     publishingHandler = nullptr;
     consumptionHandler = nullptr;
    
  5. 使用字符串常量替换源代码中的占位符值,如下所示:

    占位符
    <sample-text> 要保护的示例文本,例如:"cipher text"
    <Template-Id> 要用于保护文本的模板 ID。 例如:"bb7ed207-046a-4caf-9826-647cff56b990"

生成并测试应用

生成和测试客户端应用程序。

  1. 使用 Ctrl+Shift+B(生成解决方案)生成客户端应用程序。 如果没有生成错误,请使用 F5(启动调试)运行应用程序。

  2. 如果项目成功生成并运行,则应用程序在 SDK 每次调用 AcquireOAuth2Token() 方法时都会提示输入访问令牌。 正如之前在“列出保护模板”快速入门中所做的那样,每次都使用为 $authority 和 $resourceUrl 提供的值运行 PowerShell 脚本以获取令牌。

    *** Template List:
    Name: Confidential \ All Employees : a74f5027-f3e3-4c55-abcd-74c2ee41b607
    Name: Highly Confidential \ All Employees : bb7ed207-046a-4caf-9826-647cff56b990
    Name: Confidential : 174bc02a-6e22-4cf2-9309-cb3d47142b05
    Name: Contoso Employees Only : 667466bf-a01b-4b0a-8bbf-a79a3d96f720
    Applying Template ID bb7ed207-046a-4caf-9826-647cff56b990 to:
    <Sample-Text>
    Encrypted Text :y¬╩$Ops7Γ╢╖¢t
    Decrypting string:
    
    Run the PowerShell script to generate an access token using the following values, then copy/paste it below:
    Set $authority to: https://login.windows.net/common/oauth2/authorize
    Set $resourceUrl to: https://aadrm.com
    Sign in with user account: user1@tenant.onmicrosoft.com
    Enter access token: <paste-access-token-here>
    Press any key to continue . . .
    
    Run the PowerShell script to generate an access token using the following values, then copy/paste it below:
    Set $authority to: https://login.windows.net/94f69844-8d34-4794-bde4-3ac89ad2b664/oauth2/authorize
    Set $resourceUrl to: https://aadrm.com
    Sign in with user account: user1@tenant.onmicrosoft.com
    Enter access token: <paste-access-token-here>
    Press any key to continue . . .
    
    Decrypted Text :<Sample-Text>
    C:\MIP Sample Apps\ProtectionQS\Debug\ProtectionQS.exe (process 8252) exited with code 0.
    To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
    Press any key to close this window . . .