我需要将GET字符串传递给电子邮件,以允许用户访问特定的预订详细信息。 即/bookingconformation.php?bookingID=123。
我正在尝试使用base64(编辑和mcrypt)加密bookingID(希望几乎无法猜测并访问其他用户的预订详细信息(虽然预订详情不是真的太敏感了!))。这样只有预期用户才能访问预订信息。
我正在使用主要在这里找到的代码(stackOverflow),因为我远离加密专家!!
我有几个问题。 我正在使用的代码在下面和下面是我正在处理的问题列表
/**
* a basic encryption for things like IDs, so links can be created and emailed to i.e booking details
* @param int/str $x what is to be encrypted
* @ENCRYPTION_KET str the encyption key
* @return encrypted string
*/
public static function basicEncrypt($x, $ENCRYPTION_KET) {
$key = pack('H*', $ENCRYPTION_KET);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $x, MCRYPT_MODE_CBC, $iv);
$ciphertext = $iv . $ciphertext;
$ciphertext_base64 = base64_encode($ciphertext);
$encrypted_x = urlencode($ciphertext_base64);
return $encrypted_x;
}
/**
* a basic de-cryption for things like IDs, so links can be created and emailed to i.e booking details
* @param str $x what is to be de-crypted
* @ENCRYPTION_KET str the encyption key
* @return decrypted string
*/
public static function basicDecrypt($x, $ENCRYPTION_KET) {
$x = urldecode($x);
$ciphertext_dec = base64_decode($x);
$key = pack('H*', $ENCRYPTION_KET);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$iv_dec = substr($ciphertext_dec, 0, $iv_size);
$ciphertext_dec = substr($ciphertext_dec, $iv_size);
$de_crypted_x = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
return $de_crypted_x;
}
问题1:使用basicEncrypt()每次使用时都会给出不同的加密字符串(即相同的bookingID为123)。 只要它解密为相同,每次加密字符串是否不同并不重要。如果有人可以告诉我这是否应该每次都返回一个不同的字符串,如果可以给出一个(易于理解)解释,为什么会这样,我也会感激不尽?
问题2: 上面的代码大部分工作....(可能是80%),但其他时候它没有解密到正确的答案...我不明白为什么:-(。如果有人可以让我知道我做错了什么所以它100%的工作时间我会非常感激!
问题3 :(可能的问题) 我正在使用urlencode()和urldecode()。我已经阅读了很多关于stackOverflow的内容,如果我应该使用或不使用它,就无法解决!我怀疑问题2 可能是由此导致的,但是看不出正确的方法然后执行此操作并保证URL安全。我尝试用类似于下面的东西(在这里找到)替换URLencode,但这会导致上述工作在0%的时间内工作
function base64_url_encode($input) {
return strtr($input, '+/=', '-_,');
}
function base64_url_decode($input) {
return strtr($input, '-_,', '+/=');
}
是我用来让用户看到他们的预订详细信息的方法好/可行吗? (如上所述,数据并不是非常敏感,它只包括用户名,预订REF和预订的内容。当用户出现(酒店)预订时,需要显示ID。)
如果有人能指出(这样我可以纠正)我的方法中的错误会很棒,那么让我理解我正在做什么(和加密)更好一点的任何帮助都非常感激或者更加赞赏!
感谢您查看:-) 福特
答案 0 :(得分:3)
首先,base64()
与加密无关,它是一种编码类型,不应用于任何类型的保护。请不要在同一句话中使用这些术语!
每次加密提供不同输出的原因是您为每次加密使用随机IV。
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
为什么用户在点击预订确认终结点时需要进行身份验证?他们可以访问/bookingconfirmation.php?bookingID=123
并且已经过身份验证或必须登录才能查看预订。这似乎是最好,最安全的选择。 URL中的ID也不再是问题,因为您可以针对用户进行验证。
或者,如果您不想让用户通过身份验证,您可以将随机ID与足够随机/强大的预订绑定,以防止暴力攻击,加上端点上的速率限制。
$randomToken = bin2hex(openssl_random_pseudo_bytes(16));
然后,您将使用随机令牌获取预订,而不是预订ID /bookingconfirmation.php?bookingID=$randomToken
。与加密URL中的预订ID相比,这是一种更好,更简单的方法。
答案 1 :(得分:1)
如果有人能告诉我这是否应该返回不同的字符串 每次......为什么会这样?
加密结果由加密密钥,明文和初始化向量(iv)确定。每次加密时,iv都是随机构建的:
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
所以结果每次都不同。
上面的代码大部分时间都在工作....(可能是80%),但其他时间 它没有解密到正确的答案
我不知道那是什么。 url编码/解码应该足够了;我不认为需要base64编码。请确保以正确的顺序执行:首先加密,然后在写入时进行编码。首先解码,然后在阅读时解密。
我正在尝试使用base64加密bookingID(希望它 将几乎不可能猜测和访问其他用户预订 details ...是我用来让用户看到他们的方法 预订详情确定
更好的方法是要求身份验证。您可以保留未加密的预订ID,但需要用户名和密码来保护用户。在显示预订详情之前通过
我同意认证更好,但我也需要允许 非注册用户
我会使用键控哈希,并在网址中包含预订ID和哈希值。然后很容易知道用户何时尝试访问另一个预订。
设置网址:
//hash will always be the same for the same booking id, but impossible to guess
$hash = hash_hmac('sha256',$bookingID,$SECRET_KEY);
//url includes both the booking id and the hash
$url = "http://example.com/confirm.php?id=$bookingID&sig=$hash";
在显示预订详细信息之前,请确保哈希是正确的:
if(!isset($_GET['id'],$_GET['sig'])){
http_response_code(400); //tells the browser that the request is malformed
echo "Missing booking id or signature";
exit;
}
$bookingID = $_GET['id'];
$sig = $_GET['sig'];
$correct_hash = hash_hmac('sha256',$bookingID,$SECRET_KEY);
//if anyone modifies the url, the sig will not equal the correct hash
if($sig!==$correct_hash){
http_response_code(400);
echo "Invalid signature";
exit;
}
//we get here if the sig matched the booking ID. Show booking details
使用此技术,您可以在网址中添加更多信息,例如expires
参数,如果有人在经过太多时间后点击链接,将导致请求被拒绝。为确保没有人更改链接,只需在签名中包含所有参数:
$hash = hash_hmac('sha256',"$bookingID.$expires",$SECRET_KEY);
通过构建新哈希检查签名时,请确保以相同的顺序包含相同的参数