0

I am using IDataProtector to encrypt my data before storing into the database. All strings work fine for example:

LastName = _protector.Protect(student.LastName)

However I can't use Protect with:

 public DateTime EnrollmentDate { get; set; }

Using:

 Student nstudent = new Student
        {
            LastName = _protector.Protect(student.LastName),
            EnrollmentDate = _protector.Protect(student.EnrollmentDate)
        };

I get this error:

cannot convert from 'System.DateTime' to 'byte[]'
hncl
  • 2,295
  • 7
  • 63
  • 129
  • DataProtector is simple, it knows how to encrypt a byte[]. As a *convenience* there is an extension method that handles a string. But that's where it ends. It is up to you to convert a DateTime to byte[] if you want to take advantage of it. Like BitConverter.GetBytes(dt.ToBinary()) for example. Or to consider that there is no point in encrypting dates. – Hans Passant Oct 05 '17 at 07:20

2 Answers2

2

Probably you need to use strings instead

string sEnrollmentDate = _protector.Protect(student.EnrollmentDate.ToString())

note that the ToString would protect a localized text form of the date, so you'd better use some method that returns an ISO date string instead (see Given a DateTime object, how do I get an ISO 8601 date in string format?)

George Birbilis
  • 2,782
  • 2
  • 33
  • 35
  • Thank you, could not convert it to string. Update my question. – hncl Oct 05 '17 at 02:50
  • what do you mean when you say couldn't convert it? The idea is that you'd pass a ISO date string to the protector instead of a date and then keep what is returned by the protector into a string (not into a DateTime object). Then when decrypting you'd get back a string and convert it from the ISO date string format to a DateTime object – George Birbilis Oct 05 '17 at 02:55
  • Created an answer to explain why this isn't possible without using a different data type to store the protected value. – Martin Ullrich Oct 05 '17 at 07:02
  • Guess you mean a different datatype than DateTime. ISO dates as strings should be fine – George Birbilis Oct 12 '17 at 17:35
0

You cannot protect / unprotect to and from a fixed-length data type like DateTime. The extension method for strings creates a byte[] representation, encrypts it and then creates a base64 string representation of the protected value. This works because the protected and unprotected strings can be of different length. But DateTime is a struct with a fixed length, even if you use the backing long tick count, it only gives you 4 bytes. This requires you to use a different representation to store the protected value.

So you could have

byte[] protectedDateTime = protector.Protect(BitConverter.GetBytes(student.EnrollmentDate.Ticks));
DateTime unprotectedDateTime = new DateTime(ticks: BitConverter.ToInt64(protector.Unprotect(protectedDateTime), 0));
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Is Ticks a consistent value among .NET implementations on different platforms? If not, should use ISO date strings instead, unless your system is always protecting/unprotecting something on the same machine/architecture – George Birbilis Oct 12 '17 at 17:37
  • 1
    Yes it is a public API and contains the number 100-nanosecond intervals elapsed since midnight on January 1st in year 0001 represented as `long` (64 bit signed integer) – Martin Ullrich Oct 12 '17 at 17:42
  • Nice that they took care of that, since various operating systems have been using different "starting" dates internally and it would be a real mess when trying to move that value around if they hadn't – George Birbilis Oct 12 '17 at 18:44