用于通过URL传递变量的php双向加密

时间:2018-06-18 14:32:10

标签: php url encryption get two-way

好的......到了......

我有一个电子邮件程序,可以发送数千封电子邮件 - 每封都有str_replace()个合并字段(字段会被记录集中的行值替换)。

其中一个重要的部分是我能够在打开时跟踪这些邮件,所以我包含一个服务器端生成的像素......

<img src="http://...trace.php?email=<<<EMAIL>>>" alt="" height="1" width="1">

str_replace()用唯一的真实电子邮件地址替换<<<EMAIL>>>

trace.php文件读取$_GET['email']并记录或发送邮件确认。

我的问题是安全性:)

我想使用双向加密,以便在URL中发送的$_GET变量是加密电子邮件。然后trace.php文件需要解密它。

当它在URL中发送时,它必须是ASCII格式,否则在解密之前会损坏。

我无法使用openssl_encrypt()&amp; openssl_decrypt()我必须使用php 5.2.0(不要向我投掷滥用行为!)。

非常感谢任何帮助!!

1 个答案:

答案 0 :(得分:0)

虽然您收到的许多评论都提供了解决问题的其他有效方法,例如:一个包含主键的电子邮件地址表,我认为解决问题的最佳方法是您最初的预期方式:包括在查询URL中加密的电子邮件地址。

我觉得这种方式更好,因为:

  • 计算电子邮件地址不需要数据库访问。数据库瓶颈通常是高延迟请求的最大攻击者。
  • 加密意味着每次加密时,相同的电子邮件地址都会产生不同的IV /密文对。因此,如果您在不同时间发送多封电子邮件(例如,针对两个不同的营销活动),则每次都会有不同的URL。这可能没有效果,但它确实提供了一个安全优势,因为攻击者无法通过访问URL“假装”打开电子邮件。

问题在于,为了更好,你必须这样做。我在下面的this repository中包含了PHP的摘录。如果您无法使用openssl_*,请升级您的PHP版本。不要,永远,使用mcrypt_函数。它们已被弃用,原因。您可能需要使用十六进制编码而不是base64编码电子邮件地址,如下例所示。

<?php

define("ALGORITHM_NAME", "aes-128-gcm");
define("ALGORITHM_NONCE_SIZE", 12);
define("ALGORITHM_TAG_SIZE", 16);
define("ALGORITHM_KEY_SIZE", 16);
define("PBKDF2_NAME", "sha256");
define("PBKDF2_SALT_SIZE", 16);
define("PBKDF2_ITERATIONS", 32767);

function encryptString($plaintext, $password) {
    // Generate a 128-bit salt using a CSPRNG.
    $salt = random_bytes(PBKDF2_SALT_SIZE);
    // Derive a key.
    $key = hash_pbkdf2(PBKDF2_NAME, $password, $salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, true);
    // Encrypt and prepend salt and return as base64 string.
    return base64_encode($salt . encrypt($plaintext, $key));
}
function decryptString($base64CiphertextAndNonceAndSalt, $password) {
    // Decode the base64.
    $ciphertextAndNonceAndSalt = base64_decode($base64CiphertextAndNonceAndSalt);
    // Retrieve the salt and ciphertextAndNonce.
    $salt = substr($ciphertextAndNonceAndSalt, 0, PBKDF2_SALT_SIZE);
    $ciphertextAndNonce = substr($ciphertextAndNonceAndSalt, PBKDF2_SALT_SIZE);
    // Derive the key.
    $key = hash_pbkdf2(PBKDF2_NAME, $password, $salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, true);
    // Decrypt and return result.
    return decrypt($ciphertextAndNonce, $key);
}
function encrypt($plaintext, $key) {
    // Generate a 96-bit nonce using a CSPRNG.
    $nonce = random_bytes(ALGORITHM_NONCE_SIZE);
    // Encrypt and prepend nonce.
    $ciphertext = openssl_encrypt($plaintext, ALGORITHM_NAME, $key, OPENSSL_RAW_DATA, $nonce, $tag);
    return $nonce . $ciphertext . $tag;
}
function decrypt($ciphertextAndNonce, $key) {
    // Retrieve the nonce and ciphertext.
    $nonce = substr($ciphertextAndNonce, 0, ALGORITHM_NONCE_SIZE);
    $ciphertext = substr($ciphertextAndNonce, ALGORITHM_NONCE_SIZE, strlen($ciphertextAndNonce) - ALGORITHM_NONCE_SIZE - ALGORITHM_TAG_SIZE);
    $tag = substr($ciphertextAndNonce, strlen($ciphertextAndNonce) - ALGORITHM_TAG_SIZE);
    // Decrypt and return result.
    return openssl_decrypt($ciphertext, ALGORITHM_NAME, $key, OPENSSL_RAW_DATA, $nonce, $tag);
}
?>