扩散算法的一种PHP实现,可用于数字加密/整数加密/id加密

扩散算法的一种PHP实现,可用于数字加密/整数加密/id加密。

扩散的最终效果是数字空间到数字空间的一种一对一映射,以两位数的数字空间为例,00~99这100个数各自扩散后的结果集仍旧为00~99的100个数。

扩散前的数字55,扩散后对应到哪一个数,由数本身、扩散过程及密码共同决定。

多少位数字扩散后仍旧为多少位,但不能少于两位。对于位数少的可以在前面补0后再扩散。

还原时,输入参数中的前缀0不能省略。

class Crypto
{
    protected $numberMap = [7, 3, 5, 8, 4, 0, 2, 1, 9, 6];
    /**
     * 计算扩散/还原轮数
     * @return int 明文或密文长度。
     */
    protected function calculateRound($len)
    {
        $round = 0;
        $x = $len - 1;
        while ($x > 0) {
            $round++;
            $x = ($x >> 1);
        }
        return $round;
    }
    /**
     * 生成数字加密/解密的S盒子。
     * @return string S盒子。
     */
    public function generateNumberMap()
    {
        $s = range(0, 9);
        shuffle($s);
        return "[" . implode(',', $s) . "]";
    }
    /**
     * 设置数字加密/解密使用的S盒子。
     * @param array $map S盒子。
     * @return void
     */
    public function setNumberMap($map)
    {
        $temp = $map;
        if (!is_array($temp)) {
            throw new \Exception('Parameter $map should be an array.');
        }
        sort($temp);
        if ($temp != range(0, 9)) {
            throw new \Exception('Parameter $map should be a permutation of 0 to 9.');
        }
        $this->numberMap = $map;
    }
    /**
     * 扩展数字加密/解密的KEY
     * @return string 要扩展的密钥。
     * @return int 扩展后的长度。
     */
    protected function extendNumKey($key, $len)
    {
        //通过多次哈希计算,然后利用进制转换,从而得到密码相关的且足够长的数字密码。
        $extKey = '';
        $i = 0;
        do {
            $aHex = str_split(md5($key . $i++), 8);
            $aNum = array_map(function ($item) {
                return substr(base_convert($item, 16, 10), 1);
            }, $aHex);
            $extKey .= join('', $aNum);
        } while (strlen($extKey) < $len);
        return str_split(substr($extKey, 0, $len));
    }
    /**
     * 数字加密。
     * @param string|int $numStr 要加密的数字。
     * @param string $key 密码,支持任意字符串。
     * @param int $fill 填充长度,填充0到要加密的数字前,使数字长度不小于填充长度。
     * @return string 加密后的数字字符串。
     */
    public function numberEncrypt($numStr, $key, $fill = 0)
    {
        $numStr = (string) $numStr;
        $fill = (int) $fill;
        if ($fill > 0 && strlen($numStr) < $fill) {
            $numStr = sprintf("%0{$fill}s", $numStr);
        }
        if (!preg_match("/^\d{2,}$/", $numStr)) {
            throw new \Exception('Parameter $numStr must be a two or more Numbers.');
        }
        $num = str_split($numStr);
        $numLen = count($num);
        //扩散轮数
        $round = $this->calculateRound($numLen);
        //每次扩散使用不同密码,所以需要扩展密码。
        $extLen = $numLen * $round;
        $extKey = $this->extendNumKey($key, $extLen);
        //扩散
        $z = 0;
        for ($i = 0; $i < $round; $i++) {
            for ($j = 0; $j < $numLen; $j++) {
                $dist = ($j + (1 << $i)) % $numLen;
                $num[$dist] = $this->numberMap[($num[$j] + $num[$dist] + $extKey[$z++]) % 10];
            }
        }
        return join('', $num);
    }
    /**
     * 数字解密。
     * @param string|int $numStr 要解密的数字。
     * @param string $key 密码,支持任意字符串。
     * @param int $fill 填充长度,填充0到要解密的数字前,使数字长度不小于填充长度。
     * @return string 解密后的数字字符串。
     */
    public function numberDecrypt($numStr, $key, $fill = 0)
    {
        $numStr = (string) $numStr;
        $fill = (int) $fill;
        if ($fill > 0 && strlen($numStr) < $fill) {
            $numStr = sprintf("%0{$fill}s", $numStr);
        }
        if (!preg_match("/^\d{2,}$/", $numStr)) {
            throw new \Exception('Parameter $numStr must be a two or more Numbers.');
        }
        $num = str_split($numStr);
        $numLen = count($num);
        //还原轮数
        $round = $this->calculateRound($numLen);
        //扩展密码
        $extLen = $numLen * $round;
        $extKey = $this->extendNumKey($key, $extLen);
        //还原
        $flippedMap = array_flip($this->numberMap);
        $z = $extLen;
        for ($i = $round - 1; $i >= 0; $i--) {
            for ($j = $numLen - 1; $j >= 0; $j--) {
                $dist = ($j + (1 << $i)) % $numLen;
                $num[$dist] = (20 + $flippedMap[$num[$dist]] - $num[$j] - $extKey[--$z]) % 10;
            }
        }
        return join("", $num);
    }
}

此方法已发布为Composer包:

composer require wpfly/crypto

扩散算法原理参看:

扩散算法_百度百科

[原创] 强大的世界级加密算法:扩散加密算法-密码应用-看雪论坛-安全社区|安全招聘|bbs.pediy.com

您的【点赞】与【收藏】是博主最大的创作动力!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值