3

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

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

所以我的第一个问题是下面的函数重复的可能性有多大。我确实创建了一个打开了计时器的测试应用程序,并循环了下面的函数,将其添加到数据库并检查它是否重复。测试应用程序运行了一夜,总共循环了 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)协议

4

2 回答 2

1

关于功能的重复性

答案是,虽然极不可能,但函数最终可能会重复。

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

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

鉴于您的代码,我认为您不太可能看到它发生,尽管我无法为您提供任何证据。您可以在此处找到有关此问题的更多信息。

关于关键沟通

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

  1. 使用非对称加密来建立服务器和最终用户将用于通信的加密密钥。这里最好的选择是使用public-key cryptography。这方面的一些例子是 RSA 和 Diffie-Hellman。
  2. 然后使用只有服务器和最终用户知道的生成密钥作为 AES 或您喜欢的任何对称加密算法的加密密钥。

从理论上讲,您可以简单地对整个通信使用非对称加密,但它比对称版本具有更高的开销(计算成本),所以我建议使用上面解释的模式。

高温高压

于 2012-04-19T07:07:22.563 回答
1

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

即使服务器不支持 HTTPS,您也可以通过纯 HTTP(或任何其他协议)自己使用相同的技术。SSL 与 HTTP 没有任何关系。您只需要编写更多的代码,而不是简单地依赖 Web 服务器为您完成所有“肮脏的工作”。

于 2012-04-18T12:06:20.167 回答