使用rijndael解密。 DCPcrypt库。德尔福

时间:2010-11-20 19:51:01

标签: delphi cryptography rijndael

我有一个IV(初始化向量)和密钥,也有一个密码。我需要解密密码。从互联网上我发现了DCPcrypt Cryptographic Component Library v2。 所以,现在我已经开始编码了。

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;

这段代码给了我一个错误。 “Local Variables”窗口将indata,outdata,ivector,关键变量显示为“Inaccessible value”。 或许还有另一种方法可以做到这一点。不过,这似乎很简单。 提前谢谢。

在Wodzu帮助之后: 请注意,我收到用base64编码的解密字符串,所以我想,我需要先解码它。

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;

我无法使此代码解密其他人正在加密的数据(使用PHP)(加密数据后使用base64编码)。 注意!加密文本长度与解密文本长度不同!

4 个答案:

答案 0 :(得分:1)

我自己使用这个库,但我正在以其他方式加密/解密字符串。 你得到错误的原因是你正在使用错误类型的数据。您正在传递字符串,但您应该传递数据缓冲区以进行解密。

在这行代码中:

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

这种方法,不期待字符串。 像这样更改你的代码:

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;

修改后:

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.

希望这有帮助。

答案 1 :(得分:1)

如果您在使用我发布的代码时遇到问题,请尝试使用此流版本。

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;

以下是如何使用它:

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;

和字符串的版本:

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;

如果您需要更多帮助,请告诉我。

答案 2 :(得分:0)

他们在提供的演示中遇到了一些问题:

另外,您是否尝试过其他可能清除问题的库:

答案 3 :(得分:0)

我定期使用DCPCrypt组件并为它们编写了一个包装类,以便于使用。

首先,我假设你已经删除了表单上的组件,因为我没有看到任何构造函数/析构函数被调用或者是块密码类的本地实例,如果不是这样的话,第一个问题是这个

如果您的局部变量显示为不可访问,请确保应用程序是在调试中构建的,并且没有优化,这可能会阻止调试器监视变量。

最后这里是一些可能有用的代码,我没有任何加密数据,因此无法测试它,我从未使用过rijndael密码,因此无法提供任何帮助。

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;

在此代码中,向量是一个动态数组,在调用过程之前应该设置其长度并填充数据,键也是一个包含哈希摘要或简单键的字符串,具体取决于数据的方式加密。

为什么需要哈希我相信它是为了提高安全性,以便黑客很难解密这些数据。