Discuz的passport与Perl版本的passpost[通用](1 位领导批示)

最近做的一个项目中 需要perl与php进行数据通信.我用LWP::UserAgent的POST方法实现了与PHP程序的连接.
不过在安全上有很大问题.找了找.DZ的passport就直接拿来用了..哇卡卡..

首先是Discuz的passport方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 
/**
* Passport 加密函数
* @param string 等待加密的原字串
* @param string 私有密匙(用于解密和加密)
* @return string 原字串经过私有密匙加密后的结果
*/
function passport_encrypt($txt, $key)
{
    // 使用随机数发生器产生 0~32000 的值并 MD5()
    srand((double)microtime() * 1000000);
    $encrypt_key = md5(rand(0, 32000));
    // 变量初始化
    $ctr = 0;
    $tmp = '';
    // for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
    for($i = 0; $i < strlen($txt); $i++)
    {
        // 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
        $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
        // $tmp 字串在末尾增加两位,其第一位内容为 $encrypt_key 的第 $ctr 位,
        // 第二位内容为 $txt 的第 $i 位与 $encrypt_key 的 $ctr 位取异或。然后 $ctr = $ctr + 1
        $tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
    }
    // 返回结果,结果为 passport_key() 函数返回值的 base64 编码结果
    return base64_encode(passport_key($tmp, $key));
 
}
 
/**
* Passport 解密函数
* @param string 加密后的字串
* @param string 私有密匙(用于解密和加密)
* @return string 字串经过私有密匙解密后的结果
*/
function passport_decrypt($txt, $key)
{
    // $txt 的结果为加密后的字串经过 base64 解码,然后与私有密匙一起,
    // 经过 passport_key() 函数处理后的返回值
    $txt = passport_key(base64_decode($txt), $key);
    // 变量初始化
    $tmp = '';
    // for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
    for ($i = 0; $i < strlen($txt); $i++)
    {
        // $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
        // 与 $txt 的第 $i + 1 位取异或。然后 $i = $i + 1
        $tmp .= $txt[$i] ^ $txt[++$i];
    }
    // 返回 $tmp 的值作为结果
    return $tmp;
}
 
/**
* Passport 密匙处理函数
* @param string 待加密或待解密的字串
* @param string 私有密匙(用于解密和加密)
* @return string 处理后的密匙
*/
function passport_key($txt, $encrypt_key)
{
    // 将 $encrypt_key 赋为 $encrypt_key 经 md5() 后的值
    $encrypt_key = md5($encrypt_key);
    // 变量初始化
    $ctr = 0;
    $tmp = '';
    // for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
    for($i = 0; $i < strlen($txt); $i++)
    {
        // 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
        $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
        // $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
        // 与 $encrypt_key 的第 $ctr + 1 位取异或。然后 $ctr = $ctr + 1
        $tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
    }
    // 返回 $tmp 的值作为结果
    return $tmp;
}
 
/**
* Passport 信息(数组)编码函数
* @param array 待编码的数组
* @return string 数组经编码后的字串
*/
function passport_encode($array)
{
    // 数组变量初始化
    $arrayenc = array();
    // 遍历数组 $array,其中 $key 为当前元素的下标,$val 为其对应的值
    foreach($array as $key =&gt; $val)
    {
        // $arrayenc 数组增加一个元素,其内容为 $key=经过 urlencode() 后的 $val 值
        $arrayenc[] = $key.'='.urlencode($val);
    }
    // 返回以 "&amp;" 连接的 $arrayenc 的值(implode),例如 $arrayenc = array('aa', 'bb', 'cc', 'dd'),
    // 则 implode('&amp;', $arrayenc) 后的结果为 ”aa&amp;bb&amp;cc&amp;dd"
    return implode('&amp;', $arrayenc);
}

这个当然不能直接在perl中使用..
再来看看Perl中的自定义passpost子程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
use Digest::MD5 qw(md5_hex);
use MIME::Base64;
 
#加密模块
sub passport_encrypt
{
    my($txt, $key,$ctr,$tmp)=(shift,shift,0,undef);
    srand;
    my $encrypt_key = md5_hex(rand 32000);
    for(my $i = 0; $i < length($txt); $i++)
    {
        #如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
        $ctr = $ctr == length($encrypt_key) ? 0 : $ctr;
        #$tmp 字串在末尾增加两位,其第一位内容为 $encrypt_key 的第 $ctr 位, 第二位内容为 $txt 的第 $i 位与 $encrypt_key 的 $ctr 位取异或。然后 $ctr = $ctr + 1
        $tmp .= substr($encrypt_key,$ctr,1).(substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));
        $ctr++;
    }
 
    #返回结果,结果为 passport_key() 函数返回值的 base64 编码结果
    return encode_base64(passport_key($tmp, $key));
}
 
 
#解密模块
sub passport_decrypt
{
    my ($txt, $key,$tmp)=(shift,shift,undef);
    #$txt 的结果为加密后的字串经过 base64 解码,然后与私有密匙一起经过 passport_key() 函数处理后的返回值
    $txt = passport_key(decode_base64($txt), $key);
 
    #for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
    for (my $i = 0; $i < length($txt); $i++)
    {
        # $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位与 $txt 的第 $i + 1 位取异或。然后 $i = $i + 1
        $tmp .= substr($txt,$i,1) ^substr($txt,++$i,1);
    }
    #返回 $tmp 的值作为结果
    return $tmp;
}
 
#密匙模块
sub passport_key
{
    my ($txt, $encrypt_key,$ctr,$tmp)=(shift,shift,0,undef);
    #将 $encrypt_key 赋为 $encrypt_key 经 md5() 后的值
    $encrypt_key = md5_hex($encrypt_key);
 
    #for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
    for(my $i = 0; $i < length($txt); $i++)
    {
        #如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
        $ctr = $ctr == length($encrypt_key) ? 0 : $ctr;
        #$tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位, 与 $encrypt_key 的第 $ctr + 1 位取异或。然后 $ctr = $ctr + 1
        $tmp .= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
        $ctr++;
    }
 
    # 返回 $tmp 的值作为结果
    return $tmp;
}

相关文章

分享到新浪微博 推荐到豆瓣 分享到 Google Reader 加入Google书签 嘀咕一下 分享到饭否 分享到做啥 分享到叽歪 分享到鲜果 加入QQ书签 加入百度搜藏 加入雅虎书签 分享到垦一垦

  1. 1
    一小步一大步网

    崇拜技术

请领导指示

验证码 (必须)

Additional comments powered by BackType

随机显示的10篇日志

评论最多的10篇日志

浏览最多的10篇日志