一个相当好用的 字符串 加密 与 解密 函数,摘自 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 ;
}
}