'Why this DataProtectionProvider Error Occurs

I am testing the config data protection using DataProtectionProvider class. The test code works in one way, but failed in another way.

TEST ENVIRONMENT:

App type: ASP.NET 6 console app with c# Package: Microsoft.AspNetCore.DataProtection.Extensions 6.0.3 IDE: VS 2022 Test Project: ProtectData

PROBLEM DESCRIPTION:

In DataProtector class has 3 methods (see test code #1).

  1. The TestProtector method is for initial testing. It encrypt and decrypt data in the same method. It works without any problem

  2. In methods EncryptData and DecryptData handle the process in 2 separate steps. When running tests with these methods, the exception occurs in the DecryptData method on the statement: decrypted = protector.Unprotect(encryptedData); The exception info is shown in following screen shot. enter image description here

  3. The tests were run using the program.main method (see test code $2)

QUESTION:

When comparing the code in "TestProtector" method with code in these 2 method, they all handle the process in the same way with same key. Why does one method works perfectly and the "two-step" always fail? It really puzzles me. I'll appreciate any help or suggestions for troubleshooting.

TEST CODE

---- test code #1 (console app using DataProtectionProvider)

using Microsoft.AspNetCore.DataProtection;
using System;

namespace ProtectData
{
    public static class DataProtector
    {
        public static string EncryptData(string inputText)
        {
            string encrypted = string.Empty;
            try
            {
                var dataProtectionProvider = DataProtectionProvider.Create($".\appconfig.txt");

                var protector = dataProtectionProvider.CreateProtector("protect data");

                //var protectedPayload = protector.Protect(inputText);
                encrypted = protector.Protect(inputText);

            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
            }

            return encrypted;
        }

        public static string DecryptData(string encryptedData)
        {
            string decrypted = string.Empty;

            try
            {
                var dataProtectionProvider = DataProtectionProvider.Create($".\appconfig.txt");
                var protector = dataProtectionProvider.CreateProtector("protect conn string");
                decrypted = protector.Unprotect(encryptedData);
            }
            catch(Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message, ex);
            }

            return decrypted;
        }

        public static void TestProtector()
        {
            string inputText = "DataSource=localhost, database=testdb, userID=appuser, password=topsecret";
            Console.WriteLine($"inputText:\n{inputText}\n");

            string encrypted = string.Empty;
            string decrypted = string.Empty;

            try
            {
                // encrypt given string
                var dataProtectionProvider = DataProtectionProvider.Create($".\appconfig.txt");

                var protector = dataProtectionProvider.CreateProtector("protect data");

                //generate protected payload for input text
                encrypted = protector.Protect(inputText);
                Console.WriteLine($"protectedPayload:\n{encrypted}\n");

                //decrypt protected data
                decrypted = protector.Unprotect(encrypted);
                Console.WriteLine($"UnprotectPayload:\n{decrypted}\n");

                //show verification result
                Console.WriteLine($"Verify result:\n{(inputText == decrypted ? true : false)}");
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error:", ex);
            }
        }
    }
}

---- Test code #2 (program main)

namespace ProtectData
{
    public class Program
    {
        static void Main()
        {
            string testType = "two_step";
            RunTest(testType);

            Console.WriteLine();
            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }

        static void RunTest(string testType)
        {
            switch ( testType.ToLower())
            {
                case "simple":
                    DataProtector.TestProtector();
                    break;

                case "two_step":
                    string inputData = "DataSource=localhost, database=testdb, userID=appuser, password=topsecret";
                    Console.WriteLine($"inputData:\n{inputData}\n");

                    string protectedData = DataProtector.EncryptData(inputData);
                    Console.WriteLine($"protectedData:\n{protectedData}\n");

                    string outputData = DataProtector.DecryptData(protectedData);
                    Console.WriteLine($"outputData:\n{outputData}\n");

                    bool verify = inputData == outputData;
                    Console.WriteLine($"verified: {verify}");
                    break;
            }
        }
    }
}



Solution 1:[1]

I was able to fix the problem using examples provided in following online doc:

https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/non-di-scenarios?view=aspnetcore-6.0

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bedrock