Browse Source

Cleanup password testing: use the encryption itself (by encrypting 0 and comparing results) to test the password instead of having something separate as before.

Encryption itself is unchanged by this commit except that the key is now derived from the password only once. So it still uses SHA-256 for this.

The next step is changing this to a proper KDF, by changing the implementation of GenerateEncryptionKey and the TSetupEncryptionKey type.
Martijn Laan 11 months ago
parent
commit
9a91001f91

+ 1 - 1
ISHelp/isetup.xml

@@ -5030,7 +5030,7 @@ DiskSliceSize=1457664
 <body>
 <body>
 <p>Specifies a password you want to prompt the user for at the beginning of the installation.</p>
 <p>Specifies a password you want to prompt the user for at the beginning of the installation.</p>
 <p>When using a password, you might consider setting <link topic="setup_encryption">Encryption</link> to <tt>yes</tt> as well, otherwise files will be stored as plain text and it would not be exceedingly difficult for someone to gain access to them through reverse engineering.</p>
 <p>When using a password, you might consider setting <link topic="setup_encryption">Encryption</link> to <tt>yes</tt> as well, otherwise files will be stored as plain text and it would not be exceedingly difficult for someone to gain access to them through reverse engineering.</p>
-<p>The password itself is not stored as clear text; it's stored as a SHA-256 hash, salted with a 64-bit random number. (Note: When encryption is enabled, this stored hash is <i>not</i> used for the encryption key.)</p>
+<p>The password itself is not stored as clear text.</p>
 </body>
 </body>
 </setuptopic>
 </setuptopic>
 
 

+ 5 - 8
Projects/Src/Compiler.CompressionHandler.pas

@@ -12,7 +12,7 @@ unit Compiler.CompressionHandler;
 interface
 interface
 
 
 uses
 uses
-  SHA256, ChaCha20, Shared.Int64Em, Shared.FileClass, Compression.Base,
+  SHA256, ChaCha20, Shared.Struct, Shared.Int64Em, Shared.FileClass, Compression.Base,
   Compiler.StringLists, Compiler.SetupCompiler;
   Compiler.StringLists, Compiler.SetupCompiler;
 
 
 type
 type
@@ -45,7 +45,7 @@ type
     procedure Finish;
     procedure Finish;
     procedure NewChunk(const ACompressorClass: TCustomCompressorClass;
     procedure NewChunk(const ACompressorClass: TCustomCompressorClass;
       const ACompressLevel: Integer; const ACompressorProps: TCompressorProps;
       const ACompressLevel: Integer; const ACompressorProps: TCompressorProps;
-      const AUseEncryption: Boolean; const ACryptKey: String);
+      const AUseEncryption: Boolean; const ACryptKey: TSetupEncryptionKey);
     procedure ProgressProc(BytesProcessed: Cardinal);
     procedure ProgressProc(BytesProcessed: Cardinal);
     function ReserveBytesOnSlice(const Bytes: Cardinal): Boolean;
     function ReserveBytesOnSlice(const Bytes: Cardinal): Boolean;
     procedure WriteProc(const Buf; BufSize: Longint);
     procedure WriteProc(const Buf; BufSize: Longint);
@@ -61,7 +61,7 @@ type
 implementation
 implementation
 
 
 uses
 uses
-  SysUtils, Shared.Struct, Compiler.Messages, Compiler.HelperFunc;
+  SysUtils, Compiler.Messages, Compiler.HelperFunc;
 
 
 constructor TCompressionHandler.Create(ACompiler: TSetupCompiler;
 constructor TCompressionHandler.Create(ACompiler: TSetupCompiler;
   const InitialSliceFilename: String);
   const InitialSliceFilename: String);
@@ -161,7 +161,7 @@ end;
 
 
 procedure TCompressionHandler.NewChunk(const ACompressorClass: TCustomCompressorClass;
 procedure TCompressionHandler.NewChunk(const ACompressorClass: TCustomCompressorClass;
   const ACompressLevel: Integer; const ACompressorProps: TCompressorProps;
   const ACompressLevel: Integer; const ACompressorProps: TCompressorProps;
-  const AUseEncryption: Boolean; const ACryptKey: String);
+  const AUseEncryption: Boolean; const ACryptKey: TSetupEncryptionKey);
 
 
   procedure SelectCompressor;
   procedure SelectCompressor;
   var
   var
@@ -190,15 +190,12 @@ procedure TCompressionHandler.NewChunk(const ACompressorClass: TCustomCompressor
 
 
   procedure InitEncryption;
   procedure InitEncryption;
   begin
   begin
-    { Create an SHA-256 hash of ACryptKey, and use that as the key }
-    var Key := SHA256Buf(Pointer(ACryptKey)^, Length(ACryptKey)*SizeOf(ACryptKey[1]));
-
     { Create a unique nonce from the base nonce }
     { Create a unique nonce from the base nonce }
     var Nonce := FCompiler.GetEncryptionBaseNonce;
     var Nonce := FCompiler.GetEncryptionBaseNonce;
     Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
     Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
     Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
     Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
 
 
-    XChaCha20Init(FCryptContext, Key[0], Length(Key), Nonce, SizeOf(Nonce), 0);
+    XChaCha20Init(FCryptContext, ACryptKey[0], Length(ACryptKey), Nonce, SizeOf(Nonce), 0);
   end;
   end;
 
 
 var
 var

+ 30 - 31
Projects/Src/Compiler.SetupCompiler.pas

@@ -19,7 +19,7 @@ interface
 
 
 uses
 uses
   Windows, SysUtils, Classes, Generics.Collections,
   Windows, SysUtils, Classes, Generics.Collections,
-  SimpleExpression, SHA256,
+  SimpleExpression, SHA256, ChaCha20,
   Shared.Struct, Shared.CompilerInt, Shared.PreprocInt, Shared.SetupMessageIDs,
   Shared.Struct, Shared.CompilerInt, Shared.PreprocInt, Shared.SetupMessageIDs,
   Shared.SetupSectionDirectives, Shared.VerInfoFunc, Shared.Int64Em, Shared.DebugStruct,
   Shared.SetupSectionDirectives, Shared.VerInfoFunc, Shared.Int64Em, Shared.DebugStruct,
   Compiler.ScriptCompiler, Compiler.StringLists, Compression.LZMACompressor;
   Compiler.ScriptCompiler, Compiler.StringLists, Compression.LZMACompressor;
@@ -111,7 +111,7 @@ type
     InternalCompressProps, CompressProps: TLZMACompressorProps;
     InternalCompressProps, CompressProps: TLZMACompressorProps;
     UseSolidCompression: Boolean;
     UseSolidCompression: Boolean;
     DontMergeDuplicateFiles: Boolean;
     DontMergeDuplicateFiles: Boolean;
-    CryptKey: String;
+    CryptKey: TSHA256Digest;
     TimeStampsInUTC: Boolean;
     TimeStampsInUTC: Boolean;
     TimeStampRounding: Integer;
     TimeStampRounding: Integer;
     TouchDateOption: (tdCurrent, tdNone, tdExplicit);
     TouchDateOption: (tdCurrent, tdNone, tdExplicit);
@@ -271,7 +271,7 @@ type
     function GetDebugInfo: TMemoryStream;
     function GetDebugInfo: TMemoryStream;
     function GetDiskSliceSize:Longint;
     function GetDiskSliceSize:Longint;
     function GetDiskSpanning: Boolean;
     function GetDiskSpanning: Boolean;
-    function GetEncryptionBaseNonce: TSetupNonce;
+    function GetEncryptionBaseNonce: TSetupEncryptionNonce;
     function GetExeFilename: String;
     function GetExeFilename: String;
     function GetLineFilename: String;
     function GetLineFilename: String;
     function GetLineNumber: Integer;
     function GetLineNumber: Integer;
@@ -597,7 +597,7 @@ begin
   Result := DiskSpanning;
   Result := DiskSpanning;
 end;
 end;
 
 
-function TSetupCompiler.GetEncryptionBaseNonce: TSetupNonce;
+function TSetupCompiler.GetEncryptionBaseNonce: TSetupEncryptionNonce;
 begin
 begin
   Result := SetupHeader.EncryptionBaseNonce;
   Result := SetupHeader.EncryptionBaseNonce;
 end;
 end;
@@ -2350,29 +2350,31 @@ var
     end;
     end;
   end;
   end;
 
 
-  procedure GeneratePasswordHashAndSalt(const Password: String;
-    var Hash: TSHA256Digest; var Salt: TSetupSalt);
-  var
-    Context: TSHA256Context;
-  begin
-    { Random salt is mixed into the password hash to make it more difficult
-      for someone to tell that two installations use the same password. A
-      fixed string is also mixed in "just in case" the system's RNG is
-      broken -- this hash must never be the same as the hash used for
-      encryption. }
-    GenerateRandomBytes(Salt, SizeOf(Salt));
-    SHA256Init(Context);
-    SHA256Update(Context, PAnsiChar('PasswordCheckHash')^, Length('PasswordCheckHash'));
-    SHA256Update(Context, Salt, SizeOf(Salt));
-    SHA256Update(Context, Pointer(Password)^, Length(Password)*SizeOf(Password[1]));
-    Hash := SHA256Final(Context);
-  end;
-
-  procedure GenerateEncryptionBaseNonce(var Nonce: TSetupNonce);
+  procedure GenerateEncryptionBaseNonce(var Nonce: TSetupEncryptionNonce);
   begin
   begin
     GenerateRandomBytes(Nonce, SizeOf(Nonce));
     GenerateRandomBytes(Nonce, SizeOf(Nonce));
   end;
   end;
 
 
+  procedure GenerateEncryptionKey(const Password: String; var Key: TSetupEncryptionKey);
+  begin
+    Key := SHA256Buf(Pointer(Password)^, Length(Password)*SizeOf(Password[1]))
+  end;
+
+  { This function assumes EncryptionKey is based on the password }
+  procedure GeneratePasswordTest(const EncryptionKey: TSetupEncryptionKey;
+    const EncryptionBaseNonce: TSetupEncryptionNonce; var PasswordTest: Integer);
+  begin
+    { Create a special nonce that cannot collide with encrypted-file nonces }
+    var Nonce := EncryptionBaseNonce;
+    Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor -1;
+
+    { Encrypt a value of 0 so Setup can do same and compare the results to test the password }
+    var Context: TChaCha20Context;
+    XChaCha20Init(Context, EncryptionKey[0], Length(EncryptionKey), Nonce, SizeOf(Nonce), 0);
+    PasswordTest := 0;
+    XChaCha20Crypt(Context, PasswordTest, PasswordTest, SizeOf(PasswordTest));
+  end;
+
   procedure StrToTouchDate(const S: String);
   procedure StrToTouchDate(const S: String);
   var
   var
     P: PChar;
     P: PChar;
@@ -2813,11 +2815,8 @@ begin
     ssEnableDirDoesntExistWarning: begin
     ssEnableDirDoesntExistWarning: begin
         SetSetupHeaderOption(shEnableDirDoesntExistWarning);
         SetSetupHeaderOption(shEnableDirDoesntExistWarning);
       end;
       end;
-    ssEncryption:
-      begin
+    ssEncryption: begin
         SetSetupHeaderOption(shEncryptionUsed);
         SetSetupHeaderOption(shEncryptionUsed);
-        if shEncryptionUsed in SetupHeader.Options then
-          GenerateEncryptionBaseNonce(SetupHeader.EncryptionBaseNonce);
       end;
       end;
     ssExtraDiskSpaceRequired: begin
     ssExtraDiskSpaceRequired: begin
         if not StrToInteger64(Value, SetupHeader.ExtraDiskSpaceRequired) then
         if not StrToInteger64(Value, SetupHeader.ExtraDiskSpaceRequired) then
@@ -2929,9 +2928,9 @@ begin
       end;
       end;
     ssPassword: begin
     ssPassword: begin
         if Value <> '' then begin
         if Value <> '' then begin
-          CryptKey := Value;
-          GeneratePasswordHashAndSalt(Value, SetupHeader.PasswordHash,
-            SetupHeader.PasswordSalt);
+          GenerateEncryptionBaseNonce(SetupHeader.EncryptionBaseNonce);
+          GenerateEncryptionKey(Value, CryptKey);
+          GeneratePasswordTest(CryptKey, SetupHeader.EncryptionBaseNonce, SetupHeader.PasswordTest);
           Include(SetupHeader.Options, shPassword);
           Include(SetupHeader.Options, shPassword);
         end;
         end;
       end;
       end;
@@ -7559,7 +7558,7 @@ begin
       else
       else
         VersionInfoProductTextVersion := VersionInfoProductVersionOriginalValue;
         VersionInfoProductTextVersion := VersionInfoProductVersionOriginalValue;
     end;
     end;
-    if (shEncryptionUsed in SetupHeader.Options) and (CryptKey = '') then begin
+    if (shEncryptionUsed in SetupHeader.Options) and not (shPassword in SetupHeader.Options) then begin
       LineNumber := SetupDirectiveLines[ssEncryption];
       LineNumber := SetupDirectiveLines[ssEncryption];
       AbortCompileFmt(SCompilerEntryMissing2, ['Setup', 'Password']);
       AbortCompileFmt(SCompilerEntryMissing2, ['Setup', 'Password']);
     end;
     end;

+ 12 - 7
Projects/Src/Setup.FileExtractor.pas

@@ -28,12 +28,14 @@ type
     FNeedReset: Boolean;
     FNeedReset: Boolean;
     FChunkCompressed, FChunkEncrypted: Boolean;
     FChunkCompressed, FChunkEncrypted: Boolean;
     FCryptContext: TChaCha20Context;
     FCryptContext: TChaCha20Context;
-    FCryptKey: String;
+    FCryptKey: TSetupEncryptionKey;
+    FCryptKeySet: Boolean;
     FEntered: Integer;
     FEntered: Integer;
     procedure DecompressBytes(var Buffer; Count: Cardinal);
     procedure DecompressBytes(var Buffer; Count: Cardinal);
     class function FindSliceFilename(const ASlice: Integer): String;
     class function FindSliceFilename(const ASlice: Integer): String;
     procedure OpenSlice(const ASlice: Integer);
     procedure OpenSlice(const ASlice: Integer);
     function ReadProc(var Buf; Count: Longint): Longint;
     function ReadProc(var Buf; Count: Longint): Longint;
+    procedure SetCryptKey(const Value: TSetupEncryptionKey);
   public
   public
     constructor Create(ADecompressorClass: TCustomDecompressorClass);
     constructor Create(ADecompressorClass: TCustomDecompressorClass);
     destructor Destroy; override;
     destructor Destroy; override;
@@ -41,7 +43,7 @@ type
       const ProgressProc: TExtractorProgressProc; const VerifyChecksum: Boolean);
       const ProgressProc: TExtractorProgressProc; const VerifyChecksum: Boolean);
     procedure SeekTo(const FL: TSetupFileLocationEntry;
     procedure SeekTo(const FL: TSetupFileLocationEntry;
       const ProgressProc: TExtractorProgressProc);
       const ProgressProc: TExtractorProgressProc);
-    property CryptKey: String write FCryptKey;
+    property CryptKey: TSetupEncryptionKey write SetCryptKey;
   end;
   end;
 
 
 function FileExtractor: TFileExtractor;
 function FileExtractor: TFileExtractor;
@@ -100,6 +102,12 @@ begin
   inherited;
   inherited;
 end;
 end;
 
 
+procedure TFileExtractor.SetCryptKey(const Value: TSetupEncryptionKey);
+begin
+  FCryptKey := Value;
+  FCryptKeySet := True;
+end;
+
 var
 var
   LastSourceDir: String;
   LastSourceDir: String;
 
 
@@ -190,15 +198,12 @@ procedure TFileExtractor.SeekTo(const FL: TSetupFileLocationEntry;
 
 
   procedure InitDecryption;
   procedure InitDecryption;
   begin
   begin
-    { Initialize the key, which is the SHA-256 hash of FCryptKey }
-    var Key := SHA256Buf(Pointer(FCryptKey)^, Length(FCryptKey)*SizeOf(FCryptKey[1]));
-
     { Recreate the unique nonce from the base nonce }
     { Recreate the unique nonce from the base nonce }
     var Nonce := SetupHeader.EncryptionBaseNonce;
     var Nonce := SetupHeader.EncryptionBaseNonce;
     Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
     Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
     Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
     Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
 
 
-    XChaCha20Init(FCryptContext, Key[0], Length(Key), Nonce, SizeOf(Nonce), 0);
+    XChaCha20Init(FCryptContext, FCryptKey[0], Length(FCryptKey), Nonce, SizeOf(Nonce), 0);
   end;
   end;
 
 
   procedure Discard(Count: Integer64);
   procedure Discard(Count: Integer64);
@@ -232,7 +237,7 @@ begin
     InternalError('Cannot call file extractor recursively');
     InternalError('Cannot call file extractor recursively');
   Inc(FEntered);
   Inc(FEntered);
   try
   try
-    if (foChunkEncrypted in FL.Flags) and (FCryptKey = '') then
+    if (foChunkEncrypted in FL.Flags) and not FCryptKeySet then
       InternalError('Cannot read an encrypted file before the key has been set');
       InternalError('Cannot read an encrypted file before the key has been set');
 
 
     { Is the file in a different chunk than the current one?
     { Is the file in a different chunk than the current one?

+ 24 - 14
Projects/Src/Setup.MainFunc.pas

@@ -227,7 +227,8 @@ function ShouldProcessIconEntry(const WizardComponents, WizardTasks: TStringList
   const WizardNoIcons: Boolean; const IconEntry: PSetupIconEntry): Boolean;
   const WizardNoIcons: Boolean; const IconEntry: PSetupIconEntry): Boolean;
 function ShouldProcessRunEntry(const WizardComponents, WizardTasks: TStringList;
 function ShouldProcessRunEntry(const WizardComponents, WizardTasks: TStringList;
   const RunEntry: PSetupRunEntry): Boolean;
   const RunEntry: PSetupRunEntry): Boolean;
-function TestPassword(const Password: String): Boolean;
+procedure GenerateEncryptionKey(const Password: String; var Key: TSetupEncryptionKey);
+function TestPassword(const EncryptionKey: TSetupEncryptionKey): Boolean;
 procedure UnloadSHFolderDLL;
 procedure UnloadSHFolderDLL;
 function WindowsVersionAtLeast(const AMajor, AMinor: Byte; const ABuild: Word = 0): Boolean;
 function WindowsVersionAtLeast(const AMajor, AMinor: Byte; const ABuild: Word = 0): Boolean;
 function IsWindows8: Boolean;
 function IsWindows8: Boolean;
@@ -237,7 +238,7 @@ function IsWindows11: Boolean;
 implementation
 implementation
 
 
 uses
 uses
-  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, SHA256,
+  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, SHA256, ChaCha20,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.Install, SetupLdrAndSetup.InstFunc,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.Install, SetupLdrAndSetup.InstFunc,
   Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
@@ -371,17 +372,24 @@ begin
   Result := -1;
   Result := -1;
 end;
 end;
 
 
-function TestPassword(const Password: String): Boolean;
-var
-  Context: TSHA256Context;
-  Hash: TSHA256Digest;
+procedure GenerateEncryptionKey(const Password: String; var Key: TSetupEncryptionKey);
+begin
+  Key := SHA256Buf(Pointer(Password)^, Length(Password)*SizeOf(Password[1]))
+end;
+
+{ This function assumes EncryptionKey is based on the password }
+function TestPassword(const EncryptionKey: TSetupEncryptionKey): Boolean;
 begin
 begin
-  SHA256Init(Context);
-  SHA256Update(Context, PAnsiChar('PasswordCheckHash')^, Length('PasswordCheckHash'));
-  SHA256Update(Context, SetupHeader.PasswordSalt, SizeOf(SetupHeader.PasswordSalt));
-  SHA256Update(Context, Pointer(Password)^, Length(Password)*SizeOf(Password[1]));
-  Hash := SHA256Final(Context);
-  Result := SHA256DigestsEqual(Hash, SetupHeader.PasswordHash);
+  { Do same as compiler did in GeneratePasswordTest and compare results }
+  var Nonce := SetupHeader.EncryptionBaseNonce;
+  Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor -1;
+
+  var Context: TChaCha20Context;
+  XChaCha20Init(Context, EncryptionKey[0], Length(EncryptionKey), Nonce, SizeOf(Nonce), 0);
+  var PasswordTest := 0;
+  XChaCha20Crypt(Context, PasswordTest, PasswordTest, SizeOf(PasswordTest));
+
+  Result := PasswordTest = SetupHeader.PasswordTest;
 end;
 end;
 
 
 class function TDummyClass.ExpandCheckOrInstallConstant(Sender: TSimpleExpression;
 class function TDummyClass.ExpandCheckOrInstallConstant(Sender: TSimpleExpression;
@@ -2691,15 +2699,17 @@ var
     if NeedPassword and (InitPassword <> '') then begin
     if NeedPassword and (InitPassword <> '') then begin
       PasswordOk := False;
       PasswordOk := False;
       S := InitPassword;
       S := InitPassword;
+      var CryptKey: TSetupEncryptionKey;
+      GenerateEncryptionKey(S, CryptKey);
       if shPassword in SetupHeader.Options then
       if shPassword in SetupHeader.Options then
-        PasswordOk := TestPassword(S);
+        PasswordOk := TestPassword(CryptKey);
       if not PasswordOk and (CodeRunner <> nil) then
       if not PasswordOk and (CodeRunner <> nil) then
         PasswordOk := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, PasswordOk);
         PasswordOk := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, PasswordOk);
 
 
       if PasswordOk then begin
       if PasswordOk then begin
         Result := False;
         Result := False;
         if shEncryptionUsed in SetupHeader.Options then
         if shEncryptionUsed in SetupHeader.Options then
-          FileExtractor.CryptKey := S;
+          FileExtractor.CryptKey := CryptKey;
       end;
       end;
     end;
     end;
   end;
   end;

+ 4 - 2
Projects/Src/Setup.WizardForm.pas

@@ -2286,15 +2286,17 @@ procedure TWizardForm.NextButtonClick(Sender: TObject);
   begin
   begin
     Result := False;
     Result := False;
     S := PasswordEdit.Text;
     S := PasswordEdit.Text;
+    var CryptKey: TSetupEncryptionKey;
+    GenerateEncryptionKey(S, CryptKey);
     if shPassword in SetupHeader.Options then
     if shPassword in SetupHeader.Options then
-      Result := TestPassword(S);
+      Result := TestPassword(CryptKey);
     if not Result and (CodeRunner <> nil) then
     if not Result and (CodeRunner <> nil) then
       Result := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, Result);
       Result := CodeRunner.RunBooleanFunctions('CheckPassword', [S], bcTrue, False, Result);
 
 
     if Result then begin
     if Result then begin
       NeedPassword := False;
       NeedPassword := False;
       if shEncryptionUsed in SetupHeader.Options then
       if shEncryptionUsed in SetupHeader.Options then
-        FileExtractor.CryptKey := S;
+        FileExtractor.CryptKey := CryptKey;
       PasswordEdit.Text := '';
       PasswordEdit.Text := '';
     end else begin
     end else begin
       { Delay for 750 ms when an incorrect password is entered to
       { Delay for 750 ms when an incorrect password is entered to

+ 4 - 5
Projects/Src/Shared.Struct.pas

@@ -68,8 +68,8 @@ type
     shWizardResizable, shUninstallLogging);
     shWizardResizable, shUninstallLogging);
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
-  TSetupSalt = array[0..7] of Byte;
-  TSetupNonce = record
+  TSetupEncryptionKey = TSHA256Digest;
+  TSetupEncryptionNonce = record
     RandomXorStartOffset: Int64;
     RandomXorStartOffset: Int64;
     RandomXorFirstSlice: Int32;
     RandomXorFirstSlice: Int32;
     RemainingRandom: array[0..2] of Int32;
     RemainingRandom: array[0..2] of Int32;
@@ -109,9 +109,8 @@ type
     WizardStyle: TSetupWizardStyle;
     WizardStyle: TSetupWizardStyle;
     WizardSizePercentX, WizardSizePercentY: Integer;
     WizardSizePercentX, WizardSizePercentY: Integer;
     WizardImageAlphaFormat: (afIgnored, afDefined, afPremultiplied); // Must be same as Graphics.TAlphaFormat
     WizardImageAlphaFormat: (afIgnored, afDefined, afPremultiplied); // Must be same as Graphics.TAlphaFormat
-    PasswordHash: TSHA256Digest;
-    PasswordSalt: TSetupSalt;
-    EncryptionBaseNonce: TSetupNonce;
+    PasswordTest: Integer;
+    EncryptionBaseNonce: TSetupEncryptionNonce;
     ExtraDiskSpaceRequired: Integer64;
     ExtraDiskSpaceRequired: Integer64;
     SlicesPerDisk: Integer;
     SlicesPerDisk: Integer;
     UninstallLogMode: (lmAppend, lmNew, lmOverwrite);
     UninstallLogMode: (lmAppend, lmNew, lmOverwrite);