【问题标题】:PHP encode methodsPHP 编码方法
【发布时间】:2011-05-28 12:11:00
【问题描述】:

是否可以将用户的 ID# 编码为文本值?

例如,如果用户 ID# 是“50624”,是否可以将其转换为 7 个字符的文本值,例如“DEGXCVG”?

如果我对这个函数使用 MD5,我会得到 16 字节的哈希值。 结果值不应超过 7 或 8 个字符。

编辑: 我希望每个用户都有从 id 号获得的不同文本代码。

【问题讨论】:

  • 你输入值的取值范围是多少?
  • 值从 0 到 100.000 +
  • 所以它是无符号的 32 位整数值?
  • 所以是 10620。为了用 7 个字符表示 20 位,您需要 20/7 3=8,所以 0...7 就足够了)。

标签: php


【解决方案1】:

尝试使用dechex将整数转换为十六进制值

无论如何,如果您能够更清楚地解释您的情况,我们也许能够提供最佳解决方案

【讨论】:

  • @gumbo 是的,因为我不知道他的确切要求,我只是建议了一个编码解决方案。谢谢你的评论。 :)
【解决方案2】:

如果可以使用 MD5 等哈希函数代替加密,您可以尝试使用crc32(),它会生成更短(但发生冲突的可能性更高)的字符串。


如果你只关心编码,你可以做一些更简单的事情:

function encode($id) {
  $id_str = (string) $id;
  $offset = rand(0, 9);
  $encoded = chr(79 + $offset);
  for ($i = 0, $len = strlen($id_str); $i < $len; ++$i) {
    $encoded .= chr(65 + $id_str[$i] + $offset);
  }
  return $encoded;
}

function decode($encoded) {
  $offset = ord($encoded[0]) - 79;
  $encoded = substr($encoded, 1);
  for ($i = 0, $len = strlen($encoded); $i < $len; ++$i) {
    $encoded[$i] = ord($encoded[$i]) - $offset - 65;
  }
  return (int) $encoded;
}

例子:

var_dump(encode(50624)); // string(6) "TKFLHJ"

加密版本:

define('CRYPTO_KEY', 'Secret key');

function encrypt($id) {
  return base64_encode(mcrypt_encrypt(MCRYPT_BLOWFISH, CRYPTO_KEY, (string) $id, MCRYPT_MODE_ECB));
}

function decrypt($encrypted) {
  return (int) base64_decode(mcrypt_decrypt(MCRYPT_BLOWFISH, CRYPTO_KEY, $encrypted, MCRYPT_MODE_ECB));
}

【讨论】:

  • @rdineiu - 这是一个不错的解决方案。但结果我得到了一些奇怪的字符。可能是什么问题?
  • @Sergio,这是加密的字符串。用base64_encode()urlencode() 之类的东西对其进行编码。查看示例的最后一部分。
  • @rdineiu - 我这样做了,但我得到了 varchar 值。我需要没有数字的结果值。
  • @Sergio,如果你调用base64_encode(encrypt(50624)),你会得到字符串MCLLRJooaoQ=。这不是你想要的吗?
  • @rdineiu - 是的,但是对于 base64_encode(encrypt(50625)) 我得到 'SR2rpy5Ij00='。我不希望结果值中有数字。
【解决方案3】:

你想用这个来完成什么?

首先,MD5 不是“加密”,它是一个单向哈希函数。它无法逆转。如果这对您来说没问题,为什么不简单地对您的 ID 进行哈希处理,然后从哈希中取出 7-8 个字符?您可以对您的 ID 进行 MD5,然后获取结果 MD5 的前 8 个字符。

【讨论】:

  • 在这种情况下,如果我使用哈希中的前 7 个字符,其他用户拥有相同哈希码的可能性有多大?我希望每个用户都有从 id 号获得的不同文本代码。
  • 两个用户具有相同价值的可能性很小,但并非不可能。您最好将 int 转换为等效的十六进制字符串。任何时候你将一个东西投射到一个固定的宽度,你必然有有限数量的可能输出,所以没有办法将无限数量的输入映射到有限数量的输出而没有重复值(冲突)。
【解决方案4】:

您要查找的内容称为基数转换...您的 ID 是一个以 10 为基数的数字,从 0 到 9 的数字代表该基数的数字。

其他常见的基数是 2(二进制)、16(十六进制)或 64(通常称为基数 64 编码),但如果您愿意,也可以采用其他基数。

我已经用 c# 编写了一个通用的基本转换代码(uint 到任何基本字符串,反之亦然)......将它移植到 php 应该不难:

static void Main(string[] args)
{
    foreach (var item in UintToOtherBase(0xDEADBEEF, "01").Reverse())
    {
        Console.Write(item);
    }
    Console.WriteLine();
    Console.WriteLine(OtherBaseToInt(UintToOtherBase(0xDEADBEEF, "01"), "01").ToString("X"));
    Console.WriteLine(UintToOtherBase(0xDEADBEEF, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
}

public static string UintToOtherBase(uint input, string newBaseDigits)
{
    char[] uniqueDigits = newBaseDigits.ToCharArray().Distinct().ToArray();
    uint newBase = (uint)uniqueDigits.Length;
    if (newBase < 2)
    {
        throw new ArgumentException("otherBaseDigits has to contain at least 2 unique chars");
    }
    else
    {
        StringBuilder sb = new StringBuilder();
        while (input != 0)
        {
            uint digit = input % newBase;
            sb.Append(uniqueDigits[digit]);
            input /= newBase;
        }
        return sb.ToString();
    }
}
public static uint OtherBaseToInt(string input, string otherBaseDigits)
{
    string uniqueDigits = new String(otherBaseDigits.ToCharArray().Distinct().ToArray());
    int otherBase = uniqueDigits.Length;
    if (otherBase < 2)
    {
        throw new ArgumentException("otherBaseDigits has to contain at least 2 unique chars");
    }
    else if (input.ToCharArray().Any(x => !uniqueDigits.Contains(x)))
    {
        throw new ArgumentException("an input char was not found in otherBaseDigits");
    }
    else
    {
        uint result = 0;
        int pow = 0;
        foreach (var c in input)
        {
            result += (uint)uniqueDigits.IndexOf(c) * (uint)Math.Pow(otherBase, pow++);
        }
        return result;
    }
}

//编辑:

但要指出,这是一种编码......没有加密

【讨论】:

    【解决方案5】:

    如果模糊效果足够好,则在置换其位后将数字转换为base62

    【讨论】:

      【解决方案6】:

      我认为您可以设计自己的加密方法或参与 md5 哈希值。
      顺便说一句,加密整数的方法已经在下面的帖子中讨论过。

      Way to encrypt a single int

      【讨论】:

        猜你喜欢
        • 2020-05-15
        • 2010-11-26
        • 2011-02-08
        • 2011-07-26
        • 2017-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多