i capture this 64-bit time format from a game and trying to understand it. I can not use a date delta because every now and then the value totally changes and even becomes negative as seen below.
v1:int64=-5990085973098618987; //2021-01-25 13:30:00
v2:int64=-5990085973321147595; //4 mins later
v3:int64=6140958949625363349; //7 mins later
v4:int64=6140958948894898101; //11 mins later
v5:int64=-174740204032730139; //16 mins later
v6:int64=-174740204054383467; //18 mins later
v7:int64=-6490439358095090795; //23 mins later
I tried to split the 64-bit into two 32-bit containers to get low and high part. still strange values. I also tried using pdouble(@value)^ to get float value of the 64-bit data, still strange values. So kind of running out of ideas, maybe some kind of bitfield data or something else going on.
hipart: -1394675573 | lopart: 1466441621 | hex: acdef08b|57681f95 | swap: -7701322112560996692
hipart: -1394675573 | lopart: 1243913013 | hex: acdef08b|4a249b35 | swap: 3862721007994330796
hipart: 1429803424 | lopart: -458425451 | hex: 553911a0|e4acfb95 | swap: -7639322244965910187
hipart: 1429803424 | lopart: -1188890699 | hex: 553911a0|b922f7b5 | swap: -5334757052947285675
hipart: -40684875 | lopart: -760849435 | hex: fd9332b5|d2a65be5 | swap: -1919757392230050819
hipart: -40684875 | lopart: -782502763 | hex: fd9332b5|d15bf495 | swap: -7641381711494605827
hipart: -1511173174 | lopart: -1467540587 | hex: a5ed53ca|a8871b95 | swap: -7702413578668347995
Any ideas welcomed, thanks in advance //mbs
--EDIT: So far, thanks to Martin Rosenau we are able to encode like this:
func mulproc_nfsw(i:int64;key:uint32):int64;
begin
if (blnk i) or (blnk key) then exit;
p:pointer=@i;
hi:uint32=uint32(p+4)^; //30864159 (hex: 01d6f31f)
lo:uint32=uint32(p)^; //748455936 (hex: 2c9c8800)
hi64:int64=hi*key; //0135b55a acdef08b <-- keep
lo64:int64=lo*key; //1d566e0b a65f2800 <-- keep
q:pointer=@result; //-5990085971773806592
uint32(q+4)^:=hi64; //acdef08b
uint32(q)^:=lo64; //a65f2800
end;
func encode_time_nfsw(j:juncture):int64;
begin
if blnk j then exit; //input: '2021-01-25 13:37:07'
key:uint32=$A85A2115; //encode key
ft:int64=j.filetime; //hex: 01d6f31f 2c9c8800
result:=mulproc_nfsw(ft,key);
end;
--EDIT2: Finally, thanks to fpiette we are able to decode also:
func decode_time_nfsw(i:int64):juncture;
begin
if blnk i then exit; //input: -5990085971773806592
key:uint32=$3069263D; //decode key
ft:int64=mulproc_nfsw(i,key);
result.setfiletime(ft);
end;
I checked my suspicion that the high and the low 32 bits are simply multiplied by A85A2115 (hex):
We get a FILETIME structure. Then we perform a 32x32->32 bit multiplication (this means we throw away the high 32 bits of the 64 bits result) of the high and the low word independently.
Example:
25 Jan 2021 13:37:07 (and some milliseconds)
Unencrypted FILETIME:
High dword = 1D6F31F (hex)
Low dword = 2C9CA481 (hex)
Multiplication
High dword: 1D6F31F * A85A2115 = 135B55AACDEF08B (hex)
Low dword: 2C9CA481 * A85A2115 = 1D5680CA57681F95 (hex)
Now only take the low 32 bits of the results:
High dword: ACDEF08B (hex)
Low dword: 57681F95 (hex)
Unfortunately, I don't know how to do the the "reverse operation"; I did it by searching for the result in a loop with the following pseudo-code:
encryptedValue = 57681F95 (hex)
originalValue = 0
product = 0
while product not equal to encryptedValue
// 32-bit addition discarding carry:
product = product + A85A2115 (hex)
originalValue = originalValue + 1
end_of_while_loop
We get the following results:
25 Jan 2021 13:37:07 => acdef08b|57681f95
25 Jan 2021 13:40:51 => acdef08b|4a249b35
25 Jan 2021 13:45:07 => 553911a0|e4acfb95
25 Jan 2021 13:49:03 => 553911a0|b922f7b5
25 Jan 2021 13:53:53 => fd9332b5|d2a65be5
25 Jan 2021 13:55:50 => fd9332b5|d15bf495
25 Jan 2021 14:00:39 => a5ed53ca|a8871b95
Addendum
The reverse operation seems to be done by multiplying with 3069263D (hex) (and only using the low 32 bits).
Encrypting:
2C9CA481 * A85A2115 = 1D5680CA57681F95
=> Result: 57681F95
Decrypting:
57681F95 * 3069263D = 10876CAF2C9CA481
=> Result: 2C9CA481