如何在PHP中没有硬编码密钥的情况下进行对称加密

时间:2016-07-12 03:52:48

标签: php encryption mcrypt

我使用PHP mcrypt库来使用AES加密和存储(MySQL)数据。

我想知道在我的代码中没有硬编码加密/解密密钥的情况下是否有一个好方法。

如果黑客能够访问我的服务器,他将能够在代码上看到文件和我的密钥,从而访问数据库中的所有数据。

感谢。

2 个答案:

答案 0 :(得分:5)

  

我使用PHP mcrypt库来使用AES加密和存储(MySQL)数据。

You may wish to reconsider your choice in cryptography library

  

我想知道在我的代码中没有硬编码加密/解密密钥的情况下是否有一个好方法。

将其存储在文档根目录之外的配置文件中?例如,defuse/php-encryption

  

如果黑客能够访问我的服务器,他将能够在代码上看到文件和我的密钥,从而访问数据库中的所有数据。

如果黑客可以访问您的服务器,symmetric-key encryption cannot save you。但是,公钥加密可以保护机密性。

使用Halite,这很容易解决:

  1. 您只能在服务器上加密;从不解密。
  2. 您的密钥必须保持脱机并由人使用。
  3. 在线代码(假设PHP 7.0和Halite 2.1)

    <?php
    declare(strict_types=1);
    use ParagonIE\Halite\{
        Asymmetric\Crypto as Asymmetric,
        KeyFactory
    };
    
    $publicKey = KeyFactory::loadEncryptionPublicKey("/path/to/public/key");
    $encrypted = Asymmetric::seal("Whatever secret data we want", $publicKey);
    // Now do whatever you need with $encrypted
    

    离线代码(假设PHP 7.0和Halite 2.1)

    <?php
    declare(strict_types=1);
    use ParagonIE\Halite\{
        Asymmetric\Crypto as Asymmetric,
        KeyFactory
    };
    
    $salt = ""; // Generate from random_bytes(16) once, then persist.
    $password = ""; // Create a strong password
    
    $keyPair = KeyFactory::deriveEncryptionKeyPair($password, $salt);
    $secretKey = $keyPair->getSecretKey();
    $publicKey = $keyPair->getPublicKey();
    
    // To have the public key to a file to upload to the server:
       KeyFactory::save($publicKey, '/path/to/public/key');
    
    $decrypted = Asymmetric::unseal($encrypted, $secretKey);
    

答案 1 :(得分:1)

这取决于你愿意去的长度和你的环境。

将解密密钥保存在数据库中绝对是一个坏主意 - 如果有人掌握了数据库,他们将同时拥有解密密钥和数据。通过将其存储在应用程序服务器上,您可以确定不会发生上述情况。但是如果有人访问应用程序服务器,然后通过应用程序服务器访问数据库呢?现在他们再次拥有密钥和数据。但是你已经说过这么多了。

由于您没有提及您的环境,我们假设:

  • 标准LAMP堆栈
  • PHP作为Apache模块运行
  • 您有部署工具/脚本来部署应用程序

您可以拥有一个简单的Apache配置文件:

  • 将环境变量设置为加密密钥的值
  • 包含在主apache配置
  • 以加密方式存储在磁盘/存储/部署工具可以访问
  • 的任何位置

然后在部署期间:

  • 您的部署工具作为其部署步骤的一部分,尝试解密加密的配置文件并向部署用户询问密钥
  • 部署用户提供完全未连接到正在运行的生产应用程序的系统/方法的密钥(例如,脱机安全密码存储等)。
  • 部署工具将文件复制到生产系统并对其进行解密
  • 部署工具(重新)在生产系统上启动Apache
  • Apache加载解密的配置文件,设置环境变量
  • Apache运行后,部署工具会删除/覆盖/ shreds / etc.包含安全加密密钥的解密配置文件

在此之后,事物的当前状态将是:

  • Apache已将配置加载到内存中,解密的密钥可通过环境变量
  • 提供给PHP
  • 安全密钥不存储在生产系统的任何位置,只能在内存中使用
  • 你可以通过你的部署工具重新加载/重启Apache的唯一方法(这可能是你想要的)

你如何仍然容易受到攻击:

    当您在支持的文件系统上直接写入磁性硬盘驱动器时,
  • 粉碎文件是安全的;它可能在VM或SSD环境中不安全
  • 拥有对应用程序服务器的访问权限的攻击者可以转储Apache使用的内存,并试图弄清楚如何获取那里的解密密钥
  • 部署期间几秒钟,而Apache加载时,文件在服务器上未加密;如果攻击者具有不间断的访问权限并知道要查找的内容,那么他​​们可能会很幸运并找到该文件

但是,它比将未加密的密钥存储在应用程序服务器上要安全得多,而且需要一个非常复杂且高度复杂的攻击者来利用它。所以,正如我在开头所说,这取决于你想要去的长度。