一个相当好用的 字符串 加密 与 解密 函数,摘自 uchome系统:
代码
/**
* 04.字符串(自定义)加密、解密
* @param 1.$String 加密的对象
* @param 2.$operation = 'ENCODE' 操作类型,ENCODE:加密,DECODE:解密
* @param 3.$key = '' 加密附加密钥值
* @param 4.$expiry = 0 过期时间,0:不过期
* */
function String_authcode($string, $operation = 'ENCODE', $key = '', $expiry = 0) {
$ckey_length = 4; // 随机密钥长度 取值 0-32;
// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
// 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
// 当此值为 0 时,则不产生随机密钥
$key = md5($key ? $key : "sggwgleywasgabndwtqplwqwe32l2asglkpbssg235lsfgs5");
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$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 = ($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++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
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 {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
* 04.字符串(自定义)加密、解密
* @param 1.$String 加密的对象
* @param 2.$operation = 'ENCODE' 操作类型,ENCODE:加密,DECODE:解密
* @param 3.$key = '' 加密附加密钥值
* @param 4.$expiry = 0 过期时间,0:不过期
* */
function String_authcode($string, $operation = 'ENCODE', $key = '', $expiry = 0) {
$ckey_length = 4; // 随机密钥长度 取值 0-32;
// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
// 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
// 当此值为 0 时,则不产生随机密钥
$key = md5($key ? $key : "sggwgleywasgabndwtqplwqwe32l2asglkpbssg235lsfgs5");
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$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 = ($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++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
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 {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
注意:上面那个机密函数有一个不足之处是:它的输出结果中包含“+”,而“+”在url传参中是当中“空字符”来处理的。
例如:
id的值事先加密过,结果形式如下,
http://www.xxx.com/?p=___example1&id=9ef8eXPl/JuLsZiydwktfJ5453bZ25u+OfS6mAvBf9lVBYU
此时通过 $_GET['id'] ,获取的值却为“9ef8eXPl/JuLsZiydwktfJ5453bZ25u OfS6mAvBf9lVBYU”,注意,“+”被 空字符 自动代替了,
再对它解密,已不是原先的值了,或者可以说根本解密不出来。
于是,对上面的那个函数再次包装,如下:
代码
/**
* 字符串(自定义)加密、解密
* @param 1.$String 加密的对象
* @param 2.$operation = 'ENCODE' 操作类型,ENCODE:加密,DECODE:解密
* */
public static function String_authcode($string, $operation = 'ENCODE'){
$result="";
//1.加密:
if($operation == 'ENCODE'){
$result=Security_authcode($string,$operation);
//用*代替+
$result=str_replace("+","*",$result);
}
//2.解密:
else if($operation == 'DECODE'){
//用+代替*
$string=str_replace("*","+",$string);
$result=Security_authcode($string,$operation);
}
return $result;
}
* 字符串(自定义)加密、解密
* @param 1.$String 加密的对象
* @param 2.$operation = 'ENCODE' 操作类型,ENCODE:加密,DECODE:解密
* */
public static function String_authcode($string, $operation = 'ENCODE'){
$result="";
//1.加密:
if($operation == 'ENCODE'){
$result=Security_authcode($string,$operation);
//用*代替+
$result=str_replace("+","*",$result);
}
//2.解密:
else if($operation == 'DECODE'){
//用+代替*
$string=str_replace("*","+",$string);
$result=Security_authcode($string,$operation);
}
return $result;
}
这下经过它加密过的字符串可以放心在URL中传递了。。。
附:下面是某个人写的关于base64编码的方法:
(
从下面至少可看到base64编码后会输出哪些字符。。。从http://www.cnblogs.com/qiantuwuliang/archive/2010/10/31/1865446.html 可以了解到 url 中哪些字符不需再编码传输。我用到了其中的“*”。
)
代码
/*
这个事我实现的Base64编码器,应该有大优化的余地,但是功能没问题,
在各大邮件服务器测试过
支持中英文的Base64编码解码器
开发者:王飞平
jtchina@sohu.com
Base64 字符表
码值 字符 码值 字符 码值 字符 码值 字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
*/
import java.io.*;
public class Base64{
public static char BASETABLE[]={ '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 ', '+ ', '/ ', '= '};
public static String encode(String text){
/*编码算法
1.将数据按3个字节一组分成数块;
2.每块将3个8位的数据转换成4个6位数据段;
11111111 00000000 11111111 ---- 111111 110000 000011 111111
3.根据Base64字符表得到4个6位数据段对应的字符;
4.如果最后一块只有两个字节,则添加两个0位,转换成对应Base64字符表的三个字符,并在结尾添一个 '= '字符;
如果最后一块只有一个字节,则添加四个0位,转换成对应Base64字符表的两个字符,并在结尾添两个 '= '字符。
*/
StringBuffer code=new StringBuffer();
byte[] textBytes=text.getBytes();
int textLength=textBytes.length;
int blockCount=(int)textLength/3;
//char[] textChars=new char[textLength];
int ch, bits, textChars[]=new int[textLength];
//text.getChars(0, textLength, textChars, 0);
for(int i=0;i <textLength;i++)
textChars[i]=textBytes[i]> =0 ? textBytes[i] : 256+(int)textBytes[i];
for(int i=0;i <blockCount;i++){
ch=(int)textChars[0+i*3];
ch=ch> > > 2;
code.append(BASETABLE[ch]);
bits=(int)textChars[0+i*3]-ch*4;
ch=(int)textChars[1+i*3];
ch=ch> > > 4;
code.append(BASETABLE[ch+bits*16]);
bits=(int)textChars[1+i*3]-ch*16;
ch=(int)textChars[2+i*3];
ch=ch> > > 6;
code.append(BASETABLE[ch+bits*4]);
bits=(int)textChars[2+i*3]-ch*64;
code.append(BASETABLE[bits]);
}
if((textLength % 3)!=0)
{ ch=(int)textChars[blockCount*3];
ch=ch> > > 2;
code.append(BASETABLE[ch]);
bits=(int)textChars[blockCount*3]-ch*4;
switch(textLength % 3){
case 1: code.append(BASETABLE[bits*16]);
code.append(BASETABLE[64]);
code.append(BASETABLE[64]);
break;
case 2: ch=(int)textChars[1+blockCount*3];
ch=ch> > > 4;
code.append(BASETABLE[ch+bits*16]);
bits=(int)textChars[1+blockCount*3]-ch*16;
code.append(BASETABLE[bits*4]);
code.append(BASETABLE[64]);
break;
}
}
return code.toString();
}
public static String decode(String code){
/*解码算法
1.将数据按4个字节一组分成数块;
2.每块将4个字符去掉最高两位并转换成3个8位的数据段;
注意:数据块中的字符取值不是ASCII集的值,而是Base64字符表中相对应的索引值!
00 111111 00 110000 00 000011 00 111111 ---- 11111111 00000000 11111111
3.根据ASCII字符集得到3个8位数据段对应的字符;
4.如果最后一块只有两个 '= ',去掉两个 '= ',并去掉最低两位,转换成对应ASSCII字符集的两个字符;
如果最后一块只有一个 '= ',去掉 '= ',并去掉最低四位,转换成对应ASSCII字符集的一个字符。
*/
//StringBuffer text=new StringBuffer();
int codeLength=code.length();
int blockCount=(int)codeLength/4;
char[] codeChars=new char[codeLength];
int ch, bits;
code.getChars(0, codeLength, codeChars, 0);
byte[] textBytes;
if(codeChars[codeLength-2]== '= ') textBytes=new byte[codeLength/4*3-2];
else if(codeChars[codeLength-1]== '= ') textBytes=new byte[codeLength/4*3-1];
else textBytes=new byte[codeLength/4*3];
for(int i=0;i <blockCount;i++){
bits=indexOfBase64Table(codeChars[1+i*4])> > > 4;
ch=indexOfBase64Table(codeChars[0+i*4]);
textBytes[0+i*3]=(byte)(ch> =32 ? (32-ch)*4-bits : ch*4+bits);
if(codeChars[2+i*4]!= '= '){
ch=indexOfBase64Table(codeChars[1+i*4])-bits*16;
bits=indexOfBase64Table(codeChars[2+i*4])> > > 2;
if(ch> =8) ch=(8-ch)*16-bits;
else ch=ch*16+bits;
textBytes[1+i*3]=(byte)ch;
//text.append((char)ch);
if(codeChars[3+i*4]!= '= '){
//ch=(indexOfBase64Table(codeChars[2+i*4])-bits*4)*64+indexOfBase64Table(codeChars[3+i*4]);
ch=indexOfBase64Table(codeChars[2+i*4])-bits*4;
if(ch> =2) ch=(2-ch)*64-indexOfBase64Table(codeChars[3+i*4]);
else ch=ch*64+indexOfBase64Table(codeChars[3+i*4]);
//text.append((char)ch);
textBytes[2+i*3]=(byte)ch;
}
}
}
for(int i=0;i <textBytes.length;i++)
if(textBytes[i] <0) textBytes[i]=(byte)(-128-(int)textBytes[i]);
//return text.toString();
String text=null;
try{
text=new String(textBytes, "gb2312 ");
}catch(UnsupportedEncodingException e){}
return text;
}
private static int indexOfBase64Table(char ch){
for(int i=0;i <64;i++) if(ch==BASETABLE[i]) return i;
return -1;
}
}
这个事我实现的Base64编码器,应该有大优化的余地,但是功能没问题,
在各大邮件服务器测试过
支持中英文的Base64编码解码器
开发者:王飞平
jtchina@sohu.com
Base64 字符表
码值 字符 码值 字符 码值 字符 码值 字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
*/
import java.io.*;
public class Base64{
public static char BASETABLE[]={ '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 ', '+ ', '/ ', '= '};
public static String encode(String text){
/*编码算法
1.将数据按3个字节一组分成数块;
2.每块将3个8位的数据转换成4个6位数据段;
11111111 00000000 11111111 ---- 111111 110000 000011 111111
3.根据Base64字符表得到4个6位数据段对应的字符;
4.如果最后一块只有两个字节,则添加两个0位,转换成对应Base64字符表的三个字符,并在结尾添一个 '= '字符;
如果最后一块只有一个字节,则添加四个0位,转换成对应Base64字符表的两个字符,并在结尾添两个 '= '字符。
*/
StringBuffer code=new StringBuffer();
byte[] textBytes=text.getBytes();
int textLength=textBytes.length;
int blockCount=(int)textLength/3;
//char[] textChars=new char[textLength];
int ch, bits, textChars[]=new int[textLength];
//text.getChars(0, textLength, textChars, 0);
for(int i=0;i <textLength;i++)
textChars[i]=textBytes[i]> =0 ? textBytes[i] : 256+(int)textBytes[i];
for(int i=0;i <blockCount;i++){
ch=(int)textChars[0+i*3];
ch=ch> > > 2;
code.append(BASETABLE[ch]);
bits=(int)textChars[0+i*3]-ch*4;
ch=(int)textChars[1+i*3];
ch=ch> > > 4;
code.append(BASETABLE[ch+bits*16]);
bits=(int)textChars[1+i*3]-ch*16;
ch=(int)textChars[2+i*3];
ch=ch> > > 6;
code.append(BASETABLE[ch+bits*4]);
bits=(int)textChars[2+i*3]-ch*64;
code.append(BASETABLE[bits]);
}
if((textLength % 3)!=0)
{ ch=(int)textChars[blockCount*3];
ch=ch> > > 2;
code.append(BASETABLE[ch]);
bits=(int)textChars[blockCount*3]-ch*4;
switch(textLength % 3){
case 1: code.append(BASETABLE[bits*16]);
code.append(BASETABLE[64]);
code.append(BASETABLE[64]);
break;
case 2: ch=(int)textChars[1+blockCount*3];
ch=ch> > > 4;
code.append(BASETABLE[ch+bits*16]);
bits=(int)textChars[1+blockCount*3]-ch*16;
code.append(BASETABLE[bits*4]);
code.append(BASETABLE[64]);
break;
}
}
return code.toString();
}
public static String decode(String code){
/*解码算法
1.将数据按4个字节一组分成数块;
2.每块将4个字符去掉最高两位并转换成3个8位的数据段;
注意:数据块中的字符取值不是ASCII集的值,而是Base64字符表中相对应的索引值!
00 111111 00 110000 00 000011 00 111111 ---- 11111111 00000000 11111111
3.根据ASCII字符集得到3个8位数据段对应的字符;
4.如果最后一块只有两个 '= ',去掉两个 '= ',并去掉最低两位,转换成对应ASSCII字符集的两个字符;
如果最后一块只有一个 '= ',去掉 '= ',并去掉最低四位,转换成对应ASSCII字符集的一个字符。
*/
//StringBuffer text=new StringBuffer();
int codeLength=code.length();
int blockCount=(int)codeLength/4;
char[] codeChars=new char[codeLength];
int ch, bits;
code.getChars(0, codeLength, codeChars, 0);
byte[] textBytes;
if(codeChars[codeLength-2]== '= ') textBytes=new byte[codeLength/4*3-2];
else if(codeChars[codeLength-1]== '= ') textBytes=new byte[codeLength/4*3-1];
else textBytes=new byte[codeLength/4*3];
for(int i=0;i <blockCount;i++){
bits=indexOfBase64Table(codeChars[1+i*4])> > > 4;
ch=indexOfBase64Table(codeChars[0+i*4]);
textBytes[0+i*3]=(byte)(ch> =32 ? (32-ch)*4-bits : ch*4+bits);
if(codeChars[2+i*4]!= '= '){
ch=indexOfBase64Table(codeChars[1+i*4])-bits*16;
bits=indexOfBase64Table(codeChars[2+i*4])> > > 2;
if(ch> =8) ch=(8-ch)*16-bits;
else ch=ch*16+bits;
textBytes[1+i*3]=(byte)ch;
//text.append((char)ch);
if(codeChars[3+i*4]!= '= '){
//ch=(indexOfBase64Table(codeChars[2+i*4])-bits*4)*64+indexOfBase64Table(codeChars[3+i*4]);
ch=indexOfBase64Table(codeChars[2+i*4])-bits*4;
if(ch> =2) ch=(2-ch)*64-indexOfBase64Table(codeChars[3+i*4]);
else ch=ch*64+indexOfBase64Table(codeChars[3+i*4]);
//text.append((char)ch);
textBytes[2+i*3]=(byte)ch;
}
}
}
for(int i=0;i <textBytes.length;i++)
if(textBytes[i] <0) textBytes[i]=(byte)(-128-(int)textBytes[i]);
//return text.toString();
String text=null;
try{
text=new String(textBytes, "gb2312 ");
}catch(UnsupportedEncodingException e){}
return text;
}
private static int indexOfBase64Table(char ch){
for(int i=0;i <64;i++) if(ch==BASETABLE[i]) return i;
return -1;
}
}