I have data that's being encrypted by .NET Framework 4.5.1 code using FormsAuthentication.Encrypt, and I need to be able to decrypt it in code using dotnet core 3.1.
Based on this documentation, I believe I should be able to make this work by using Microsoft.AspNetCore.DataProtection.SystemWeb on the .NET Framework side, and configuring data protection identically on the dotnet core side. However, I get the following error instead:
CryptographicException: The payload was invalid.
On the .NET Framework side, I configure data protection as documented:
public class DataProtector : DataProtectionStartup
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("myapp")
.PersistKeysToFileSystem(new System.IO.DirectoryInfo("C:\\PathToKeys\\"));
}
}
The encrypted value is the direct output of FormsAuthentication.Encrypt(ticket);. I've confirmed that it uses the new mechanism: It persists keys to the file system, and the resulting cipher text leads with the expected 09F0C9F0 header, and the dotnet core code both recognizes it and is able to recognize that it has a relevant key. However, it fails to actually Unprotect.
The dotnet core code uses that as the value of "ciphertext" in the following code:
static void Main(string[] args)
{
var provider = DataProtectionProvider.Create(new DirectoryInfo("/pathToKeys"));
var protector = provider.CreateProtector("myapp");//("FormsAuthentication.Ticket");
byte[] b = HexToBinary(ciphertext);
protector.Unprotect(b); // Error thrown here
}
Based on my reading of the relevant code, I've attempted using a few alternate purposes such as "FormsAuthentication.Ticket" but without any luck. Is there a step I'm missing here, or a purpose I need to specify that I don't know about?
Adding the HexToBinary code as suggested. This is lifted directly from Microsoft.
public static byte[] HexToBinary(string data)
{
if (data == null || data.Length % 2 != 0)
{
// input string length is not evenly divisible by 2
return null;
}
byte[] binary = new byte[data.Length / 2];
for (int i = 0; i < binary.Length; i++)
{
int highNibble = HexToInt(data[2 * i]);
int lowNibble = HexToInt(data[2 * i + 1]);
if (highNibble == -1 || lowNibble == -1)
{
return null; // bad hex data
}
binary[i] = (byte)((highNibble << 4) | lowNibble);
}
return binary;
}
public static int HexToInt(char h)
{
return (h >= '0' && h <= '9') ? h - '0' :
(h >= 'a' && h <= 'f') ? h - 'a' + 10 :
(h >= 'A' && h <= 'F') ? h - 'A' + 10 :
-1;
}