2

I am using Microsoft.AspNetCore.DataProtection.IDataProtector to protect and unprotect strings stored in a SQL Server database. The key ring is persisted in the same SQL Server database and they are protected using a Self-signed X509Certificate2.

This is how the data protection configuration looks like:

// Configuring database context
services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(
      Configuration.GetConnectionString("MySites")));

// Adding Data Protection and configure persistence with Entity Framework
      services.AddDataProtection()
      .SetApplicationName("MySites.v1")
      .PersistKeysToDbContext<ApplicationDbContext>()
      .ProtectKeysWithCertificate(new X509Certificate2("certificate.pfx", "*****", X509KeyStorageFlags.MachineKeySet));

And this is how I unprotect data:

_dataProtector = dataProtectionProvider.CreateProtector("MySites.v1");

_dataProtector.Unprotect(protectedString)

I understand this method is not recommended to protect/unprotect long persisted data, but I also understand that nothing prevents us from doing so. I also understand that the keys are eventually rotated and you can only use the active key for protecting data, but you can keep using expired keys to unprotect data.

The Certificate protecting the keys is about to expire, and I am not sure how this will affect the ability to keep protecting and unprotecting data. So, I tried creating an API to backup the data just in case, but when I ran the application in my computer (debugging) but connected to the deployed data base (where the keys are persisted), I get the following error:

Message: The payload was invalid

StackTrace: at Microsoft.AspNetCore.DataProtection.Cng.CbcAuthenticatedEncryptor.DecryptImpl(Byte* pbCiphertext, UInt32 cbCiphertext, Byte* pbAdditionalAuthenticatedData, UInt32 cbAdditionalAuthenticatedData) at Microsoft.AspNetCore.DataProtection.Cng.Internal.CngAuthenticatedEncryptorBase.Decrypt(ArraySegment1 ciphertext, ArraySegment1 additionalAuthenticatedData) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData) at Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector protector, String protectedData)\r\n at MySites.Controllers.SitesController.GetAll(Int32 siteCategoryId)

I also tried to use DangerousUnprotect but I got the same error

 IPersistedDataProtector persistedProtector = _dataProtector as IPersistedDataProtector;
 
 bool requiresMigration, wasRevoked;
 
 var unprotectedPayload = persistedProtector.DangerousUnprotect(
   protectedData: WebEncoders.Base64UrlDecode(site.PasswordHash),
   ignoreRevocationErrors: true,
   requiresMigration: out requiresMigration,
   wasRevoked: out wasRevoked);

 site.Password = WebEncoders.Base64UrlEncode(unprotectedPayload);

The deployed application works normally, and it is able to protect and unprotect data with no problem.

Serge
  • 31
  • 2
  • What changes did you make to get the error? Did you edit the certificate or just changed the time on the PC? – jdweng Mar 16 '22 at 14:16
  • @jdweng I have not changed anything yet. The certificate is not expired yet. The only difference I can think of, is that the app instance that is working is running on an Azure App Service and the other one I am running from my computer in debug mode. If I were persisting the key ring in file system, maybe that could be the issue since they are different machines, but the keys are persisted in the same database accessed by both instances. – Serge Mar 16 '22 at 16:12
  • It is not clear from posting what you changed to break the working code. Did you add CreateProtector and Unprotect? – jdweng Mar 16 '22 at 16:17
  • @jdweng I did not change anything. The first section of code is just to demonstrate how I am configuring data protection, and the second part is a failed attempt to make it work after I got the error. Since I don't remember changing anything, I suspect it could be either an environment (azure app service vs kestrel in local computer) related issue or an update on the Data Protection library itself. – Serge Mar 16 '22 at 17:56
  • Lets see if the issue is with the application(s) or the database. The database is a mdf file. So you can deattach the database from the server and then make a copy of the mdf file. The attach the database back to the server. This is better than archiving the database. Once you have a copy of the database you can attach to working server. i usually do the atttach/deattach using SSMS with the query command shown on following : https://www.mssqltips.com/sqlservertip/6222/sql-server-attach-and-detach-database-examples/?force_isolation=true – jdweng Mar 17 '22 at 09:49

0 Answers0