Difference between revisions of "CryptINI"

From Free Pascal wiki
Jump to navigationJump to search
(Unformatted content)
(Part-formatted)
Line 1: Line 1:
 
==CryptINI==
 
==CryptINI==
PURPOSE
+
===PURPOSE===
=======
+
 
 
This is a TiniFile implementation that is resistant to tampering.
 
This is a TiniFile implementation that is resistant to tampering.
 
In normal (PlainTextMode = FALSE) mode, any calls to Write values are
 
In normal (PlainTextMode = FALSE) mode, any calls to Write values are
Line 17: Line 17:
 
It is paired with ReadInteger and VerifyInteger
 
It is paired with ReadInteger and VerifyInteger
  
DISCLAIMER
+
===DISCLAIMER===
==========
+
 
 
This unit does not claim to pass any security tests nor be used in
 
This unit does not claim to pass any security tests nor be used in
 
any environment where a moderate-level hacker could circumvent it.
 
any environment where a moderate-level hacker could circumvent it.
  
ENCRYPTION
+
===ENCRYPTION===
==========
+
 
 
By Default CryptINI uses the DCPCrypt package for string encryption.
 
By Default CryptINI uses the DCPCrypt package for string encryption.
 
The mode is IDEA cipher with an MD5 hash for the key. The EncryptINI
 
The mode is IDEA cipher with an MD5 hash for the key. The EncryptINI
Line 34: Line 34:
 
You can then delete any requirement for dcpcrypt in the project inspector.
 
You can then delete any requirement for dcpcrypt in the project inspector.
  
FREEPASCAL VERSIONS
+
===FREEPASCAL VERSIONS===
===================
+
 
 
Starting in FPC V3.0 there are additional options in TINIFile which
 
Starting in FPC V3.0 there are additional options in TINIFile which
 
are implemented in TCryptINI if the FPC Version >= 3 is detected.
 
are implemented in TCryptINI if the FPC Version >= 3 is detected.
  
USE AND EXAMPLE CODE
+
===USE AND EXAMPLE CODE===
====================
+
 
** You can hard-code an Ident Section in your INI file
+
* You can hard-code an Ident Section in your INI file
** and check if it has been altered
+
* and check if it has been altered
** Typical Form.Create()
+
* Typical Form.Create()
 +
<syntaxhighlight>
 
procedure TForm1.FormCreate(Sender: TObject);
 
procedure TForm1.FormCreate(Sender: TObject);
 
const
 
const
Line 79: Line 80:
 
   ...other code
 
   ...other code
 
end;
 
end;
 +
</syntaxhighlight>
  
 
+
* Has the Ident been tampered with?  Put this in Form.Create
** Has the Ident been tampered with?  Put this in Form.Create
+
<syntaxhighlight>
 
// Use the MD5 value from the INI file (use your own!)
 
// Use the MD5 value from the INI file (use your own!)
 
If INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then
 
If INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then
Line 87: Line 89:
 
else
 
else
 
   ShowMessage('Ident failed verification'); // Warning message/exit
 
   ShowMessage('Ident failed verification'); // Warning message/exit
 
+
</syntaxhighlight>
 
** Test for first run
 
** Test for first run
 +
<syntaxhighlight>
 
If INI.IsVirgin then // note that doing the test Deflowers the app by default
 
If INI.IsVirgin then // note that doing the test Deflowers the app by default
 
   ShowMessage('First time run of this app');
 
   ShowMessage('First time run of this app');
 +
</syntaxhighlight>
  
** Toggle to normal UnEncrypted INI use
+
* Toggle to normal UnEncrypted INI use
 
(by default it is set to FALSE)
 
(by default it is set to FALSE)
 +
<syntaxhighlight>
 
INI.PlainTextMode:=TRUE;
 
INI.PlainTextMode:=TRUE;
 
INI.WriteString('MySection', 'String', 'MyString'); // just writes normally
 
INI.WriteString('MySection', 'String', 'MyString'); // just writes normally
 +
</syntaxhighlight>
  
** When PlainTextMode = FALSE (default),Write<anytype> encrypts the value
+
* When PlainTextMode = FALSE (default),Write<anytype> encrypts the value
 
   and prefixes the encrypted value with an MD5Hash
 
   and prefixes the encrypted value with an MD5Hash
INI.WriteInteger('MySection', 'Integer',1000);
+
<syntaxhighlight>INI.WriteInteger('MySection', 'Integer',1000);</syntaxhighlight>
** Note WriteInteger adds a '+' (INTEGER_MARKER) to the written Key
+
 
 +
* Note WriteInteger adds a '+' (INTEGER_MARKER) to the written Key
 
   This is so that CryptINI can deal with Integers specially
 
   This is so that CryptINI can deal with Integers specially
 
   Using CryptINI in either mode, this is invisible in use
 
   Using CryptINI in either mode, this is invisible in use
 
   (i.e. don't add a + to the ident for any methods)
 
   (i.e. don't add a + to the ident for any methods)
  
** When PlainTextMode = FALSE (default), use these convenient methods if you like:
+
* When PlainTextMode = FALSE (default), use these convenient methods if you like:
 +
<syntaxhighlight>
 
INI.ReadUnencryptedString
 
INI.ReadUnencryptedString
 
INI.WriteUnencryptedString
 
INI.WriteUnencryptedString
 
INI.ReadUnEncryptedInteger
 
INI.ReadUnEncryptedInteger
 
INI.WriteUnencryptedInteger
 
INI.WriteUnencryptedInteger
 +
</syntaxhighlight>
  
** Store 'First Run' status using these methods:
+
* Store 'First Run' status using these methods:
 +
<syntaxhighlight>
 
INI.IsVirgin
 
INI.IsVirgin
 
INI.Deflower
 
INI.Deflower
 
INI.ReFlower (useful for testing)
 
INI.ReFlower (useful for testing)
 
+
</syntaxhighlight>
** You can encrypt and decrypt the entire INI file usine EncryptINI and DecryptINI
+
* You can encrypt and decrypt the entire INI file usine EncryptINI and DecryptINI
 
   This uses a different cipher and hash method, so is extra-secure
 
   This uses a different cipher and hash method, so is extra-secure
 
   cryptINI methods and properties an only work with an unencrypted INI file
 
   cryptINI methods and properties an only work with an unencrypted INI file
Line 124: Line 134:
 
   file extension to use for the encrypted file.
 
   file extension to use for the encrypted file.
  
** Original IniFiles methods and properties
+
* Original IniFiles methods and properties
 
   Just use them as normal. Note: you can mix-and-match Plaintext and Encrypted
 
   Just use them as normal. Note: you can mix-and-match Plaintext and Encrypted
 
   in the same INI file. Just toggle the property PlainTextMode before Writing/Reading
 
   in the same INI file. Just toggle the property PlainTextMode before Writing/Reading
 +
 +
===Testing App/Demo===
 +
 +
* This can be downloaded from https://sourceforge.net/projects/lazautoupdate/files/otherpackages/testcryptini_compiled.zip
 +
* There are compiled versions for Windows 32/64-bit and Linux 32/64-bit in the archive
 +
 +
==Download==
 +
* In progress...

Revision as of 19:38, 21 November 2016

CryptINI

PURPOSE

This is a TiniFile implementation that is resistant to tampering. In normal (PlainTextMode = FALSE) mode, any calls to Write values are accompanied by an embedded MD5 hash value (and also reversed then Base64/IDEA Encrypted) This is invisible in normal use (i.e. read methods return normal results) but there are added methods to internally verify any entries. It also is able to write a standard ident section containing various details including authorship and copyright. A single function allows you to check on app startup whether this section has been altered. It also includes a useful 'First Run' functionality. It's intended purpose is to store information that cannot be easily altered in a text editor (such as HiScores etc) by a weekend scripter. The WriteInteger method is the most secure as it double-encrypts as well as embedding an MD5Hash value as a checksum. Very handy to save scores etc. It is paired with ReadInteger and VerifyInteger

DISCLAIMER

This unit does not claim to pass any security tests nor be used in any environment where a moderate-level hacker could circumvent it.

ENCRYPTION

By Default CryptINI uses the DCPCrypt package for string encryption. The mode is IDEA cipher with an MD5 hash for the key. The EncryptINI and DecryptINI methods use DCPCrypt RC4 Cipher (With SHA hash) There is a $DEFINE USE_DCPCRYPT directive at the top of this file.

If this DEFINE is commented out, then CryptINI will default to BASE64 string encryption, which is weaker. Encrypt/DecryptINI methods will be unavailable. You can then delete any requirement for dcpcrypt in the project inspector.

FREEPASCAL VERSIONS

Starting in FPC V3.0 there are additional options in TINIFile which are implemented in TCryptINI if the FPC Version >= 3 is detected.

USE AND EXAMPLE CODE

  • You can hard-code an Ident Section in your INI file
  • and check if it has been altered
  • Typical Form.Create()
procedure TForm1.FormCreate(Sender: TObject);
const
  C_KEYPHRASE = 'I do like to be beside the seaside'; // Move this to the top of the unit
Begin
 ...other code
 // Initialise the encrypted config file
 INI := TCryptIniFile.Create(ChangeFileExt(Application.EXEName, '.cfg'));

 // First ever run.  INI is absent
 If INI.IsVirgin then INI.WriteIdent('minesadorada','(c)2016','minesadorada@charcodelvalle.com','Creative Commons',TRUE);l

 if NOT INI.VerifyIdent('5b319674f5cb55f3ed1e404e33c25868') then // I got this from the INI file
   ShowMessage('This is not a genuine copy of ' + Application.Title + '!')
 else INI.Deflower; // If not Deflowered then the default ini is used.

 // After first run, use the encrypted version
 If NOT INI.IsVirgin then
 begin
   INI.DecryptINI(TRUE,C_KEYPHRASE);
 // Check the unencrypted version..
   if NOT INI.VerifyIdent('5b319674f5cb55f3ed1e404e33c25868') then // I got this from the INI file
   ShowMessage('This is not a genuine copy of ' + Application.Title + '!');
 end;
 INI.KeyPhrase:=C_KEYPHRASE; // for subsequent read/writes
 ...other code
end;

procedure Tmainform.FormDestroy(Sender: TObject);
const
  C_KEYPHRASE = 'I do like to be beside the seaside'; // Move this to the top of the unit
Begin
 ...other code
  INI.EncryptINI(TRUE,C_KEYPHRASE);
  ...other code
end;
  • Has the Ident been tampered with? Put this in Form.Create
// Use the MD5 value from the INI file (use your own!)
If INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then
  ShowMessage('Ident verified OK') // do nothing
else
  ShowMessage('Ident failed verification'); // Warning message/exit
    • Test for first run
If INI.IsVirgin then // note that doing the test Deflowers the app by default
   ShowMessage('First time run of this app');
  • Toggle to normal UnEncrypted INI use

(by default it is set to FALSE)

INI.PlainTextMode:=TRUE;
INI.WriteString('MySection', 'String', 'MyString'); // just writes normally
  • When PlainTextMode = FALSE (default),Write<anytype> encrypts the value
  and prefixes the encrypted value with an MD5Hash
INI.WriteInteger('MySection', 'Integer',1000);
  • Note WriteInteger adds a '+' (INTEGER_MARKER) to the written Key
  This is so that CryptINI can deal with Integers specially
  Using CryptINI in either mode, this is invisible in use
  (i.e. don't add a + to the ident for any methods)
  • When PlainTextMode = FALSE (default), use these convenient methods if you like:
INI.ReadUnencryptedString
INI.WriteUnencryptedString
INI.ReadUnEncryptedInteger
INI.WriteUnencryptedInteger
  • Store 'First Run' status using these methods:
INI.IsVirgin
INI.Deflower
INI.ReFlower (useful for testing)
  • You can encrypt and decrypt the entire INI file usine EncryptINI and DecryptINI
  This uses a different cipher and hash method, so is extra-secure
  cryptINI methods and properties an only work with an unencrypted INI file
  So; Decrypt on startup, and Encrypt before exit.
  By default the routines use the KeyPhrase property, but you can override this
  in the method call along with whether to delete the "old" file and what
  file extension to use for the encrypted file.
  • Original IniFiles methods and properties
  Just use them as normal. Note: you can mix-and-match Plaintext and Encrypted
  in the same INI file. Just toggle the property PlainTextMode before Writing/Reading

Testing App/Demo

Download

  • In progress...