了解使用 base64 和 mcrypt 的加密
Understanding encryption with base64 and mcrypt
我需要将 GET 字符串传递给电子邮件,以允许用户访问特定的预订详细信息。
即 /bookingconformation.php?bookingID=123.
我正在尝试使用 base64(edit 和 mcrypt)加密 bookingID(希望几乎不可能猜测和访问其他用户的预订详细信息(尽管预订细节并不太敏感!))。这样只有目标用户才能访问预订信息。
我使用的代码主要在此处 (Whosebug),因为我远不是加密专家!!
我有一些问题。
我正在使用的代码在下面,下面是我遇到的问题列表
/**
* 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() 每次我使用它时都会给出不同的加密字符串(即对于相同的预订 ID 123)。
只要它解密为相同的,每次加密字符串是否不同都没有关系。如果有人可以让我知道这是否应该 return 每次都是不同的字符串,如果可以给出(易于理解的)解释为什么会这样,我也将不胜感激?
第 2 期:
上面的代码大部分时间都有效....(可能是 80%)但其他时候它不会解密为正确的答案...我不明白为什么 :-(。如果有人可以让我知道我做错了什么以便它在 100% 的时间内工作,我将不胜感激!
问题 3:(可能的问题)
我正在使用 urlencode() 和 urldecode()。我已经阅读了很多关于 Whosebug 的文章,但不知道我是否应该使用它!我怀疑 问题 2 可能由此引起,但无法找出正确的方法来做到这一点并 URL 安全。我尝试用类似于下面的东西(在此处找到)替换 URLencode,但这会导致上面的工作时间为 0%
function base64_url_encode($input) {
return strtr($input, '+/=', '-_,');
}
function base64_url_decode($input) {
return strtr($input, '-_,', '+/=');
}
此外, 是我用来让用户查看其预订详细信息的方法 OK/advisable? (如前所述,数据并不是很敏感,它只包括用户名、预订 REF 和预订的内容。当用户出现(酒店)预订时需要显示 ID)。
任何能让我更好地理解我在做什么(和加密)的帮助都非常感谢,如果有人能指出(这样我就可以纠正)我的方法中的错误,那就太好了!!
感谢您看到这里 :-)
福特
首先,base64()
与加密无关,它是一种编码,不应该用于任何类型的保护。请不要在同一句话中使用这些术语!
加密每次提供不同输出的原因是您为每次加密使用随机 IV。
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
为什么在用户点击预订确认端点时对用户进行身份验证会出现问题?他们可以访问 /bookingconfirmation.php?bookingID=123
并且要么已经通过身份验证,要么必须登录才能查看预订。这似乎是最好和最安全的选择。 URL 中的 ID 也不再是问题,因为您可以根据用户对其进行验证。
或者,您可以将随机 ID 绑定到足以 random/strong 足以防止暴力攻击的预订,并在端点上限制速率,如果您不想让用户得到认证。
$randomToken = bin2hex(openssl_random_pseudo_bytes(16));
然后您将使用随机令牌而不是预订 ID 来获取预订,/bookingconfirmation.php?bookingID=$randomToken
。与在 URL.
中加密预订 ID 相比,这是一种更好、更简单的方法
If anyone can let me know if this should return a different string
each time and...to why this is?
加密结果由加密密钥、明文和初始化向量(iv)决定。由于此行,每次加密时都会随机构建 iv:
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
所以每次的结果也不一样
The above code works MOST of the time.... (maybe 80%) but other times
it does not decrypt to the correct answer
我不知道那是什么。 url encoding/decoding 应该足够了;我认为不需要 base64 编码。请确保以正确的顺序进行:先加密,然后在写入时进行编码。读时先解码再解密
I am trying to encrypt the bookingID with base64 (in the hope that it
will be nearly impossible to guess and access other users booking
details...is the method i am using to allow the user to see their
booking details OK
更好的方法是要求身份验证。您可以不加密预订 ID,但在显示预订详细信息之前要求用户名和密码以保护用户
i agree authentication is better, but i also need to allow for
non-registered users
我会使用键控哈希,并在 url 中包含预订 ID 和哈希。这样就很容易知道用户何时试图访问其他人的预订。
设置URL:
//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
使用此技术,您可以在 URL 中添加更多信息,例如 expires
参数,如果有人在点击 link 后点击过多,该参数将导致请求被拒绝时间过去了。为确保没有人更改 link,只需在签名中包含所有参数:
$hash = hash_hmac('sha256',"$bookingID.$expires",$SECRET_KEY);
当您通过构建新的散列来检查签名时,请确保以相同的顺序包含相同的参数
我需要将 GET 字符串传递给电子邮件,以允许用户访问特定的预订详细信息。 即 /bookingconformation.php?bookingID=123.
我正在尝试使用 base64(edit 和 mcrypt)加密 bookingID(希望几乎不可能猜测和访问其他用户的预订详细信息(尽管预订细节并不太敏感!))。这样只有目标用户才能访问预订信息。
我使用的代码主要在此处 (Whosebug),因为我远不是加密专家!!
我有一些问题。 我正在使用的代码在下面,下面是我遇到的问题列表
/**
* 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() 每次我使用它时都会给出不同的加密字符串(即对于相同的预订 ID 123)。 只要它解密为相同的,每次加密字符串是否不同都没有关系。如果有人可以让我知道这是否应该 return 每次都是不同的字符串,如果可以给出(易于理解的)解释为什么会这样,我也将不胜感激?
第 2 期: 上面的代码大部分时间都有效....(可能是 80%)但其他时候它不会解密为正确的答案...我不明白为什么 :-(。如果有人可以让我知道我做错了什么以便它在 100% 的时间内工作,我将不胜感激!
问题 3:(可能的问题) 我正在使用 urlencode() 和 urldecode()。我已经阅读了很多关于 Whosebug 的文章,但不知道我是否应该使用它!我怀疑 问题 2 可能由此引起,但无法找出正确的方法来做到这一点并 URL 安全。我尝试用类似于下面的东西(在此处找到)替换 URLencode,但这会导致上面的工作时间为 0%
function base64_url_encode($input) {
return strtr($input, '+/=', '-_,');
}
function base64_url_decode($input) {
return strtr($input, '-_,', '+/=');
}
此外, 是我用来让用户查看其预订详细信息的方法 OK/advisable? (如前所述,数据并不是很敏感,它只包括用户名、预订 REF 和预订的内容。当用户出现(酒店)预订时需要显示 ID)。
任何能让我更好地理解我在做什么(和加密)的帮助都非常感谢,如果有人能指出(这样我就可以纠正)我的方法中的错误,那就太好了!!
感谢您看到这里 :-) 福特
首先,base64()
与加密无关,它是一种编码,不应该用于任何类型的保护。请不要在同一句话中使用这些术语!
加密每次提供不同输出的原因是您为每次加密使用随机 IV。
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
为什么在用户点击预订确认端点时对用户进行身份验证会出现问题?他们可以访问 /bookingconfirmation.php?bookingID=123
并且要么已经通过身份验证,要么必须登录才能查看预订。这似乎是最好和最安全的选择。 URL 中的 ID 也不再是问题,因为您可以根据用户对其进行验证。
或者,您可以将随机 ID 绑定到足以 random/strong 足以防止暴力攻击的预订,并在端点上限制速率,如果您不想让用户得到认证。
$randomToken = bin2hex(openssl_random_pseudo_bytes(16));
然后您将使用随机令牌而不是预订 ID 来获取预订,/bookingconfirmation.php?bookingID=$randomToken
。与在 URL.
If anyone can let me know if this should return a different string each time and...to why this is?
加密结果由加密密钥、明文和初始化向量(iv)决定。由于此行,每次加密时都会随机构建 iv:
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
所以每次的结果也不一样
The above code works MOST of the time.... (maybe 80%) but other times it does not decrypt to the correct answer
我不知道那是什么。 url encoding/decoding 应该足够了;我认为不需要 base64 编码。请确保以正确的顺序进行:先加密,然后在写入时进行编码。读时先解码再解密
I am trying to encrypt the bookingID with base64 (in the hope that it will be nearly impossible to guess and access other users booking details...is the method i am using to allow the user to see their booking details OK
更好的方法是要求身份验证。您可以不加密预订 ID,但在显示预订详细信息之前要求用户名和密码以保护用户
i agree authentication is better, but i also need to allow for non-registered users
我会使用键控哈希,并在 url 中包含预订 ID 和哈希。这样就很容易知道用户何时试图访问其他人的预订。
设置URL:
//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
使用此技术,您可以在 URL 中添加更多信息,例如 expires
参数,如果有人在点击 link 后点击过多,该参数将导致请求被拒绝时间过去了。为确保没有人更改 link,只需在签名中包含所有参数:
$hash = hash_hmac('sha256',"$bookingID.$expires",$SECRET_KEY);
当您通过构建新的散列来检查签名时,请确保以相同的顺序包含相同的参数