php动态密码和加密解密函数的使用(动态密码、Discuz核心函数AuthCode、任意输入密码验证)

news2024/11/25 2:24:28

php加密解密的使用

  • 一、项目说明
  • 二、项目分析
    • 1.js外部文件
    • 2.HTML容器构建
    • 3.layui前端验证
    • 4.php后端验证
      • 封装函数
      • 密码验证规则
      • strpos内置函数
  • 三、经典的核心加密函数
    • 1.Discuz!开发之核心加密解密函数
    • 2.常用简单加密解密函数

一、项目说明

在开发大屏时,需要在前端输入密码,以便认证用户的登录权限。但是本次的项目需求是,没有数据库存储密码,且希望每次密码都不相同,最好是动态密码。

二、项目分析

  • 没有数据库储存密码,意味着密码将以明文或密文的形式储存于php文件中。从安全性和保密性来说,不是很强。登录、验证、判断即可。
  • 动态密码,既能满足动态不断变换又能是通用规则,内部员工知晓即可的条件,就自有不断变换的时间了。

基于此,做了个简单的DEMO。输入年时间作为动态密码,在后端验证时,任意输入密码字符串,只要包含当前符合规则的联系数字即可。现在是2023年4月24日 18:05,生成的密码分为三种情况:

  1. 20231805,8位数字;
  2. 231805,6位数字;
  3. 1805,4位数字;

在这里插入图片描述

1.js外部文件

  <title>漏刻有时密码测试工具</title>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/functions.js"></script>
    <!--layui封装库-->
    <script src="js/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="js/layui/css/layui.css">

在这里插入图片描述

2.HTML容器构建

<div class="layui-fluid" style="margin-top: 20px;">
    <form class="layui-form layui-form-pane" lay-filter="component-form-group">
        <div class="layui-card">
            <div class="layui-card-header" style="font-weight: bold;text-align: center;">漏刻有时密码测试工具</div>
            <div class="layui-card-body" style="padding: 15px;">
                <div class="layui-form-item">
                    <label class="layui-form-label">测试密码<span class="x-red">*</span></label>
                    <div class="layui-input-inline"><input type="password" id="password" name="password" autocomplete="off" lay-verify="password" class="layui-input"></div>
                    <div class="layui-form-mid layui-word-aux"><span id="passTips" class="x-red"></span></div>
                </div>

                <div class="layui-form-item">
                    <label class="layui-form-label">密码明文<span class="x-red">*</span></label>
                    <div class="layui-input-inline"><input type="text" id="passshow" name="passshow" autocomplete="off" lay-verify="required" class="layui-input" readonly></div>
                </div>

                <div class="layui-form-item">
                    <a class="layui-btn layui-btn-fluid layui-btn-normal" lay-filter="save" id="L_add" lay-submit=""><i class="layui-icon layui-icon-search"></i> 确定配置 </a>
                </div>
            </div>
        </div>
    </form>
</div>

3.layui前端验证

  //同步密码;
    $("#password").change(function(){
        var $pass= $("#password").val();
        $("#passshow").val($pass);
    })

    layui.use(['form'], function () {
        var $ = layui.jquery;
        var form = layui.form;

        //验证规则
        form.verify({
            password: [/(?=.*[0-9])(?=.*[a-zA-Z]).{6,30}/, '密码必须同时包含字母和数字且至少6位']
        });

        //监听提交;
        form.on('submit(save)', function () {
            $.ajax({
                type: "post",
                url: "indexDeal.php?act=annual",
                async: true,
                data: {
                    pass: $('#password').val()
                },
                dataType: "json",
                success: function (res) {
                    if (res.code == 1) {
                        layer.msg(res.msg + "成功", {icon: 1, time: 1000}, function () {
                            $("#passTips").html("您的密码为:"+res.pass);
                        });
                    }else{
                        layer.msg(res.msg + "失败", {icon: 2, time: 1000}, function () {
                            $("#passTips").html("您的密码为:"+res.pass);
                        });
                    }
                }
            });
            return false;
        });
    });

4.php后端验证

$act = $_GET['act'];
if ($act == 'annual') {
    //获取前端输入密码
    $pass = trim($_POST['pass']);
    $res['code'] = dynamicCode($pass, 2);
    $res['pass'] = $pass;
    $res['msg'] = "密码已验证:";
    die(json_encode($res));
}

封装函数

/*判断是否包含*/
function getCode($str, $server_pass)
{
    if (strpos($str, $server_pass) === FALSE) {
        return 0;
    } else {
        return 1;
    }
}

密码验证规则

/*动态密码*/
function dynamicCode($str, $type = '1')
{
    /*$server_pass
     * 默认获取系统的时间,即服务器的时间
     * 默认客户端时间和系统时间同步;
     * 返回0,代表验证失败;1,代表验证成功;
    */

    /*验证密码
     * 1,前端获取的字符串是否包含连续的$server_pass,仿密码锁原理,只要联系输对即可
     * */
    switch ($type) {
        case 1://8位数字密码
            $server_pass = date('YHi');//时间格式20232330,代表2023年23:30
            return getCode($str, $server_pass);
            break;
        case 2:
            //六位密码
            $server_pass = date('yHi');//时间格式20232330,代表2023年23:30
            return getCode($str, $server_pass);
            break;
        case 3:
            //四位密码
            $server_pass = date('Hi');//时间格式20232330,代表2023年23:30
            return getCode($str, $server_pass);
            break;
        default:
            return 0;
    }
}

strpos内置函数

定义和用法

strpos(string,find,start)

strpos() f函数查找字符串在另一字符串中第一次出现的位置(区分大小写)。

相关函数:

  • strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
  • stripos() -查找字符串在另一字符串中第一次出现的位置(不区分大小写)
  • strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)

三、经典的核心加密函数

1.Discuz!开发之核心加密解密函数

Discuz!开发的使用异或运算进行加密和解密的函数,Discuz!所有产品都是用这个函数。Discuz!整合UCenter的同步登录中authcode()就扮演者重要的角色。在同步登录(从项目登录到UCenter)的过程中,authcode()把用户的登录信息进行加密,因为没有加密的数据在传递过程中容易被截取,会暴露了用户的信息,authcode()的作用就是给传递的数据提供加密保护作用。在数据到达终端(UCenter)时authcode()再把加密的数据进行反向解密,还原数据。

AuthCode动态密匙加解密并设置密文有效期,相同的明文会生成不同密文。

  • AuthCode的算法非常经典和使用,在实际使用的过程中必须设置$key,防止被截获予以破解;
  • 在使用get方式传递参数时,产生的+容易被当成空格处理,因此在接受参数的时候,需要予以替换解决。
<?php
/* 参数解释
   $string: 明文 或 密文
   $operation:DECODE表示解密,其它表示加密
   $key: 密匙
   $expiry:密文有效期*/
if(!function_exists('AuthCode'))
{
    function AuthCode($string, $operation='DECODE', $key='', $expiry=0)
    {
        // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
        // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
        // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
        // 当此值为 0 时,则不产生随机密钥
        $cfg_auth_key = '';
        $ckey_length = 4;
        // 密匙
        $key = md5($key ? $key : $cfg_auth_key);
        // 密匙a会参与加解密
        $keya = md5(substr($key, 0, 16));
        // 密匙b会用来做数据完整性验证
        $keyb = md5(substr($key, 16, 16));
        // 密匙c用于变化生成的密文
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
        // 参与运算的密匙
        $cryptkey = $keya.md5($keya.$keyc);
        $key_length = strlen($cryptkey);
        // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性
        // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
        $string_length = strlen($string);
        $result = '';
        $box = range(0, 255);
        $rndkey = array();

        // 产生密匙簿
        for($i = 0; $i <= 255; $i++)
        {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }

        // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上并不会增加密文的强度
        for($j = $i = 0; $i < 256; $i++)
        {
            //$j是三个数相加与256取余
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        // 核心加解密部分
        for($a = $j = $i = 0; $i < $string_length; $i++)
        {
            //在上面基础上再加1 然后和256取余
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;//$j加$box[$a]的值 再和256取余
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            // 从密匙簿得出密匙进行异或,再转成字符,加密和解决时($box[($box[$a] + $box[$j]) % 256])的值是不变的。
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if($operation == 'DECODE')
        {
            // substr($result, 0, 10) == 0 验证数据有效性
            // substr($result, 0, 10) - time() > 0 验证数据有效性
            // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
            // 验证数据有效性,请看未加密明文的格式
            if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16))
            {
                return substr($result, 26);
            }
            else
            {
                return '';
            }
        }
        else
        {
            // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码
            return $keyc.str_replace('=', '', base64_encode($result));
        }
    }
}

2.常用简单加密解密函数

下面的加密解密函数是一段比较简单的算法,仅限于数字、字母和大小写,在对保密性要求不高的情形下,可以使用。

function lockAuth($tex, $key, $type = "encode")
{
    $chrArr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
    if ($type == "decode") {
        if (strlen($tex) < 14) return false;
        $verity_str = substr($tex, 0, 8);
        $tex = substr($tex, 8);
        if ($verity_str != substr(md5($tex), 0, 8)) {
            //完整性验证失败
            return false;
        }
    }
    $key_b = $type == "decode" ? substr($tex, 0, 6) : $chrArr[rand() % 62] . $chrArr[rand() % 62] . $chrArr[rand() % 62] . $chrArr[rand() % 62] . $chrArr[rand() % 62] . $chrArr[rand() % 62];
    $rand_key = $key_b . $key;
    $rand_key = md5($rand_key);
    $tex = $type == "decode" ? base64_decode(substr($tex, 6)) : $tex;
    $texlen = strlen($tex);
    $reslutstr = "";
    for ($i = 0; $i < $texlen; $i++) {
        $reslutstr .= $tex{$i} ^ $rand_key{$i % 32};
    }

    //加密
    if ($type != "decode") {
        $reslutstr = trim($key_b . base64_encode($reslutstr), "==");
        $reslutstr = substr(md5($reslutstr), 0, 8) . $reslutstr;
    }
    return $reslutstr;
}

@漏刻有时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/456820.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】4、Linux 的用户、用户组和权限等

目录 一、Linux 的 root 用户二、切换用户相关命令(1) su(2) sudo 三、用户和用户组(1) 用户组命令(2) 用户相关命令(3) 查看当前系统中有哪些用户和用户组 四、认识权限控制信息(1) 权限控制信息分析(2) chmod 命令(3) 权限的数字序号(4) chown 命令 一、Linux 的 root 用户 …

【Android入门到项目实战-- 6.2】—— 如何访问其他应用程序的数据?

目录 一、ContentResolver基本用法 如何查询&#xff1f; 如何向表中添加一条数据&#xff1f; 如何更新这条新添加的数据&#xff1f; 如何删除这条数据&#xff1f; 二、读取系统联系人 要想你的APP访问其他应用程序的数据&#xff0c;需要使用内容提供器&#xff0c;下面使…

Springboot结合线程池的使用

1.使用配置文件配置线程的参数 配置文件 thread-pool:core-size: 100max-size: 100keep-alive-seconds: 60queue-capacity: 1配置类 Component ConfigurationProperties("thread-pool") Data public class ThreadPoolConfig {private int coreSize;private int ma…

数据结构与算法(三):数论(树形结构、二叉树、二叉搜索树、红黑树、Btree、B+Tree、赫夫曼树、堆树)

数论&#xff08;树形结构、二叉树、二叉搜索树、红黑树、Btree、BTree、赫夫曼树、堆树&#xff09; 树形结构概念 在树形结构里面重要的术语&#xff1a; 结点&#xff1a;树里面的元素。 父子关系&#xff1a;结点之间相连的边 子树&#xff1a;当结点大于1时&#xff0…

19学习提升:gRPC源码中的那些优秀设计(上)

gRPC作为高性能的RPC框架,离不开它优雅的设计和编码,无论是作为一名底层开发者还是上层的业务开发者,能够写出一手好的代码一直都是决定自身水平高低的一个重要体现,如果想要达到一个较高层次的水平,离不开长时间的学习和训练以及不断的感悟,而一些优秀的开源软件和框架往…

Idea 配置 maven 离线使用

首先&#xff0c;项目中的依赖已经下载到本地仓库&#xff0c;在没有网络或者没办法连通公司的maven仓库时&#xff0c;需要配置离线使用。 1. 配置 setting.xml 在 maven 使用的 setting.xml 文件中&#xff0c;加入以下配置。 默认在 maven安装目录下的 conf 文件夹下 。 &…

Web安全 XSS靶场搭建(玩转整个XSS环境.)

Web安全 XSS靶场搭建 XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击&#xff0c;指的是攻击者在Web页面&#xff0c;插入恶意JS代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中JS代码就会被执行&#xff0c;从而达到攻击的目的.&#xff08;包含&…

美颜sdk开发实践:如何构建美颜sdk功能?

美颜功能是现今很多应用中必不可少的一项功能。而要实现美颜功能&#xff0c;除了自己编写美颜算法外&#xff0c;还可以使用美颜sdk来实现。本文将介绍如何从零开始构建美颜功能&#xff0c;利用美颜sdk实现美颜效果。 一、简介 美颜sdk可以向用户提供多种美颜效果&#xff…

HopeHomi脚手架(五)远程调用Feign与Sentinel

代码示例 cloudB cloudA-api cloudA feign对象注册源码解析 FeignClientsRegistrar FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar 当启动类自动扫描构造beanDefinition的时候&#xff0c;进行beanDefinition注册 ImportBeanDefinitionRegistrar回调registerB…

TryHackMe-Second(boot2root)

Second 排名第二并不是一件坏事&#xff0c;但在这种情况下并非如此。 端口扫描 循例nmap Web枚举 进到8000 注册个账号进去&#xff0c;没啥用 二次注入 虽然登录框那里没有sql注入&#xff0c;但是可以尝试注册个非法账户名尝试二次注入 登录进去之后使用单词计数器 说明…

【产品设计】RBAC权限设计

权限管理是B端中常见的话题&#xff0c;它规定了用户各自的角色和可使用的职能&#xff0c;也对数据的安全提供了保障。 权限管理是B端产品绕不开的话题&#xff0c;本文总结了我对权限管理的设计经验与设计方法&#xff0c;共分为4个部分&#xff1a; 权限管理的概念梳理RBAC…

部署LVS-DR群集

LVS-DR数据包流向分析 为了方便进行原理分析&#xff0c;将Client与群集机器放在同一网络中&#xff0c;数据包流经的路线为1-2-3-4 &#xff08;Client向目标VIP发出请求&#xff0c;调度器接收&#xff1b;director根据负载均衡算法选择realserver不修改也不封装IP&#xf…

【深度学习入门系列】径向基函数(RBF)神经网络原理介绍及pytorch实现(内含分类、回归任务实例)

文章目录 1 RBF神经网络1.1 简介1.2 步骤输入rbf层核函数中心点求解方法 输出 1.3 几个问题 2 分类2.0 数据集2.1 网络架构2.2 代码2.3 结果 3 回归3.0 数据集3.1 网络架构3.2 代码3.3 结果 4 代码&#xff08;可直接食用&#xff09; 众所周知&#xff0c;MATLAB工具箱里提供了…

MySQL基础练习——创建数据库、数据表,并进行修改

目录 题目&#xff1a; 创建库和表&#xff1a; 创建库&#xff1a; 创建表&#xff1a; 将 c_contact 字段插入到 c_birth 字段后面&#xff1a; 将 c_name 字段数据类型改为VARCHAR(70)&#xff1a; 将 c_contact 字段改名为 c_phone&#xff1a; 将表名修改为 customer…

魔兽世界az端和TC端有什么区别 Mangos,TC,SW,AZ,AC的关系

魔兽世界az端和TC端有什么区别 Mangos,TC,SW,AZ,AC的关系 大家好我是艾西&#xff0c;魔兽世界现在很多小伙伴对AZ端和TC端不是很能理解什么意思有什么区别&#xff0c;小编查询了大量的资料简单跟大家说一下&#xff0c;今天是艾西故事会大家全当听故事了&#xff01; &#…

learn C++ NO.2 ——认识引用、auto关键字

1.引用 1.1 引用的概念 引用并不是定义一个新的变量&#xff0c;而是给已经存在的变量起的一个别名。从语言的层面上&#xff0c;编译器并不会为了引用而去开辟新的内存空间。引用和被它引用的变量是共用一块内存空间的。举个生活中引用的例子&#xff0c;西游记中&#xff0…

C++入门(上)

C入门 c是对于c语言的补充而发展的一种面向对象的语言&#xff0c;也能兼容c语言的内容&#xff0c;所以c语言的东西可以在cpp文件中写c语言的内容&#xff0c;也是可以运行的&#xff08;可以混写&#xff09; 文章目录 C入门命名空间命名空间的定义命名空间的使用 C的输入…

22、Tweak原理及部分逆向防护

一、Tweak原理 1.1 Tweak产物.dylib 执行make命令时,在 .theos的隐藏目录中,编译出obj/debug目录,包含 arm64、arm64e两种架构,同时生成readbadges.dylib动态库 在arm64、arm64e目录下,有各自架构的readbadges.dylib,而debug目录下的readbadges.dylib,是一个胖二进制文件 fi…

ShareSDK QQ平台注册

注册开发者账号 1.在QQ互联开放平台首页 QQ互联官网首页 &#xff0c;点击右上角的“登录”按钮&#xff0c;使用QQ帐号登录&#xff0c;如下图所示&#xff1a; 重要提示&#xff1a; 开发者QQ号码一旦注册不能变更&#xff0c;建议使用公司公共QQ号码而不是员工私人号码注册…

软件测试好学习吗?

软件测试好不好学习其实各自的认知都不同&#xff0c;想要知道自己能不能学会&#xff0c;对于自己怎么样&#xff0c;最简单的方法就是找个基础教程先去学习一下了~ 其实软件测试这个行业与其他岗位相比&#xff0c;对零基础的学习者更加友好。即使你不懂互联网&#xff0c;不…