代码之家  ›  专栏  ›  技术社区  ›  Larry OBrien

将订单号作为另一个数字进行模糊/加密:对称的“随机”外观?

  •  26
  • Larry OBrien  · 技术社区  · 16 年前

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

    我的第一个想法就是洗牌。当我向客户展示一个样本序列时,他抱怨随后的模糊记录器数量在增加,直到它们到达一个“无序”点(低阶位开始发挥作用的点)。他希望模糊的记录数字看起来尽可能随机。

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

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

    我的第四个想法是将actualOrderNumber的位解释为一个灰色编码的整数,并返回它。

    不过,我的第五个问题是:“我可能是想得太多了。我敢打赌StackOverflow上的某个人可以在几行代码中做到这一点。”

    7 回复  |  直到 9 年前
        1
  •  5
  •   Tim Cooper    13 年前

    客户是否需要分发模糊的连续订单号,以使其看起来特别像什么?

    如果您不想让自己的加密复杂化,可以使用位洗牌和一点随机跳跃(如果您有位/数字备用)xor的组合,它叠加在某个固定常量上(或者某个函数,该函数随时可以与模糊的订单ID一起使用,例如 customer_id 谁下的订单?)


    编辑

    客户的所有愿望似乎都是希望外部当事人无法推断销售的进展。在这种情况下,一个解组解决方案(位映射,例如原始位1映射到模糊位6,原始位6映射到模糊位3等)应该足够。如果你真的想让它更难破解,添加一些随机位,前提是你有额外的位可用(例如,假设原始订单号最多只能达到6位,但在模糊订单号中允许8-9位,那么在执行位映射之前,你可以使用2-3位来实现随机性)。可能是xor的附加恐吓的结果(好奇的一方可能试图产生两个连续的模糊的命令,xor它们对彼此以消除xor常数,然后必须推断出哪些非零位来自salt,哪些来自增量,以及他是否真的得到了两个连续的我的订单号是不是…他必须重复这一步骤,希望其中有相当一部分是连续的订单号,以便破解。)


    编辑2

    当然,您可以为模糊的订单ID分配完全随机的数字,存储与持久存储(例如db)的对应关系,并对相同的存储执行冲突检测和消除模糊。如果你问我的话有点过分了,但从积极的方面来说,这是最好的混淆(你实现了你灵魂想要的任何分布功能, 您可以随时更改分发功能。)

        2
  •  15
  •   Pesto    16 年前

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

    1         = 000000000000000000000000000001
    
    Flip      = 100000000000000000000000000000
    839712541 = 110010000011001111111100011101
    XOR       = 010010000011001111111100011101 = 302841629
    
    2         = 000000000000000000000000000010
    
    Flip      = 010000000000000000000000000000
    839712541 = 110010000011001111111100011101
    XOR       = 100010000011001111111100011101 = 571277085
    

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

        4
  •  4
  •   Sunny Milenov    16 年前

    在9位数字中,第一位数字是介于0和7(或1-8)之间的随机索引。在那个位置再加一个随机数字。其余为“实际订单号:

    • 顺序: 一百
    • 随机指数:5
    • 随机数字:4(保证,轧制 骰子:)
    • 结果: 五亿零四万零一百

    • ORIGNR: 一百零一

    • 随机指数:2
    • 随机数字6
    • 结果: 二亿零一千零六十一

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

    或者,如果您可以使用6位数的实数,那么您也可以引入“二级”索引。你可以颠倒“实数”的数字顺序。

        5
  •  3
  •   rossum    13 年前

    我看得太晚了,(!)因此我迟来的回应。它可能对以后的人有用。

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

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

    或者你可以自己写。假设你不需要国家安全局不能破解的东西,那么你可以构造一个简单的 Feistel cipher 满足你的需求。

        6
  •  0
  •   iBoy    13 年前

    如果您的订单ID是唯一的,那么您只需制作一个前缀,并将该前缀与您的订单ID进行添加/混合即可。

    像这样:

    long pre = DateTime.Now.Ticks % 100;
    string prefix = pre.ToString();
    string number = prefix + YOURID.ToString()
    
        7
  •  -1
  •   Sundar Bons    10 年前
    <?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/>";
    ?>