用 PHP 加密和解密:快速、简短、有效的 HTML id 和 URL 安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11788313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:05:57  来源:igfitidea点击:

Encrypt & decrypt in PHP: fast, short, valid HTML ids & URL safe

phpencryption

提问by StackOverflowNewbie

Can anyone suggest a versatile PHP encrypt/decrypt algorithm that encrypts in the following way:

任何人都可以建议一种通用的 PHP 加密/解密算法,该算法以以下方式加密:

  1. it's fast
  2. it's short, similar to YouTube's video ids
  3. can be used as a valid id (an elements attribute)
  4. can be used as part of a URL safely
  1. 它很快
  2. 它很短,类似于 YouTube 的视频 ID
  3. 可以用作有效的 id(元素属性)
  4. 可以安全地用作 URL 的一部分

Security is not the primary concern here. I'm just wanting to prevent the casual "hacker" from easily accessing certain pages by changing the URL (e.g. www.domain.com/?id=1 can easily be changed to www.domain.com/?id=2).

安全不是这里的主要问题。我只是想通过更改 URL 来防止随意的“黑客”轻松访问某些页面(例如 www.domain.com/?id=1 可以轻松更改为 www.domain.com/?id=2)。

采纳答案by Branden S. Smith

If you really really really want to encrypt your primary key (Highly inefficient, will explain later) then use

如果你真的真的很想加密你的主键(效率非常低,稍后会解释)然后使用

$url = substr(md5(uniqid($row['id'], true)),0,6);

Where row['id'] is your primary key. This creates a url/html safe 6 character string, all will be unique (kind of, see below).

其中 row['id'] 是您的主键。这将创建一个 url/html 安全的 6 个字符串,所有字符串都是唯一的(有点,见下文)。

Now. This is why you should NOT do this.

现在。这就是为什么你不应该这样做。

  1. Encryptions should always take place in the backend when uploading data to the sql database, not client side. The general rule is less client side processing the better. It is the difference clientside from pulling $row['url'] from your sql database where $row['id'] is the key, or pulling the id then running an encryption. That adds 1 more step client-side.
  2. Although highly unlikely, using an encryption like the one below has the potential to have duplicates. (If your site has 1000+ keys your chances of a duplicate is higher) so to prevent a duplicate you would need to encrypt your key, then do an sql search to retreive ALL of your keys, encrypt EACH key, then compare EVERY key to the current encrypted key. That adds 4x(however many keys you have) to your processing time.
  3. Really it is just bad form. If forever reason you wanted to search for a page based on the encrypted url, you would have to again retrieve ALL keys and encrypt + compare all of them.
  1. 将数据上传到 sql 数据库时,应始终在后端进行加密,而不是在客户端进行。一般规则是客户端处理越少越好。这是客户端从 $row['url'] 从您的 sql 数据库中提取 $row['id'] 是关键,或者提取 id 然后运行加密的不同之处。这增加了 1 步客户端。
  2. 尽管不太可能,但使用如下加密方式可能会出现重复。(如果您的站点有 1000 多个密钥,您重复的机会会更高)所以为了防止重复,您需要加密您的密钥,然后进行 sql 搜索以检索所有密钥,加密每个密钥,然后将每个密钥与当前加密的密钥。这使您的处理时间增加了 4 倍(无论您拥有多少密钥)。
  3. 真的,这只是糟糕的形式。如果您永远想根据加密的 url 搜索页面,则必须再次检索所有密钥并加密 + 比较所有密钥。

For everyone else USE THIS if you want efficiency

对于其他人,如果您想要效率,请使用此

I have the script to create the unique id

我有创建唯一 ID 的脚本

$token = substr(md5(uniqid(rand(), true)),0,6); // creates a 6 digit token

I use a mysql database to store previously used id's, you could use any other kind of database to store the Id's.

我使用 mysql 数据库来存储以前使用过的 ID,您可以使用任何其他类型的数据库来存储 ID。

function generateUniqueID () {
  $token = substr(md5(uniqid(rand(), true)),0,6); // creates a 6 digit token
  $query = "SELECT count(*) FROM table WHERE url = $token";
  $result = mysql_query($query, $connection) or die(mysql_error());
  $numResults = mysql_num_rows($result);
  if ($numResults) {
    generateUniqueID();
  }
}

Using this code you have ONE step client-side, to get the row where id then you receive the row['rl'].

使用此代码,您可以在客户端进行一步操作,以获取 id 所在的行,然后您会收到行 ['rl']。

Please read up on program efficiencyand take a look at the documentation for mysql, do so and you will get more happy clients :)

请阅读程序效率并查看mysql的文档,这样做,您将获得更多满意的客户:)

回答by timoh

If it is not possibly to modify the database and add a new column to hold the "identifier", you could go with a block cipher which has a small block size.

如果不可能修改数据库并添加一个新列来保存“标识符”,则可以使用块大小较小的块密码。

Blowfish is something you could go with. You encrypt the id with a secret key and output it in hex format. This way you end up having 16-byte hex encoded identifiers (as long as the numeric id fits into Blowfish's block size).

河豚是你可以搭配的东西。您使用密钥对 id 进行加密并以十六进制格式输出。这样你最终会得到 16 字节的十六进制编码标识符(只要数字 id 适合 Blowfish 的块大小)。

Roughly something like (no validations included):

大致类似于(不包括验证):

$key = md5('crypto key...', true); // For demonstration purpose

function encrypt($id, $key)
{
    $id = base_convert($id, 10, 36); // Save some space
    $data = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $id, 'ecb');
    $data = bin2hex($data);

    return $data;
}

function decrypt($encrypted_id, $key)
{
    $data = pack('H*', $encrypted_id); // Translate back to binary
    $data = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $data, 'ecb');
    $data = base_convert($data, 36, 10);

    return $data;
}

There are cryptographic shortcomings with this kind of approach, but assuming your id-numbers won't grow over 2821109907455 (and they are not negative), this should be fine. As long as 17 byte identifiers are o.k. for you (16 bytes of encrypted data from encrypt function and one byte of hard coded letter to make sure your html attributes start with a letter).

这种方法存在密码学缺陷,但假设您的 id 号不会超过 2821109907455(并且它们不是负数),这应该没问题。只要 17 字节标识符适合您(来自 encrypt 函数的 16 字节加密数据和 1 字节硬编码字母以确保您的 html 属性以字母开头)。

回答by cherankrish

Can't you use MySQL's built-in MD5 function?

不能使用MySQL内置的MD5功能吗?

You can use MD5 to hash the database id, then the URL will be something like

您可以使用 MD5 来散列数据库 ID,然后 URL 将类似于

mysite.com/?id=2343423423j23kj3kkjdslfjsldjfsfjs

E.g.

例如

$id = $_GET['id'];

And in MySQL

在 MySQL 中

select * from product where md5(id) =  $id;

回答by FtDRbwLXw6

The uniqid()function could be what you're looking for if you need to generate the IDs themselves.

uniqid()如果您需要自己生成 ID,该函数可能就是您正在寻找的。