假设我有一个表Orders
,其中包含自动递增的ID,例如1,2,3,4 ......,它们当前被查询为http://www.example.com/order?id= {1,2,3 ..}
现在,我想将主键[1,2,3,...]哈希到另一个名为Order Number的号码中,以便我们的客户可以在他们的请求中引用它们,例如
1 -> 100192938303
2 -> 293029200002
我想要以下内容:
有可能吗?
答案 0 :(得分:2)
我认为您可以选择更简单的方法 - 不使用自动递增ID,使用随机整数作为ID。例如:
while (true) {
$id = get_random_integer();
$stmt = $db->prepare("INSERT INTO Orders (id, foo, bar) VALUES (:id, 'foo', 'bar')");
try {
$stmt->execute(array(':id' => $id));
//OK
break;
} catch (Exception $ex) {
if (is_duplicate_id_exception) {
//generate new id and try again
continue;
}
//Some other problem
throw $ex;
}
}
这样你:
答案 1 :(得分:0)
您提议使用盐渍哈希。由于散列是单向函数,并且您需要将散列转换为原始值,因此您需要以下其中一项来将散列转换为原始顺序值:
您还注意到原始订单标识符是保密的,因为可以获取多个订单ID的攻击者可以推断订单量。订单标识符的机密性与订单本身的机密性是一个单独的问题,该问题没有解决,可以通过单独的访问控制机制来处理。
我认为您示例中的首选方法是使用加密而不是哈希。加密订单ID将满足机密性和往返要求,而不会产生哈希或数据库查找缓存的开销。方法可能如下所示:
例如,对于订单42和DES密钥E0EC4E44EF2C6CEE
和零IV,您将dmTt0kbIlcA=
作为订单ID发送到客户端(如果您将42编码为小端32位整数)。 (零IV适用于此,因为在您的方案中不需要考虑唯一的密文。)
答案 2 :(得分:0)
以下是两个想法:
在我的头顶,一个简单的可逆哈希可能只是"横向添加"比特。对于更复杂的东西,在我的头顶,流行的" MurmurHash"据称,算法族是可逆的。
我不知道任何加密强烈的可逆哈希值。但是,关于对称加密主题的其他答案与此想法类似。
对于从内部ID到外部ID的映射,您只需生成序列。反过来说,你一直走到找到ID,或者点击最大订单ID。这个算法是O(n),这显然不是理想的,但如果你愿意稍微妥协,增加更多的复杂性,或者更聪明,你可能会找到一种方法来缓解这个问题。例如,您可以在RAM中保留ID的缓存。
编辑:
由于线性复杂性,我自己对#2持怀疑态度,因此我运行了一些数字。使用来自Core2处理器的Crypto ++基准测试数字,如果你预算10毫秒到数字转换,并且你使用40位ID(假设你得到一个千万亿的订单),你会得到一个订单ID最多约2,500,000。而且我认为你可以通过使用更小的密钥来加倍。
所以这种方法可以采用任何一种方式。对于小规模的东西,它很好。 (上面的假设是保守的。)但对于大型的东西,这可能是一个烦恼。它足以让您完成产品发布;在您开始讨论如何将软件构建为分布式系统时,您想要重新访问它,这也有助于解决此问题。但在那时,你可能最好不要质疑初始假设,只是将这个东西存放在某个数据库中。
答案 3 :(得分:-2)
您可以使用base64_encode()编码订单ID,然后在GET表单中提交,然后在捕获表单发送的变量时使用base64_decode()
你甚至可以添加盐,例如base64_encode($ id。“salt”)