如何掩盖数字,因为它将是随机值

时间:2011-09-03 07:55:38

标签: numbers mask

可以从我正在处理的网页访问的数据库资源具有唯一的ID号,并且设置了auto_increment。所以url必须看起来像some.web.page.com/resource/id-number

用户很容易注意到他可以在最后增加或减少数量以获得他喜欢的任何东西,而在这种情况下安全性不是很大的关注,我真的想防止这种行为

我试图找到一些可以将数字转换为随机字符串的函数,但是我失败了(在google.com上真的不知道要放在该字段中的内容;))。我也有自己的想法,但我更喜欢使用已经在某个地方运作良好的方法。该函数需要是对称的,因此我可以轻松生成字符串,并从该字符串中获取数字。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

Ray Morgan给出了PHP中的算法和实现。该算法有一些很好的属性,即:

  • 该算法具有确定性,即始终为给定的数字ID值生成相同的混淆字符串。
  • 混淆是完全可逆的,即,如果您(仅)知道混淆值,则可以提取基础数字ID
  • 不会产生任何可识别的模式(例如简单的增加整数序列)
  • 它可以检测到混淆的ID字符串是否已被篡改

作者本身解释了以下基本步骤

  • 根据$ id的哈希值创建一个随机数($ segment1)。
  • 根据$ segment1的哈希值创建第二个随机数($ segment2)。
  • 通过添加或减去$ id的值来改变$ segment2。
  • 从$ segment1和更改的$ segment2中创建第三个哈希值($ segment3)。此哈希使得可以检测编码ID的任何更改。
  • 将三个段连接成一个字符串
  • 和il - 你有你混淆的ID。

对于像我这样对PHP不熟悉的人来说,算法的Common Lisp端口看起来像是:

#-(and) (ql:quickload "ironclad")
#-(and) (ql:quickload "trivial-utf-8")

(defpackage "HASHID"
  (:use "COMMON-LISP" "IRONCLAD" "TRIVIAL-UTF-8")
  (:shadowing-import-from "COMMON-LISP" "NULL"))

(in-package "HASHID")

(defparameter +secret+ "Secret Password")

(defun sha1-hex-digest (string &optional (secret +secret+))
  (let ((digest (make-digest :sha1)))
    (update-digest digest (string-to-utf-8-bytes string))
    (update-digest digest (string-to-utf-8-bytes secret))
    (let* ((result (produce-digest digest))
           (length (length result))
           (char-length (* length 2))
           (buffer (make-array char-length :element-type 'character))
           (digits "0123456789ABCDEF"))
      (loop
         :with wp := 0
         :for byte :across result
         :do (setf (char buffer (prog1 wp (incf wp))) (char digits (ash byte -4)))
             (setf (char buffer (prog1 wp (incf wp))) (char digits (logand byte 15)))
         :finally (return buffer)))))


(defun obfuscate-id (identifier)
  (let* ((segment-1 (subseq (sha1-hex-digest (format nil "~D" identifier)) 0 16))
         (segment-2 (subseq (sha1-hex-digest (concatenate 'string segment-1)) 0 8))
         (decimal (parse-integer segment-2 :radix 16))
         (buried-id (if (< identifier decimal) (- decimal identifier) (+ decimal identifier)))
         (new-segment-2 (format nil "~8,'0X" buried-id))
         (segment-3 (subseq (sha1-hex-digest (concatenate 'string segment-1 new-segment-2)) 0     8)))
    (concatenate 'string segment-1 new-segment-2 segment-3)))


(defun deobfuscate-id (string)
  (let* ((segment-1 (subseq string 0 16))
         (segment-2 (subseq string 16 24))
         (segment-3 (subseq string 24))
         (expected-2 (subseq (sha1-hex-digest segment-1) 0 8))
         (expected-3 (subseq (sha1-hex-digest (concatenate 'string segment-1 segment-2)) 0 8)))
    (and (string-equal segment-3 expected-3)
         (let* ((v1 (parse-integer segment-2 :radix 16))
                (v2 (parse-integer expected-2 :radix 16)))
           (abs (- v1 v2))))))

请注意,原始实现从模糊ID生成了base-64编码的字符串,并将其用作实际值。我在这里省略了这一步,但添加起来应该很简单,尤其是your programming language of choice comes with base-64 support