1

I have a IV (initialization vector) and key, also a cryptogram. I need do decrypt the cryptogram. From the internet i found DCPcrypt Cryptographic Component Library v2. So, now i've reached to coding.

procedure TForm1.Button1Click(Sender: TObject);
var
key:Ansistring;
ivector,indata,outdata:string;
begin
  key := 'abc12345679';  //<--key for decrypting
  dcp_rijndael1.InitStr(key,TDCP_sha1);  //I don't understand why i need hashing!?

  ivector := edit2.Text;  //initialization vector
  dcp_rijndael1.SetIV(ivector);
  dcp_rijndael1.BlockSize := Length(ivector); //'This variable should be the same size as the block size' says the documentation

  indata := edit1.Text;  //getting the cryptogram

  dcp_rijndael1.CipherMode := cmCBC;

  dcp_rijndael1.DecryptCBC(indata,outdata,Length(indata));
  label3.Caption := outdata;                                    //output to label
end;

This code gives me an error. "Local Variables" window shows indata, outdata, ivector, key variables as 'Inaccessible value'. Or maybe is there another way to do it. This seems pretty straight forward, though. Thanks in advance.

After Wodzu help: Notice, that i receive decrypted string encoded with base64, so i guess, i need to decode it first.

var
  Form1: TForm1;
  StringToEncrypt, StringToDecrypt, DecryptedString: string;
  vector:string;

procedure TForm1.Button2Click(Sender: TObject);
begin
  vector := '1234567812345678';        //Length 16
  stringtodecrypt := '2YOXZ20Z7B3TRI/Ut8iH/GpEZWboE2tnnWU';
  stringtodecrypt := Decode64(stringtodecrypt);  //after encrypted string is sent over internet, it is encoded with base64, so i need to decode it.
  SetLength(DecryptedString, 36);  //36 is the length of the output
  DCP_rijndael1.Init('MyKey:128bit', 128, @Vector[1]);
  DCP_rijndael1.SetIV(Vector);
  DCP_rijndael1.BlockSize := Length(Vector); //Should this be also 128
  DCP_rijndael1.DecryptCBC(StringToDecrypt[1], DecryptedString[1], Length(StringToDecrypt)*2);  //Here i get hieroglyph as a result. Why is length multiplied with 2?
  decryptedstring := Encode64(decryptedstring);  //Here i get less hieroglyph, but would like to get correct decrypted string. I doubt the necessity of encoding

  ShowMessage(DecryptedString);

end;

I can't make this code to decrypt data that somebody else is encrypting (with PHP) (after encrypting the data is encoded with base64). Note! encrypted text length is not the same as the decrypted text length!

Peacelyk
  • 1,126
  • 4
  • 24
  • 48
  • 3
    And the **exact** error message is? – jachguate Nov 20 '10 at 19:54
  • I do not see constructor for the dcp_rijndael1 anywhere in your code, this might be the problem. To see local variables you need to turn off the compiler optimization. – Wodzu Nov 20 '10 at 20:57
  • this error is not associated with the decryption. After calling DecryptCBC method 'indata', 'outdata' and other variables become 'inaccessible value', so when i try to set label's caption using one of inaccessible variables i get error. I guess i'm doing something wrong, so assigning data to labels is a minor problem. – Peacelyk Nov 20 '10 at 21:09
  • Simplifying actual behavior, one can say debugger shows "inaccessible value" label for variables the linker has determined are not used after the execution point. But if you use them in your code afterwards, the debugger will show you the value for that variables. So if you want to see that value in debug-time, just include some code which _uses_ the value (for example a ShowMessage or assigning it as a value to a public property or global variable. – jachguate Nov 22 '10 at 20:17

4 Answers4

1

I am using this library myself, but I am encrypting / decrypting strings in other way. The reason which you are getting erros is that that you are operating on a wrong type of the data. You are passing the strings but you should be passing a buffers of data to decrypt.

In this line of code:

dcp_rijndael1.DecryptCBC(indata,outdata,Length(indata));

This method, is not expecting the strings. Change your code like this:

procedure TForm1.Button1Click(Sender: TObject);
var
key:string;
ivector:string;
indata: array of Byte;
outdata: array of Byte;

begin
  key := 'abc12345679';  
  dcp_rijndael1.InitStr(key,TDCP_sha1);  

  ivector := edit2.Text;  
  dcp_rijndael1.SetIV(ivector);
  dcp_rijndael1.BlockSize := Length(ivector); 

 // indata := edit1.Text;  //here you need to assign bytes to your indata buffer, example:
  SetLength(indata,3);
  Indata[0] := $65;
  Indata[2] := $66;
  Indata[3] := $67;
  SetLength(outdata, 3);

  dcp_rijndael1.CipherMode := cmCBC;

  dcp_rijndael1.DecryptCBC(indata[0],outdata[0],Length(indata));
//  label3.Caption := outdata; //this will not show you anything I guess
end;

After edit:

Example for WideStrings:

unit Unit14;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DCPcrypt2, DCPsha1, DCPblockciphers, DCPrijndael, StdCtrls;

type
  TForm14 = class(TForm)
    btnEncrypt: TButton;
    DCP_rijndael1: TDCP_rijndael;
    DCP_sha11: TDCP_sha1;
    btnDecrypt: TButton;
    procedure btnEncryptClick(Sender: TObject);
    procedure btnDecryptClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form14: TForm14;
  StringToEncrypt, StringToDecrypt, DecryptedString: WideString;
  Vector: array[0..3] of Byte;
implementation

{$R *.dfm}

procedure TForm14.btnEncryptClick(Sender: TObject);

begin
  SetLength(StringToDecrypt, 16);
  StringToEncrypt := 'Encrypt me babe!';
  DCP_rijndael1.Init('1234', 32, @Vector[0]);
  DCP_rijndael1.SetIV(Vector);
  DCP_rijndael1.BlockSize := 4;
  DCP_rijndael1.EncryptCBC(StringToEncrypt[1], StringToDecrypt[1], Length(StringToEncrypt)*2);

end;

procedure TForm14.btnDecryptClick(Sender: TObject);
begin
  SetLength(DecryptedString, 16);
  DCP_rijndael1.Init('1234', 32, @Vector[0]);
  DCP_rijndael1.SetIV(Vector);
  DCP_rijndael1.BlockSize := 4;
  DCP_rijndael1.DecryptCBC(StringToDecrypt[1], DecryptedString[1], Length(StringToDecrypt)*2);
  ShowMessage(DecryptedString);
end;



procedure TForm14.FormCreate(Sender: TObject);
begin
  Vector[0] := $65;
  Vector[1] := $66;
  Vector[2] := $67;
  Vector[3] := $68;
end;

end.

Hope this helps.

Wodzu
  • 6,932
  • 10
  • 65
  • 105
  • Yes, but how can i get human readable format from it? The outdata has the same length as indata, but the encrypted data might not be that long. – Peacelyk Nov 21 '10 at 15:49
  • 1
    If you assume that one character is encoded with one byte, than the conversion is pretty straightforward. You might try as @MikeT suggested to use an AnsiString as an outdata, or you may convertet the bytes to characters manualy: YourString[1] := Char(outdata[0]) and so one. I do not understand the second part of your comment. Isn't the indata = encrypted data? – Wodzu Nov 21 '10 at 18:54
  • the encrypted string is 64 characters long, but the decrypted string 36 characters long. if i convert decrypted hex numbers (which i get 64 of them) to char i get a real mishmash out of it. What do i need to do if the character was encoded with 2 bytes? – Peacelyk Nov 22 '10 at 08:07
  • I've included a complete solution for you with an example of WideStrings. – Wodzu Nov 22 '10 at 09:13
  • Thank you for your code Wodzu. I tried it and it works fine when i encrypt it and then decrypt it. But when i try to decrypt data that has not been encrypted by this code then i get as weird string as encrypted one. i need the encrypted be something like 'PJ7z38g2xAAwFhDUFUBB5QfzPJcr2D5anNY6/1nArDWTVavcPiokTawquV+1gE8I' what string type i need to use to get that? What is the second parameter in DCP_rijndael1.Init() function? And although encrypted is ~64 char long, decrypted is ~35. – Peacelyk Nov 22 '10 at 18:00
  • It is impossile to say why you get weird output if I don't know how you are encrypting the input data. If you show the code in which you are encrypting your data then I might be able to help. – Wodzu Nov 23 '10 at 10:22
0

Are you having some issues with the demo they provided:

Also, did you try other libraries that might clear things up:

Community
  • 1
  • 1
icyrock.com
  • 27,952
  • 4
  • 66
  • 85
  • First, i don't understand why is hash needed to decrypt data? I have iv,key and cryptogram. Shouldn't i use these as some kind of parameters to decrypt? Second, the crypto method has to be CBC. Thanks – Peacelyk Nov 20 '10 at 21:04
  • I am not that familiar with AES. I did use it a few times a few years ago and I remember there are algorithm constraints that you mention (like requiring IV to be of a certain length, etc.). If you really want to know why you need to do this or that or wondering why the algorithm or this specific implementation does some initializations (hashing, as you call it), then you would have to read a bit more on the subject. From the user perspective - I edited the post with two more posts describing the libraries for Delphi which might help clearing things up. – icyrock.com Nov 20 '10 at 21:21
0

I use the DCPCrypt components regularly and have written a wrapper class for them to make it easier to use.

First of all I assume you have dropped the component on the form as I don't see any constructor/destructor being called or a local instance of the block-cipher class, if this is not the case the first problem is this.

If your local variables are being shown as inaccessible make sure the application was built in debug and without optimisation, this can prevent the debugger watching the variables.

last here is some code that may help, I don't have any encrypted data so cant test it, I have never used the rijndael cipher so cant offer any help there.

procedure Decrypt(const AKey: AnsiString; const AVector: array of Byte;
  const AInData: array of Byte; var AOutData: array of Byte);
var
  Cipher : TDCP_rijndael;
begin
  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.Init(AKey, Length(AKey)*8, @AVector[0]);
    Cipher.CipherMode := cmCBC;
    Cipher.DecryptCBC(AInData[0], AOutData[0], Length(AInData));
  finally
    Cipher.Burn;
    Cipher.Free;
  end;
end;

IN this code the vector is a dynamic array and should have its length set and populated with the data before calling the procedure, also the key is a string containing the either a hash digest or a simple key depending on how the data was encrypted.

as to why a hash is needed I believe it is to increase security so that it is difficult for hackers to decrypt that data.

Mike Taylor
  • 2,376
  • 2
  • 17
  • 33
  • @Mike have you tested it under Delphi 2009 or higher? I am not sure but it might not work for the unicode strings. – Wodzu Nov 20 '10 at 23:45
  • very good point best using array of byte or AnsiString for the AInData and AOutDATA. I'm still using Delphi 2007. – Mike Taylor Nov 21 '10 at 01:07
  • Mike, i tried your code Decrypt('4tkF4tGN1KSiwc4E',Vector,toDecrypt^,DecryptedData); Types: toDecrypt - pointer to byte of array, DecryptedData - empty byte of array, Vector - byte of array. However, i get error: EAccessViolation... – Peacelyk Nov 25 '10 at 20:05
  • vector value is (1, 2, 9, 0, 6, 1, 6, 7, 5, 8, 3, 1, 7, 3, 3, 8) – Peacelyk Nov 25 '10 at 20:09
  • I corrected the code example for you, but make sure you have set the length of the dynamic arrays before you pass them to the decrypt procedure, this can cause an Access Violation if you don't. i'm assuming that the length of the decrypted data is the same as the encrypted data and allocating the same space in both arrays. – Mike Taylor Nov 26 '10 at 23:29
  • That's the case, that decrypted data and encrypted data are not the same size. encrypted string is 64 char but decrypted should be ~47 or so, decrypted size may vary. – Peacelyk Nov 27 '10 at 15:29
0

If your having trouble with the code i posted before try this version with streams.

procedure TForm1.Decrypt(const aKey: AnsiString; aPVector: Pointer;
  var aInData, aOutData: TMemoryStream);
var
  Cipher : TDCP_rijndael;
begin
  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.Init(aKey, Length(aKey)*8, aPVector);
    Cipher.CipherMode := cmCBC;
    Cipher.DecryptStream(aInData, aOutData, aInData.Size);
  finally
    Cipher.Burn;
    Cipher.Free;
  end;
end;

and here is how to use it:

var
  din, dout: TMemoryStream;
  Vector: array of byte;
begin


SetLength(Vector, 16);

Vector[1] := 1;
Vector[2] := 2;
Vector[3] := 9;
Vector[4] := 0;
Vector[5] := 6;
Vector[6] := 1;
Vector[7] := 6;
Vector[8] := 7;
Vector[9] := 5;
Vector[10] := 8;
Vector[11] := 3;
Vector[12] := 1;
Vector[13] := 7;
Vector[14] := 3;
Vector[15] := 3;
Vector[16] := 8;

din := TMemoryStream.Create;
dout := TMemoryStream.Create;
try
  din.LoadFromFile('Encrypted.DAT');
  din.Position := 0;
  decrypt('4tkF4tGN1KSiwc4E', addr(Vector[1]), din, dout);
  dout.SaveToFile('Decrypted.DAT');
finally
  din.Free;
  dout.Free;
end;

and a version for strings:

procedure TForm1.Decrypt(const aKey: AnsiString; aPVector: Pointer;
   const aInData: AnsiString; var aOutData: AnsiString);
var
  Cipher : TDCP_rijndael;
begin
  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.Init(aKey, Length(aKey)*8, aPVector);
    Cipher.CipherMode := cmCBC;
    aOutData := Cipher.DecryptString(aInData);
  finally
    Cipher.Burn;
    Cipher.Free;
  end;
end;

if you need any more help let me know.

Mike Taylor
  • 2,376
  • 2
  • 17
  • 33
  • Thanks for your reply. Here is the output i get: 9¾i«å}Źäz ½ļqv$8)¶L'’c…„_r™*+;&čJeFP÷—&†“ =$¶_ĮŌĪ¢G(IL35. Well, it is disfigured a little because i copied it here. The input is encoded base64, shouldn't it be decoded first? Why do i get such a weird result? the output can't be that long! it has to be only half of the encrypted string. Any ideas? – Peacelyk Nov 27 '10 at 15:05
  • this is the result that i get when i use string version of the decryption method: ģ±aFżdolTråY|ÓĶä H˙5÷«f:ō—ė¸Ņq—qĄ?¾½äßS†O. Why do i get completely different result when using different approaches? – Peacelyk Nov 27 '10 at 15:13
  • Can you post some encrypted data, the key, iv and what it should decrypt to. Then I can see what's happening. – Mike Taylor Nov 29 '10 at 01:06
  • Mike, thank you for all the responses. I found http://www.cityinthesky.co.uk/cryptography.html a link where there is a demo for those who are trying to decrypt cryptogram that has been created by PHP. I got it work now!!! – Peacelyk Dec 05 '10 at 16:31