TurboMagic 92 Posted yesterday at 05:35 PM Hello, in order to decide how to properly fix this issue in DEC (Delphi Encryption Compendium) I would like to look up the exact original definition of the KDF algorithms for the case of an empty key/password being given as argument. Unfortunately that is in some IEEE paper/standard, which is behind a paywal. Is there anybody having access to IEEE P1363? Here's the DEC issue: https://github.com/MHumm/DelphiEncryptionCompendium/issues/76 Cheers TurboMagic Share this post Link to post
DelphiUdIT 200 Posted 21 hours ago I don't have any pubblication about that, but this site use and have an implementation about this standard, may be can help: https://github.com/miracl/MIRACL/tree/master/source/p1363 Share this post Link to post
Kas Ob. 124 Posted 9 hours ago Hi, I looked at the implementation at https://github.com/MHumm/DelphiEncryptionCompendium/blob/master/Source/DECHashAuthentication.pas#L997-L1049 and lets say this one https://github.com/MHumm/DelphiEncryptionCompendium/blob/master/Source/DECHashAuthentication.pas#L1067-L1074 class function TDECHashAuthentication.KDF1(const Data, Seed: TBytes; MaskSize: Integer): TBytes; begin if (length(Seed) > 0) then Result := KDFInternal(Data[0], length(Data), Seed[0], length(Seed), MaskSize, ktKDF1) else Result := KDFInternal(Data[0], length(Data), NullStr, 0, MaskSize, ktKDF1); end; The problem is easy to see and and easy to fix here, but lets point the cause Data is TBytes, in other words managed type and if Data is empty then Data is nil, and that is it, accessing Data from class function TDECHashAuthentication.KDFInternal(const Data; DataSize: Integer; const Seed; SeedSize, MaskSize: Integer; KDFType: TKDFType): TBytes; var I, n, Rounds, DigestBytes : Integer; Count : UInt32; HashInstance : TDECHashAuthentication; begin SetLength(Result, 0); DigestBytes := DigestSize; Assert(MaskSize >= 0); Assert(DataSize >= 0); Assert(SeedSize >= 0); Assert(DigestBytes >= 0); HashInstance := TDECHashAuthenticationClass(self).Create; try Rounds := (MaskSize + DigestBytes - 1) div DigestBytes; SetLength(Result, Rounds * DigestBytes); if (KDFType = ktKDF2) then n := 1 else n := 0; for I := 0 to Rounds-1 do begin Count := SwapUInt32(n); HashInstance.Init; if (KDFType = ktKDF3) then begin HashInstance.Calc(Count, SizeOf(Count)); HashInstance.Calc(Data, DataSize); // <-------- here Data can't be nil end else begin HashInstance.Calc(Data, DataSize); HashInstance.Calc(Count, SizeOf(Count)); // <-------- here Data can't be nil end; HashInstance.Calc(Seed, SeedSize); HashInstance.Done; Move(HashInstance.Digest[0], Result[(I) * DigestBytes], DigestBytes); Also as designed, i mean KDFx it does hash the concatenation of Data with the seed, if data is nil then just skip it, and that is the fix. As for your request the specification, then check your private messages, as i attached IEEE 1363-2000 and an old draft of ISO/IEC 18033-2. Share this post Link to post
Kas Ob. 124 Posted 9 hours ago On side note KDF(x) are key driving functions, but these functions are old and mainly used for specific purposes, which generating a key from a key or sufficient and accepted entropy, they never meant to be used for passwords and for that they had the seed added, they should have have been designed better to focus on this issue, not like PBKDF which is Password Based Key Deriving Function, which designed to be get a key from low entropy sources like password and it compensate with arbitrary rounds of HMAC. Share this post Link to post