Recent

Author Topic: How do you encrypt and decrypt any type of file using Dcpcrypt library?  (Read 4604 times)

Awesome Programmer

  • Sr. Member
  • ****
  • Posts: 451
  • Programming is FUN only when it works :)
    • Cool Technology
I keep reading on this forum and on Google that you can use Dcpcrypt to encrypt and decrypt datastream. Even examples only seems to deal with encrypting and decrypting strings. But I want to know how you can encrypt and decrypt a file using Dcpcrypt library? I need a simple example where it demonstrates how you use the Dcpcrypt library to encrypt and decrypt a file.

Thank you for your help.
« Last Edit: March 26, 2015, 08:10:29 pm by reltek »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
From a work application; loading:

Code: [Select]
var
    first : TBase64DecodingStream;
    ins :TStringStream;
    ind,outs : TMemoryStream;
    cipher : TDCP_rijndael;
    hash: TDCP_sha512;
    CipherIV: array of byte;     // the initialisation vector (for chaining modes)
    HashDigest: array of byte;   // the result of hashing the passphrase with the salt
    Salt: array[0..7] of byte;   // a random salt to help prevent precomputated attacks

  ins:=TStringstream.Create(s);  // input: a base64 encoded string
  first :=TBase64DecodingStream.Create(ins);  //first decode
  try
  ind:=TMemoryStream.create;  // stream for based64 decoded data
  try
  ind.CopyFrom(first,first.Size);
  ind.Seek(0,soFromBeginning);  // !!!!! ALWAYS MAKE SURE THAT INPUT STREAM
                                               // IS AT CORRECT POINT, MOST COMMON MISTAKE!
  outs:=TMemoryStream.Create;  // the memorystream containeing the output
  try

  Hash := TDCP_sha512.create(nil);
  try
  SetLength(HashDigest,Hash.HashSize div 8);
  ind.ReadBuffer(Salt[0],Sizeof(Salt));  // read the salt in from the file
  Hash.Init;
  Hash.Update(Salt[0],Sizeof(Salt));   // hash the salt
  Hash.UpdateStr(Passphrase);  // and the passphrase
  Hash.Final(HashDigest[0]);           // store the hash in HashDigest

  Cipher := TDCP_rijndael.Create(nil);
  try
  SetLength(CipherIV,TDCP_blockcipher(Cipher).BlockSize div 8);
  ind.ReadBuffer(CipherIV[0],Length(CipherIV));       // read the initialisation vector from the file
  Cipher.Init(HashDigest[0],Min(Cipher.MaxKeySize,Hash.HashSize),CipherIV);  // initialise the cipher
  TDCP_blockcipher(Cipher).CipherMode := cmCBC;

  Cipher.DecryptStream(ind,outs,ind.Size - ind.Position); // decrypt!
  Cipher.Burn;
  ins.Free;
  outs.Seek(0,soFromBeginning);
  r:=TMyReader.Create;
  try
  r.handle:=outs; // open(s);
  r.readinteger(mversie);
//  mversie:=$160011;
  r.setversionobject(self);
  laad(r);
  finally
    r.free;
  end;
  finally
    cipher.free;
  end;
  finally
    hash.free;
  end;
  finally
    outs.free;
  end;
  finally
    ind.free;
  end;
  finally
    first.free;
  end;

The writing:
Code: [Select]
var i,j : integer;
    w : TMyWriter;
    ins,outs: TMemoryStream;
    final : TStringStream;
    bstr : TBase64EncodingStream;
    cipher : TDCP_rijndael;
    hash: TDCP_sha512;
    CipherIV: array of byte;     // the initialisation vector (for chaining modes)
    HashDigest: array of byte;   // the result of hashing the passphrase with the salt
    Salt: array[0..7] of byte;   // a random salt to help prevent precomputated attacks

begin
 ins:=TMemoryStream.create;
 try
  // code here streams datastructure to "ins".
   ins.Seek(0,soFromBeginning);   // reset INS position.
   j:=ins.size;
   outs:=TmemoryStream.create;
   try
     Hash := TDCP_sha512.create(nil);
     try
     SetLength(HashDigest,Hash.HashSize div 8);
     for i := 0 to 7 do
       Salt[i] := Random(256);  // just fill the salt with random values (crypto secure PRNG would be better but not _really_ necessary)
     outs.WriteBuffer(Salt,Sizeof(Salt));  // write out the salt so we can decrypt!
     Hash.Init;
     Hash.Update(Salt[0],Sizeof(Salt));   // hash the salt
     Hash.UpdateStr(Passphrase);  // and the passphrase
     Hash.Final(HashDigest[0]);           // store the output in HashDigest

        cipher :=TDCP_rijndael.create(nil);
        try
       SetLength(CipherIV,TDCP_blockcipher(Cipher).BlockSize div 8);
      for i := 0 to (Length(CipherIV) - 1) do
        CipherIV[i] := Random(256);           // again just random values for the IV
      outs.WriteBuffer(CipherIV[0],Length(CipherIV));  // write out the IV so we can decrypt!
      Cipher.Init(HashDigest[0],Min(Cipher.MaxKeySize,Hash.HashSize),CipherIV);  // initialise the cipher with the hash as key
      TDCP_blockcipher(Cipher).CipherMode := cmCBC;   // use CBC chaining when encrypting

      Cipher.EncryptStream(ins,outs,ins.Size); // encrypt the entire file
      Cipher.Burn;   // important! get rid of keying information

      final:=TStringStream.create('');
      outs.Seek(0,soFromBeginning);
      bstr :=TBase64EncodingStream.Create(final); // we base64 result, because have to store in XML config file.
      try
      bstr.WriteBuffer(outs.memory^,outs.Size);
      finally
      bstr.Free;
      end;

      final.Seek(0,soFromBeginning);
      data :=final.DataString;

      final.Free;
      finally
       cipher.free;
       end;
      finally
        hash.free;
       end;
    finally
      outs.Free;
      end;
  finally
    ins.Free;
  end;
end;


The streams can be TFileStreams. These are seekable, so work the same. Only non seekable streams require (possibly) different approach.

Awesome Programmer

  • Sr. Member
  • ****
  • Posts: 451
  • Programming is FUN only when it works :)
    • Cool Technology
 :) Oh good... I have something to work from. Thank you so much Marcov.

 

TinyPortal © 2005-2018