Quickstart: Encrypt/Decrypt text using MIP SDK (C++)

This Quickstart shows you how to use more of the MIP Protection SDKs. Using one of the protection templates you listed in the previous Quickstart, you use a Protection handler to Encrypt ad hoc text. The Protection handler class exposes various operations for applying/removing protection.

Prerequisites

If you haven't already, be sure to complete the following prerequisites before continuing:

Implement an observer class to monitor the Protection handler object

Similar to the observer you implemented (for the Protection profile and engine) in the Application initialization Quickstart, now you implement an observer class for Protection handler objects.

Create a basic implementation for a Protection handler observer, by extending the SDK's mip::ProtectionHandler::Observer class. The observer is instantiated and used later, to monitor Protection handler operations.

  1. Open the Visual Studio solution you worked on in the previous "Quickstart: List protection templates (C++)" article.

  2. Add a new class to your project, which generates both the header/.h and implementation/.cpp files for you:

    • In the Solution Explorer, right-click the project node again, select Add, then select Class.
    • On the Add Class dialog:
      • In the Class Name field, enter "handler_observer". Notice that both the .h file and .cpp file fields are automatically populated, based on the name you enter.
      • When finished, click the OK button.
  3. After generating the .h and .cpp files for the class, both files are opened in Editor Group tabs. Now update each file to implement your new observer class:

    • Update "handler_observer.h", by selecting/deleting the generated handler_observer class. Don't remove the preprocessor directives generated by the previous step (#pragma, #include). Then copy/paste the following source into the file, after any existing preprocessor directives:

      #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;
           };
      
      
    • Update "handler_observer.cpp", by selecting/deleting the generated handler_observer class implementation. Don't remove the preprocessor directives generated by the previous step (#pragma, #include). Then copy/paste the following source into the file, after any existing preprocessor directives:

      #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. Optionally, use Ctrl+Shift+B (Build Solution) to run a test compile/link of your solution, to make sure it builds successfully before continuing.

Add logic to encrypt and decrypt ad hoc text

Add logic to encrypt and decrypt ad hoc text, using the Protection engine object.

  1. Using Solution Explorer, open the .cpp file in your project that contains the implementation of the main() method.

  2. Add the following #include and using directives, below the corresponding existing directives, at the top of the file:

      #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. Toward the end of the Main() body, where you left off in the previous Quickstart, insert the following code:

    //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. Toward the end of main() find the application shutdown block created in the first quickstart and add below lines to release handler resources:

     publishingHandler = nullptr;
     consumptionHandler = nullptr;
    
  5. Replace the placeholder values in the source code that you as follows, using string constants:

    Placeholder Value
    <sample-text> Sample text you would like to protect, for example: "cipher text".
    <Template-Id> Template Id which you would like to use to protect the text. For example: "bb7ed207-046a-4caf-9826-647cff56b990"

Build and test the application

Build and test your client application.

  1. Use Ctrl+Shift+B (Build Solution) to build your client application. If you have no build errors, use F5 (Start debugging) to run your application.

  2. If your project builds and runs successfully, the application prompts for an access token, each time the SDK calls your AcquireOAuth2Token() method. As you did previously in the "List protection templates" Quickstart, run your PowerShell script to acquire the token each time, using the values provided for $authority and $resourceUrl.

    *** 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 . . .