使用Delphi7中的AES(CBC)在服务器和应用程序之间进行安全通信

时间:2012-04-18 08:37:27

标签: delphi security delphi-7 aes communication

我正在编写一个与PHP脚本通信的应用程序(authentication.php?UserID=ClientsEmail@email.com& ClientsID = 81E17)如果在MySQL数据库中找到客户端,则返回的脚本将通知应用程序以及客户端可以下载的文件。通过Internet进行的所有通信都将加密AES-256(CBC),主加密密钥将硬编码到可执行文件中。这个主键每年只会通过重新编译exe并将其作为升级传递给所有客户端来更改一次。因为这个密钥很少改变,所以我必须生成一个希望永远不会重复的初始化向量。

因为我的Cipher文本输出是Base 64.我试图使IV尽可能统一,换句话说,看起来好像它是Cipher文本输出的一部分。

所以我的第一个问题是下面的函数重演的可能性有多大。我创建了一个测试应用程序,它具有一个计时器并循环下面的函数将其添加到数据库并检查它是否重复。测试应用程序运行过夜,共有69369个循环,没有重复。

// Generate a  16 bytes = 128 bits Initialization vector Used for AES-256
Function TfrmMain.GenerateIV:String;
  Var
   i,j : Integer;

   Const
    {Uppercase}
    alpa_L : array[1..26] of string = ('a','b','c','d','e','f','g','h','i','j','k',
                                       'l','m','n','o','p','q','r','s','t','u','v',
                                       'w','x','y','z');
    {Lowercase}
    alpa_U : array[1..26] of string = ('A','B','C','D','E','F','G','H','I','J','K',
                                       'L','M','N','O','P','Q','R','S','T','U','V',
                                       'W','X','Y','Z');
    {numeric}
    Num : array[1..10] of string     = ('0','1','2','3','4','5','6','7','8','9');
Begin
  Result := '';
  Randomize;
  for i := 1 to 16 do //16 bytes = 128 bits AES=Fixed 128 Blocks
   Begin
      j := RandomRange(1, 4); //RandomRange - Delphi's help says inclusive but it is non-inclusive
      case j of
        1: Result := Result + alpa_L[RandomRange(1, 27)]; {alphabetic Uppercase}
        2: Result := Result + alpa_U[RandomRange(1, 27)]; {alphabetic Lowercase}
        3: Result := Result + Num[RandomRange(1, 11)]     {numeric}
      end;
   end;        
end;

说完所有这些之后,我还有另一个想法,我正试图把它放在一起。我的想法如下,而不是将主加密密钥硬编码到可执行文件中。我的服务器会随机生成一个加密密钥,并将其不受保护地传递给我的应用程序。服务器和应用程序之间的所有通信都将使用该密钥对该会话进行加密,并且一旦下载了所有文件,会话就会关闭。

上述唯一的问题是,因为加密密钥被发送到不受保护的应用程序,所以可以通过一点精明来了解应用程序和服务器正在进行通信,并且黑客可以看到身份验证是如何进行的完成。一旦他/她知道这一点,就可以将应用程序重定向到他们的服务器以执行身份验证部分,然后照常继续。解决这个问题的唯一方法是保护这个密钥,然后我又回到原点“硬编码到可执行文件中”

所以我的这个应用程序的第一个版本是将密钥硬编码到可执行文件中,直到我解决了上面的问题。

不幸的是服务器不支持(HTTPS)协议

2 个答案:

答案 0 :(得分:1)

如果加密密钥嵌入到可执行文件中并且每年更改一次,则您没有安全通信。有安全的密钥交换协议(即寻找Diffie-Hellman),它可以安全地交换会话密钥。当然,您需要确保与您说话的人(而不是中间人)进行交谈,因此您可能还需要对端点进行身份验证。

即使服务器不支持HTTPS,您也可以使用与普通HTTP(或任何其他协议)相同的技术。 SSL绝不与HTTP相关联。您只需编写更多代码,而不仅仅依靠Web服务器为您执行所有“脏工作”。

答案 1 :(得分:1)

关于功能的可重复性

答案是,虽然极不可能,但最终有可能该功能重复。

它的原因是随机数的生成方式。大多数编译器,包括Delphi的编译器,都使用伪随机数生成器。这些生成器使用算法,这些算法基于称为 seed 的给定初始值生成伪随机数。

如果您知道种子和使用的算法,则可以复制生成的数字。虽然算法可能很容易知道,但种子不是。在Delphi中,您使用Randomize建立种子,Randomize调用GetTickCount或QueryPerformanceCounter。

鉴于你的代码,我认为你不太可能看到它发生,虽然我不能给你任何证据。您可以找到有关此问题的更多信息here

关于密钥沟通

你最好的选择是使用@Mad Hatter建议的内容。此类环境的良好安全架构如下:

  1. 使用非对称加密技术建立服务器和最终用户将用于通信的加密密钥。这里最好的选择是去public-key cryptography。其中一些例子是RSA和Diffie-Hellman。
  2. 然后使用生成的密钥,只有服务器和最终用户知道AES的加密密钥或您喜欢的任何symmetric cryptography algorithm
  3. 从理论上讲,你可以简单地在整个通信中使用不对称密码术,但它比对称版本具有更高的开销(计算成本),所以我建议使用上面解释的模式。

    HTH