Pascal Newsletter #17
The full source code examples of this issue are available for download.
![]() |
![]() |
Pascal Newsletter #17 - 20-FEB-2001 INDEX 1. A FEW WORDS FROM THE EDITOR 2. INTRODUCTION TO STRONG CRYPTO PROGRAMMING USING BORLAND DELPHI - Some words - Warranty - Definitions - The algorithm - The code 3. PROGRESS BAR WITHOUT A FRAME ________________________________________________________________________ 1. A FEW WORDS FROM THE EDITOR The JfControls Library Drawing ended with no winner, but JfActiveSoft is determined to give away one license anyway, so they decided to reduce the number of digits of the lottery to three, and if nobody hits the last three digits of the first prize of the National Lottery of Spain that will take place on Saturday, March 17, they will continue with the second prize, third, fourth, etc. until there is a winner. This time you'll have more time to register since the deadline is Thursday, March 15 at 20:00 GMT. Those who have registered to participate in the first drawing are automatically registered for the new drawing and as a courtesy will be given an extra number that will be notified by email. Participation is free. All you have to do is download and install the trial version of the library (available for Delphi and C++ Builder, both in versions 3, 4 and 5) to get the Key Number (a unique number that identifies each installation of the library) that you need in order to be able to fill in the registration form. If you don't want to install the trial version of the library, the latest version of JfSetup will give you a Key Number if you install only the demo (it's worth seing it and doesn't require the library to be installed for the executable to run). For more information about the drawing: http://www.latiumsoftware.com/jfcontrols/index.php?lang=en In this issue I'm glad to present an article of Uri Fridman about cryptography, and also another article from Vladimir S. showing us how to get a progress bar without a frame. I'd like to remember you that this newsletter can only keep going with your contributions. If you don't have time for writing or if you feel you're not good at it, but you have some useful or interesting code you want to share with other developers, please contact me and I possibly can do some writing for you. You have to be the author of the material you submit and only source code contributions are accepted... please don't send me compiled programs or units! Best regards, Ernesto De Spirito eds2004 @ latiumsoftware.com ________________________________________________________________________ JfControls Library. Multi-language. Multi-appearance. Skins. Privileges. More than 40 integrated and customizable components. Impressive GUI. Centralized resources administration. Multiple programming problems solved. For Delphi 3-7 and C++ Builder 3-6. http://www.jfactivesoft.com/ ________________________________________________________________________ 2. INTRODUCTION TO STRONG CRYPTO PROGRAMMING USING BORLAND DELPHI Copyright (c) 2001 Uri Fridman <urifrid@hushmail.com> Some words ========== Historically, cryptography was used by governments throughout the ages to conceal secret messages. The need to keep "state secrets" out of reach of the general public led to the invention of several encryption methods. In the 20th century these methods were taken one step beyond as they were automated by introducing machines such as the Enigma (broken by the allies in WWII). With the introduction of the computer, this automated process became even easier and yet newer cryptography methods were invented. Today computers are everywhere. Governments have access to almost everything. System Administrators have access to most of the files in your HD. Competition has access to stolen laptops... I mean, I don't want to sound "too" paranoid but in today's world, privacy is getting more and more difficult to achieve. But don't worry. We have Cryptography to help us. Warranty ======== NO WARRANTY. THIS ARTICLE COMES WITH NO WARRANTY, AND IS PROVIDED ON AN "AS IS" BASIS. YOU ASSUME THE ENTIRE COST OF ANY DAMAGE RESULTING FROM THE INFORMATION CONTAINED IN OR PRODUCED BY THE CONTENTS OF THIS ARTICLE. YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THIS ARTICLE TO ACHIEVE YOUR INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED FROM IT. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, URI, HIS SUPPLIERS AND OTHERS WHO MAY DISTRIBUTE THIS ARTICLE DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, CONFORMANCE WITH DESCRIPTION, AND NON-INFRINGEMENT, WITH RESPECT TO THIS SOFTWARE PRODUCT. IN OTHER WORDS: USE AT YOUR OWN RISK Definitions =========== In crypto terminology a plain readable file is called Plaintext. The process of scrambling its contents in order to make it unreadable is called Encryption, thus we are Encrypting the file. This unreadable message is now called Ciphertext. The opposite operation, unscrambling the ciphertext, is called Decryption, thus we Decrypt the file. These two processes use a Key to encrypt or decrypt the file. Only by knowing the correct key we should be able to decrypt a message encrypted with that key. Warning ======= These definitions are all good and nice but the real world is a little different. It might look easy and fun to create Ciphers (cryptographic algorithms) but it's not. Good crypto looks the same as bad crypto. Both output unreadable garbage. But don't be fooled. Always use public and well known ciphers, one that has been studied by professionals and has been analyzed over the years. Always try to get the source code for the ciphers. Go to the following link to learn how to differentiate a good product from a bad one: http://www.interhack.net/people/cmcurtin/snake-oil-faq.html I tried to be as accurate as possible when writing this article. However English is not my mother tongue and I'm not a professional cryptographer, so some mistakes can appear in the article. Please feel free to comment about them or other issues by sending an email to <urifrid@hushmail.com>. The algorithm ============= I chose Twofish as the algorithm for this introduction. I did it for several reasons: 1) It was written by Bruce Schneier (www.counterpane.com), a well known cryptographer and cryptanalyst 2) It hasn't been broken 3) It's easy to use 4) IT'S PUBLIC. The source code can be found in several places. 5) It can be used in any mode: ECB, CBC, CFB 8bit, OFB, OFB counter 8bit. To know more about modes read Applied Crytography by Bruce Schneier or go to his web site http://www.counterpane.com In short, Twofish is: - A 128 bit block cipher. Encrypts blocks of 128 bits in size - 128, 192 or 256 bits keys. Can use several lengths of keys. In general, if a cipher has 128 bits key it would take 2^128 tries to try each and every key. - Performs 16 rounds encryption. It iterates the cipher 16 times before returning ciphertext The code in Delphi for this algorithm was ported from the original C implementation by David Barton (<davebarton@bigfoot.com>). You can download several other ciphers from his web page: http://www.scramdisk.clara.net I'm providing all the files that this article uses. You will find them in the archive that accompanies this article. The code ======== Create a new project. Add 3 edit boxes (Edit1, Edit2 and Edit3). Add 4 buttons (encrypt, decrypt, hash and browse). Also add a radiogroup and call it RadioHex, insert two radiobuttons in there, one "Show in Hex" and the other "Show in Base64". We are going to add the following to the uses clause: uses SHA1, Twofish, Base64; * SHA1 is the Hash. One-way hash functions are like fingerprints of the data being hashed, it takes variable-length input and produces a fixed-length output (160 bits in SHA1). The hash function ensures that, if the information is changed in any way —even by just one bit— an entirely different output value is produced. This is useful in many ways. One of them for example is to encrypt a file and then make a hash of that encrypted file. You send both the file and the hash of it. When the other end gets the file he or she can check if the file was tampered with by creating a hash of the file and comparing it with the hash sent. Of course the hash has to be sent in a secure way to be sure that it is untouched (probably using some public key encryption algorithm like RSA). We are going to use hashes to create a fingerprint of both the password entered by the user and the encrypted file. * TWOFISH is the encryption algorithm. * Base64 is a way of coding output so it has only printable characters. Add the following procedures to your program: // produces a hash of a string procedure _HashString(s: string; var Digest: TSHA1Digest); var Context: TSHA1Context; // record to store intermediate // data begin SHA1Init(Context); // initialize the data record SHA1Update(Context,@S[1],Length(S)); // update the data record with // the string SHA1Final(Context,Digest); // produce the final hash end; // produces a hash of a file procedure _HashFile(filename: string; var Digest: TSHA1Digest); var Context: TSHA1Context; // record to store intermediate // data Source: file; // source file Buffer: array[1..8192] of byte; // read buffer Read: integer; // number of bytes read begin AssignFile(Source,filename); try Reset(Source,1); except MessageDlg('Unable to open source file.',mtInformation,[mbOK],0); Exit; end; SHA1Init(Context); // initialize the data structure repeat BlockRead(Source,Buffer,Sizeof(Buffer),Read); SHA1Update(Context,@Buffer,Read); // update the hash until Read<> Sizeof(Buffer); SHA1Final(Context,Digest); // produce the final hash CloseFile(Source); end; These procedures will produce the One-Way Hash for files and strings. Note that the encryption and decryption process will be like this: 1) get a hash of the password 2) initialize the key in the algorithm using the hash 3) make an IV (the first block to use in the chaining modes) 4) encrypt or decrypt 5) burn data (key in memory, IV, etc.) and sets the algorithm for the next task. 6) (Optional) get a hash of the encrypted file In (1) we generate the hash of the user's password. This hash will be used in (2) to initialize the key. This key is NOT the password the user typed. In (3) we generate the first block of encrypted data, this block contains random data. This is done because we are using one of the chaining modes and we need and each block depends on the previous one to be encrypted. This helps to hide patters in the text like redundancy and other file headers (like the "PK" in zipped files). In (4) we perform the actual encryption/decryption and in (5) we get rid of the data place in memory (we don't want any sniffer stealing our password, right?) So, in the OnClick Procedure for the button you called Encrypt you can write the following (Warning, this will OVERWRITE the original file. Unless you remember the password you won't be able to recover the data): var KeyData: TTwofishData; // the initialized key data Digest: TSHA1Digest; IV: array[0..15] of byte; // the initialization vector needed for // chaining modes Buffer: array[0..8191] of byte; Source,source2: file; i, j, n: integer; Key: string; NumRead, NumWritten: Integer; begin Key:= edit2.Text; // you wrote the password in edit2 _HashString(Key,Digest); TwofishInit(KeyData,@Digest,Sizeof(Digest),nil); // initialize the // key data using a hash of the key FillChar(IV,Sizeof(IV),0); // make the IV all zeros TwofishEncryptCBC(KeyData,@IV,@IV); // encrypt the IV to // get a 'random' IV Move(IV,KeyData.InitBlock,Sizeof(KeyData.InitBlock)); // move the // IV into the keydata so can use chaining TwofishReset(KeyData); // reset the keydata so it uses the new IV AssignFile(Source, edit1.Text); // file to encrypt in edit1 try Reset(Source,1); except TwofishBurn(KeyData); // get rid of the data in memory MessageDlg('File cannot be opened...', mtInformation, [mbOK], 0); Edit2.text:='00000000000000000000000000000000'; Edit2.text:=''; Exit; end; repeat n:= FilePos(Source); BlockRead(Source,Buffer,Sizeof(Buffer),i); for j:= 1 to (i div 16) do // 16 is the blocksize of Twofish // so process in 16 byte blocks TwofishEncryptCBC(KeyData,@Buffer[(j-1)*Sizeof(IV)], // encrypt! @Buffer[(j-1)*Sizeof(IV)]); if (i mod 16)<> 0 then // encrypt the last bytes that don't // fit in to a full block begin Move(KeyData.LastBlock,IV,Sizeof(IV)); TwofishEncryptCBC(KeyData,@IV,@IV); // encrypt the full block // again (so that it is encrypted twice) for j:= 1 to (i mod 16) do // xor this encrypted block with the short block Buffer[(i and not 15)+j]:= Buffer[(i and not 15)+j] xor IV[j]; end; Seek(Source,n); BlockWrite(Source,Buffer,i); // write out the buffer to the file until i<> Sizeof(Buffer); CloseFile(Source); TwofishBurn(KeyData); // get rid of data Edit2.text:='00000000000000000000000000000000'; Edit2.text:=''; Edit1.text:=''; MessageDlg('All done. File Encrypted with the same name as the ' + 'original.', mtInformation,[mbOK],0); end; Presto! We just encrypted the file in Edit1 with the password in Edit2! To decrypt do exactly the same, but instead of using TwofishEncryptCBC() use: TwofishDecryptCBC(KeyData,@Buffer[(j-1)*Sizeof(IV)], @Buffer[(j-1)*Sizeof(IV)]); Simple, huh? Ok, you have your encrypted file. Some nice touch will be to generate the hash of that encrypted file and send it along with it. To achieve this we will use the _HashFile procedure we wrote before. On the OnClick procedure for the button you named Hash add the following: procedure TForm1.HashClick(Sender: TObject); var Digest: TSHA1Digest; // binary form of the hash i: integer; begin if Edit1.Text='' then exit; // make sure we have a file to hash _HashFile(Edit1.Text,Digest); // calculate the hash // and store in Digest if radiohex.ItemIndex=0 then // we want to show the // hash in hexadecimal begin Edit3.Text:= '0x'; for i:= 0 to (Sizeof(Digest)-1) do Edit3.Text:= Edit3.Text+IntToHex(Digest[i],2); // convert Digest // to a hexadecimal string end else // in base64 begin Edit3.Text:= ''; for i:= 0 to (Sizeof(Digest)-1) do Edit3.Text:= Edit3.Text+chr(Digest[i]); // convert Digest to a // base64 Edit3.Text:=B64Encode(Edit3.Text); end; end; Now can choose to save the hash to a file and compress both the encrypted file and its hash in one single .zip archive. We can now send the zip file to a friend being sure that only him/her can decrypt it. This is a simple application. A lot can be added to make it more secure but this is just and example, it's up to you to add your own code and remember: "...may the source be with you." Source Code for SHA1, Twofish and Base64 along with a program using them can be found in the archive that accompanies this newsletter. Please be sure to read the warranty very carefully. Thanks. Uri, February 10, 2001. - urifrid@hushmail.com ----------------- NOTE: In case you are insterested, Uri has a freeware application that presents an explorer-like interface and allows to encrypt and decrypt files. There's also a console version available: http://www.geocities.com/urifrid/soft.html ________________________________________________________________________ 3. PROGRESS BAR WITHOUT A FRAME By Vladimir S. <shvetadvipa@mtu-net.ru> Delphi's ProgressBar always have a frame. If you wish to place it on a StatusBar it looks not beautifully. You can do small change in the component and you'll get the new one without a frame. Look the picture (progress.gif). You can see three ProgressBars. One is a standard Delphi's component with a frame and the rest of them a component with a new property. Now you can drive a ProgressBar's frame. unit NewProgress; // By Vladimir S. <shvetadvipa@mtu-net.ru> interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls; type TNProgressBar = class(TProgressBar) procedure WMNCPAINT(var Msg: TMessage); message WM_NCPAINT; private FShowFrame: boolean; procedure SetShowFrame(Value: boolean); public constructor Create(AOwner: TComponent); override; published property ShowFrame: boolean read FShowFrame write SetShowFrame; end; procedure Register; implementation { TNProgressBar } constructor TNProgressBar.Create(AOwner: TComponent); begin inherited; FShowFrame := True; end; procedure TNProgressBar.SetShowFrame(Value: boolean); begin if FShowFrame <> Value then begin FShowFrame:= Value; RecreateWnd; end; end; procedure TNProgressBar.WMNCPAINT(var Msg: TMessage); var DC: HDC; RC: TRect; begin if ShowFrame then begin inherited; Invalidate; end else begin DC := GetWindowDC(Handle); try Windows.GetClientRect(Handle, RC); with RC do begin Inc(Right, 2); Inc(Bottom, 2); end; Windows.FillRect(DC, RC, Brush.Handle); finally ReleaseDC(Handle, DC); end; end; end; procedure Register; begin RegisterComponents('Controls', [TNProgressBar]); end; end. ________________________________________________________________________ YOU CAN HELP US We need your help to keep this newsletter going and growing. You can help by referring the newsletter to your colleagues: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Or you can help by voting for us in some or all of these rankings to give more visibility to our web site and thus increase the number of subscriptions to this newsletter: http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://www.top219.org/cgi-bin/vote.cgi?delphi&83 http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80 It's just a few seconds for you that REALLY mean a lot to us. ________________________________________________________________________ If you haven't received the full source code examples for this issue, you can get them from http://www.latiumsoftware.com/download/p0017.zip ________________________________________________________________________ This newsletter is provided "AS IS" without warranty of any kind. Its use implies the acceptance of our licensing terms and disclaimer of warranty you can read at http://www.latiumsoftware.com/en/legal.php where you will also find a note about legal trademarks. Articles are copyright of their respective authors and they are reproduced here with their permission. You can redistribute this newsletter as long as you do it in full (including copyright notices), without changes, and gratis. ________________________________________________________________________ Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Group home page: http://groups.yahoo.com/group/pascal-newsletter/ Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com Problems with your subscription? eds2004 @ latiumsoftware.com ________________________________________________________________________ Latium Software http://www.latiumsoftware.com/en/index.php Copyright (c) 2001 by Ernesto De Spirito. All rights reserved. ________________________________________________________________________ |
The full source code examples of this issue are available for download.

progress.gif
![]() |
Errors? Omissions? Comments? Please contact us!






