2

I'm encrypting with an FPE algorithm in C#. What I did is convert the date I want to encrypt to the day of year value and a year value like so.

string input = "1901-01-01";
DateTimeOffset parsedDateOffset = new DateTimeOffset();
bool parsed = false;
parsed = DateTimeOffset.TryParseExact(input, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out parsedDateOffset);

if(parsed){

    DateTime dtNew = new DateTime(parsedDateOffset.Year, parsedDateOffset.Month, parsedDateOffset.Day);
    int dayOfYear = dtNew.DayOfYear;
    int yyyy = parsedDateOffset.Year;

// Then I encrypt the day of year separate from the year

    int encodedDay = FE11.Encrypt(365, dayOfYear, Encoding.UTF8.GetBytes(input.ToString()), Encoding.UTF8.GetBytes("0"));
    int encodedYear= FE11.Encrypt(2015 - 1901, yyyy, Encoding.UTF8.GetBytes(input.ToString()), Encoding.UTF8.GetBytes("0"));

// Then combine them together again taking into account leap year

     DateTime encodedDate = new DateTime((int)encodedYear, 1, 1).AddDays((int)encodedDay - 1);;
     if (DateTime.IsLeapYear((int)encodedYear))
     {
         encodedDate.AddDays(1);
     }   
}

However I'm encountering duplicate dates (i.e. for two plaintext dates result in the same encrypted date) But with format preserving encryption this should not be the case, and I know it is because of the way I am emcrypting the year separate from the day of year.

Does anyone have any suggestion to overcome this? I have tried introducing a tweak but the problem persists.

Ideally I would like to encrypt only one value. But encrypting the day of year alone still requires me to place it in the context of a year when presenting the final encrypted result.

Are there other date representation besides day of year that might be useful?

EDIT: The FPE library I am using at this time is called DotFPE located here https://dotfpe.codeplex.com/ (which is supposedly a port of the Format Preserving module of Botan Crypto)

erotavlas
  • 507
  • 3
  • 14

2 Answers2

7

So, in the comments, you state that

I'm using the original date as the key

This is the reason for the duplicate dates. The encryption is entirely deterministic for a fixed key. When you change the key, however, it is not. So it is entirely plausible that encrypting the number 215 with the key 215 could result in the same ciphertext as encrypting the number 10 with the key 10. But, encrypting the numbers 215 and 10 each with the same key, say 111, should be guaranteed to result in different ciphertexts (assuming you are not using the tweak, or using a fixed tweak).

If you had a fixed, random key, then you should get different ciphertexts. Adding in a random, per-message "tweak" can also cause this behavior.

So you can fix this "problem" by just using the same key everywhere and no tweak. This does, however, scare me. You are using deterministic encryption in an application that has a fairly small domain. Could make you vulnerable to frequency attacks, or other attacks, depending on the exact application.

mikeazo
  • 39,117
  • 9
  • 118
  • 183
3

One potential reason you might be running into duplicates is if you encrypt 'December 31' of a leap year; that makes it day 366, and that's out of range for your FPE method.

The obvious way to address this (and encrypt both days and years together) would be to convert the value into "days since January 1, 1901", encrypt that as a value between 0 and 42003 (the number of days between January 1, 1901 and December 31, 2015), and then convert that back into the standard format.

mikeazo
  • 39,117
  • 9
  • 118
  • 183
poncho
  • 154,064
  • 12
  • 239
  • 382