Search code examples
delphiencryptiondelphi-73des

Encrypt a string in Delphi 7 using DCPCrypt (3DES)


I need to encrypt a string in Delphi 7. The only encryption library I managed to get running is DCPCrypt.

I studied an example that encrypted files, and tried to adapt it for strings, but I'm afraid I failed miserably...

This is my function:

function Encrypt3DES(psString, psKey: string): string;
var
    lCipher:TDCP_3des;
    CipherIV: array of byte;     // the initialisation vector (for chaining modes)
    lHash:TDCP_sha256;
    lHashDigest: 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
    i:integer;
begin
    lHash:=TDCP_sha256.Create(nil);
    SetLength(lHashDigest,lHash.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)

    //strmOutput.WriteBuffer(Salt,Sizeof(Salt));  // write out the salt so we can decrypt! ***I don't know what to do with this***

    lHash.Init;
    lHash.Update(Salt[0],Sizeof(Salt));   // hash the salt
    lHash.UpdateStr(psKey);  // and the passphrase
    lHash.Final(lHashDigest[0]);           // store the output in HashDigest

    lCipher:=TDCP_3des.Create(nil);
    //3DES is a block cipher, we need an initialisation vector

    SetLength(CipherIV,TDCP_blockcipher(lCipher).BlockSize div 8);
    for i := 0 to (Length(CipherIV) - 1) do
      CipherIV[i] := Random(256);           // again just random values for the IV

    //strmOutput.WriteBuffer(CipherIV[0],Length(CipherIV));  // write out the IV so we can decrypt! ***I don't know what to do with this***

    lCipher.Init(lHashDigest[0],TNeo.Min(lCipher.MaxKeySize,lHash.HashSize),CipherIV);  // initialise the cipher with the hash as key
    TDCP_blockcipher(lCipher).CipherMode := cmCBC;   // use CBC chaining when encrypting

    //lCipher.EncryptStream(strmInput,strmOutput,strmInput.Size); // encrypt the entire file
    result:=lCipher.EncryptString(psString);
    lCipher.Burn;   // important! get rid of keying information
    //strmInput.Free;
    //strmOutput.Free;
end;

Please, bear in mind that I am completely ignorant on how encryption works. I know you don't encrypt string, but binaries, but I don't know how to translate that to code. Every time I run it, I get a different result (I guess it's normal if you use random values), but I don't know if it should be like that, since I have to send this to another server so they can check the integrity there.

Thay gave me a Java function in the API, but obviously I can't use it:

public byte [] encrypt_3DES(final String claveHex, final String datos) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
    byte [] ciphertext = null;
    // Crea la clave
    DESedeKeySpec desKeySpec = new DESedeKeySpec(toByteArray(claveHex));
    SecretKey desKey = new SecretKeySpec(desKeySpec.getKey(), "DESede");
    // Crea un cifrador
    Cipher desCipher = Cipher.getInstance("DESede/CBC/NoPadding");

    // Inicializa el cifrador para encriptar
    desCipher.init(Cipher.ENCRYPT_MODE, desKey, new IvParameterSpec(IV));

    // Se añaden los 0 en bytes necesarios para que sea un múltiplo de 8
    int numeroCerosNecesarios = 8 - (datos.length() % 8);
    if (numeroCerosNecesarios == 8) {
        numeroCerosNecesarios = 0;
    }
    ByteArrayOutputStream array = new ByteArrayOutputStream();
    array.write(datos.getBytes("UTF-8"), 0, datos.length());
    for (int i = 0; i < numeroCerosNecesarios; i++) {
        array.write(0);
    }
    byte [] cleartext = array.toByteArray();
    // Encripta el texto
    ciphertext = desCipher.doFinal(cleartext);
    return ciphertext;
}

I any kind soul could give me a hand with this, I'd be really grateful. I've been banging my head against this for several days.

Thanks in advance.


Solution

  • This example uses the Open Source TLockBox library to encrypt/decrypt a string using 3DES https://sourceforge.net/p/tplockbox/wiki/Home/

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,
      //lockbox units 
      LbCipher, LbClass, LbAsym, LbRSA, LbString;
    
    type
      TForm1 = class(TForm)
        edPlainText: TEdit;
        edCipherText: TEdit;
        btnEncryptString: TButton;
        btnDescryptString: TButton;
        procedure btnEncryptStringClick(Sender: TObject);
        procedure btnDescryptStringClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    Function TripleDesEncrypt(const APlaintext, APassphrase: String): String;
    Var
      Key128: TKey128;
    begin
      GenerateLMDKey(Key128, SizeOf(Key128), APassphrase);
      result  := TripleDESEncryptStringEx(APlainText, Key128, True);
    End;
    
    Function TripleDesDecrypt(const ACipherText, APassphrase: String): String;
    Var
      Key128: TKey128;
    begin
      GenerateLMDKey(Key128, SizeOf(Key128), APassphrase);
      Try
        result := TripleDESEncryptStringEx(ACipherText, Key128, False);
      Except
        Result := '';
      End;
    End;
    
    procedure TForm1.btnEncryptStringClick(Sender: TObject);
    begin
      edCipherText.text := TripleDesEncrypt(edPlainText.Text, 'SecretPassphrase');
    end;
    
    procedure TForm1.btnDescryptStringClick(Sender: TObject);
    begin
      edPlainText.text := TripleDesDecrypt(edCipherText.text, 'SecretPassphrase');
    end;
    
    end.