30

客户有一个简单的递增订单号(1、2、3...)。他希望最终用户收到一个 8 位或 9 位(只有数字——没有字符)的“随机”数字。显然,这个“随机”数字实际上必须是唯一且可逆的(它实际上是对实际订单号的加密)。

我的第一个想法是随机播放一些位。当我向客户展示一个示例序列时,他抱怨随后的 obfuscOrderNumbers 一直在增加,直到它们达到“混洗”点(低阶位开始发挥作用的点)。他希望 obfuscOrderNumbers 看起来尽可能随机。

我的下一个想法是确定性地播种一个线性同余伪随机数生成器,然后取实际OrderNumber th 值。但在这种情况下,我需要担心冲突——客户端需要一个保证在至少 10^7 个周期内不会发生冲突的算法。

我的第三个想法是“嗯,只是加密该死的东西”,但如果我使用股票加密库,我必须对其进行后处理才能获得 8 位或 9 位数字的唯一要求。

我的第四个想法是将 actualOrderNumber 的位解释为格雷编码的整数并返回它。

我的第五个想法是:“我可能想多了。我敢打赌 StackOverflow 上的某个人可以用几行代码做到这一点。”

4

7 回答 7

22

随机选择一个 8 位或 9 位数字,例如 839712541。然后,取您的订单号的二进制表示形式(在此示例中,我没有使用 2 的补码),将其填充到相同的位数(30),然后反转它, 异或翻转的订单号和幻数。例如:

1         = 000000000000000000000000000001

Flip      = 100000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR       = 010010000011001111111100011101 = 302841629

2         = 000000000000000000000000000010

Flip      = 010000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR       = 100010000011001111111100011101 = 571277085

要取回订单编号,请将输出编号与您的幻数异或,转换为位字符串,然后反转。

于 2009-03-04T19:33:02.553 回答
6

哈希函数? http://www.partow.net/programming/hashfunctions/index.html

于 2009-03-04T19:10:02.157 回答
5

客户是否会要求分发混淆的连续订单号以使其看起来特别像任何东西?

如果您不想使加密复杂化,请结合使用位改组和一些随机加盐(如果您有多余的位/数字) XOR 叠加在某个固定常数(或某些函数的某些函数上,很容易可随时与模糊的订单 ID 一起使用,例如customer_id下订单的人?)


编辑

看来,客户的所有愿望都是让外部方无法推断销售进度。在这种情况下,改组解决方案(位映射,例如原始位 1 映射到混淆位 6,原始位 6 映射到混淆位 3 等)应该绰绰有余。如果你真的想让它更难破解,可以添加一些随机位,前提是你有额外的位可用(例如,假设原始订单号最多只有 6 位,但你可以在混淆的订单号中使用 8-9,那么您可以在执行位映射之前使用 2-3 位随机数)。可能对结果进行异或以进行额外的恐吓(好奇的一方可能会尝试生成两个连续的混淆订单,将它们相互异或以摆脱异或常数,


编辑2

当然,您可以为经过混淆的订单 ID 分配完全随机的数字,将对应关系存储到持久存储(例如 DB)并执行冲突检测以及针对同一存储的去混淆处理。如果你问我有点矫枉过正,但从好的方面来说,它是最好的混淆(并且你实现你的灵魂想要的任何分布函数,可以随时更改分布函数。)

于 2009-03-04T19:09:47.087 回答
4

在 9 位数字中,第一个数字是 0 到 7(或 1-8)之间的随机索引。在该位置放置另一个随机数字。剩下的就是“真实订单号:

  • 原始订单:100
  • 随机指数:5
  • 随机数:4(保证,掷骰子:))
  • 结果:500040100

  • 原编号:101

  • 随机指数:2
  • 随机数字 6
  • 结果:200001061

您可以决定第 5 个(或任何其他)数字是索引。

或者,如果您可以接受 6 位数的真实订单号,那么您也可以引入“二级”索引。您可以颠倒“真实”顺序中的数字顺序。

于 2009-03-04T19:20:56.280 回答
3

我看到这个很晚,(!)因此我的反应很晚。它可能对以后出现的其他人有用。

你说:“我的第三个想法是‘嗯,只是加密该死的东西,’但如果我使用股票加密库,我必须对其进行后处理才能获得 8 位或 9 位数字的唯一要求。”

那是对的。加密是可逆的,并且对于给定的输入保证是唯一的。正如您所指出的,大多数标准加密都没有正确的块大小。然而,有一个Hasty Pudding Cipher可以有 1 位以上的任何块大小。

或者,您可以编写自己的。鉴于您不需要 NSA 无法破解的东西,那么您可以构建一个简单的Feistel 密码来满足您的需求。

于 2011-07-25T14:47:27.157 回答
0

如果您的订单 ID 是唯一的,您只需创建一个前缀并将该前缀与您的订单 ID 添加/混合。

像这样的东西:

long pre = DateTime.Now.Ticks % 100;
string prefix = pre.ToString();
string number = prefix + YOURID.ToString()
于 2011-11-06T10:08:53.933 回答
-1
<?PHP 

$cry = array(0=>5,1=>3,2=>9,3=>2,4=>7,5=>6,6=>1,7=>8,8=>0,9=>4);

function enc($e,$cry,$k){
    if(strlen($e)>10)die("max encrypt digits is 10");
    if(strlen($e) >= $k)die("Request encrypt must be lesser than its length");
    if(strlen($e) ==0)die("must pass some numbers");

    $ct =  $e;
    $jump = ($k-1)-strlen($e);
    $ency = $cry[(strlen($e))];
    $n = 0;
    for($a=0;$a<$k-1;$a++){
        if($jump > 0){
            if($a%2 == 1){
                $ency .=rand(0,9);
                $jump -=1;
            }else{
                if(isset($ct[$n])){
                    $ency.=$cry[$ct[$n]];
                    $n++;
                }else{
                    $ency .=rand(0,9);
                    $jump -=1;
                }
            }
        }else{
            $ency.= $cry[$ct[$n]];
            $n++;
        }
    }
    return $ency;
}

function dec($e,$cry){
    //$decy = substr($e,6);
    $ar = str_split($e,1);
    $len = array_search($ar[0], $cry);
    $jump = strlen($e)-($len+1);
    $val = "";
    for($i=1;$i<strlen($e);$i++){
        if($i%2==0){
            if($jump >0){
                //$val .=array_search($e[$i], $cry);
                $jump--;
            }else{
                $val .=array_search($e[$i], $cry);
            }
        }else{
            if($len > 0){
                $val .=array_search($e[$i], $cry);
                $len--;
            }else{
                $jump--;
            }
        }
    }
    return $val;
}
if(isset($_GET["n"])){
    $n = $_GET["n"];
}else{
    $n = 1000;
}

$str = 1253;
$str = enc($str,$cry,15);
echo "Encerypted Value : ".$str ."<br/>";
$str = dec($str,$cry);
echo "Decrypted Value : ".$str ."<br/>";
?>
于 2014-11-20T09:45:54.917 回答