zoukankan      html  css  js  c++  java
  • discuz加密解密函数 java版

    简介:这是discuz加密解密函数 java版的详细页面,介绍了和php,java, php, security discuz加密解密函数 java版有关的知识、技巧、经验,和一些php源码等。

    class='pingjiaF' frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=358618' scrolling='no'> 最近做一个项目,取第三方接口库,数据都是加密的,恶心的是第三方只提供给我们php版的加密解密方法。部门没人懂PHP。组长让我解决。我查了下资料。想到三种方法:
    第一种:由第三方解密好在传给我们,但是对方拒绝了。
    第二种:用php_java_bridge连接桥。在java类中直接调用php方法。
    第三种:将php版本的方法翻译成java版的。
    其实我个人比较倾向于第二种。因为我也不懂php,且不说我能不能讲php版的翻译成java版的。。。就算我翻译成了java版。还不一定能够和php版的执行效果一样。。
    所以我先研究了下连接桥。
    官方地址http://php-java-bridge.sourceforge.net/pjb/index.php
    在里面能够下到JavaBridge.jar,php-script.jar,php-servlet.jar这三个程序所需要的jar包,同时还要要求安装php cgi环境,其实连接桥的实现主要基于java SE6的新特性,SE6提供脚本支持,也就是说利用ScriptEngineManager类,可以直接调用外部脚本文件,包括javascript,php,等一系列动态语言脚本,这个地址http://www.ibm.com/developerworks/cn/java/j-javascripting1/http://www.ibm.com/developerworks/cn/java/j-javascripting2/index.html有相应说明大家可以看看,这个地址http://autumnice.blog.163.com/blog/static/555200200641182016948/有简单样例,我自己试过一次但是报
    Exception in thread "main" java.lang.ClassCastException: php.java.script.CloseablePhpScriptEngine cannot be cast to javax.script.Invocable
    异常。不知道是我安装php环境有问题还是我php文件写的不对。留待下次考证。

    后来还是想办法实现第三种方式,首先在网上找到我这段php加密和解密方法的解释
    /*
    * $string: 明文 或 密文
    * $operation:DECODE表示解密,其它表示加密
    * $key: 密匙
    * $expiry:密文有效期
    * */
    function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
    {
        // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
        //设为0表示不使用动态密匙
        $ckey_length = 0;
    
        // 密匙
        $key = md5($key ? $key : 'livcmsencryption ');
        // 密匙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 = ($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') {
            // 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段网上别人写的代码,一段来自http://hqman.iteye.com/blog/740486,另外一段来自http://code.google.com/p/0756licai/source/browse/trunk/src/webvega/src/appfuse/framework/ucenter/util/Authcode3.java,然后发现第一个能够执行加密解密但是解密的结果不正确,第二段虽然能够正常加密解密,但是不是和php版的实现效果不同。后来把2个方法综合了一下,可以了。实现效果和php版的一致,也支持中文
    先将代码贴出来。
    import java.io.File;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Calendar;
    import java.util.Random;
    
    
    public class AuthCodeUtil {
    	public enum DiscuzAuthcodeMode {   
            Encode, Decode   
        };   
      
        
      
        /// <summary>   
        /// 从字符串的指定位置截取指定长度的子字符串   
        /// </summary>   
        /// <param name="str">原字符串</param>   
        /// <param name="startIndex">子字符串的起始位置</param>   
        /// <param name="length">子字符串的长度</param>   
        /// <returns>子字符串</returns>   
        public static String CutString(String str, int startIndex, int length) {   
            if (startIndex >= 0) {   
                if (length < 0) {   
                    length = length * -1;   
                    if (startIndex - length < 0) {   
                        length = startIndex;   
                        startIndex = 0;   
                    } else {   
                        startIndex = startIndex - length;   
                    }   
                }   
      
                if (startIndex > str.length()) {   
                    return "";   
                }   
      
            } else {   
                if (length < 0) {   
                    return "";   
                } else {   
                    if (length + startIndex > 0) {   
                        length = length + startIndex;   
                        startIndex = 0;   
                    } else {   
                        return "";   
                    }   
                }   
            }   
      
            if (str.length() - startIndex < length) {   
      
                length = str.length() - startIndex;   
            }   
      
            return str.substring(startIndex, startIndex + length);   
        }   
      
        /// <summary>   
        /// 从字符串的指定位置开始截取到字符串结尾的了符串   
        /// </summary>   
        /// <param name="str">原字符串</param>   
        /// <param name="startIndex">子字符串的起始位置</param>   
        /// <returns>子字符串</returns>   
        public static String CutString(String str, int startIndex) {   
            return CutString(str, startIndex, str.length());   
        }   
      
        /// <summary>   
        /// 返回文件是否存在   
        /// </summary>   
        /// <param name="filename">文件名</param>   
        /// <returns>是否存在</returns>   
        public static boolean FileExists(String filename) {   
            File f = new File(filename);   
            return f.exists();   
        }   
      
        /// <summary>   
        /// MD5函数   
        /// </summary>   
        /// <param name="str">原始字符串</param>   
        /// <returns>MD5结果</returns>   
    //    public static String MD5(String str) {   
    //        return md5.getMD5ofStr(str);   
    //    }   
      
        /// <summary>   
        /// 字段串是否为Null或为""(空)   
        /// </summary>   
        /// <param name="str"></param>   
        /// <returns></returns>   
        public static boolean StrIsNullOrEmpty(String str) {   
            //#if NET1   
            if (str == null || str.trim().equals("")) {   
                return true;   
            }   
      
            return false;   
        }   
      
        /// <summary>   
        /// 用于 RC4 处理密码   
        /// </summary>   
        /// <param name="pass">密码字串</param>   
        /// <param name="kLen">密钥长度,一般为 256</param>   
        /// <returns></returns>   
        static private byte[] GetKey(byte[] pass, int kLen) {   
            byte[] mBox = new byte[kLen];   
      
            for (int i = 0; i < kLen; i++) {   
                mBox[i] = (byte) i;   
            }   
      
            int j = 0;   
            for (int i = 0; i < kLen; i++) {   
      
                j = (j + (int) ((mBox[i] + 256) % 256) + pass[i % pass.length])   
                        % kLen;   
      
                byte temp = mBox[i];   
                mBox[i] = mBox[j];   
                mBox[j] = temp;   
            }   
      
            return mBox;   
        }   
      
        /// <summary>   
        /// 生成随机字符   
        /// </summary>   
        /// <param name="lens">随机字符长度</param>   
        /// <returns>随机字符</returns>   
        public static String RandomString(int lens) {   
            char[] CharArray = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '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' };   
            int clens = CharArray.length;   
            String sCode = "";   
            Random random = new Random();   
            for (int i = 0; i < lens; i++) {   
                sCode += CharArray[Math.abs(random.nextInt(clens))];   
            }   
            return sCode;   
        }   
      
        /// <summary>   
        /// 使用 Discuz authcode 方法对字符串加密   
        /// </summary>   
        /// <param name="source">原始字符串</param>   
        /// <param name="key">密钥</param>   
        /// <param name="expiry">加密字串有效时间,单位是秒</param>   
        /// <returns>加密结果</returns>   
        public static String authcodeEncode(String source, String key, int expiry) {   
            return authcode(source, key, DiscuzAuthcodeMode.Encode, expiry);   
      
        }   
      
        /// <summary>   
        /// 使用 Discuz authcode 方法对字符串加密   
        /// </summary>   
        /// <param name="source">原始字符串</param>   
        /// <param name="key">密钥</param>   
        /// <returns>加密结果</returns>   
        public static String authcodeEncode(String source, String key) {   
            return authcode(source, key, DiscuzAuthcodeMode.Encode, 0);   
      
        }   
      
        /// <summary>   
        /// 使用 Discuz authcode 方法对字符串解密   
        /// </summary>   
        /// <param name="source">原始字符串</param>   
        /// <param name="key">密钥</param>   
        /// <returns>解密结果</returns>   
        public static String authcodeDecode(String source, String key) {   
            return authcode(source, key, DiscuzAuthcodeMode.Decode, 0);   
      
        }   
      
        /// <summary>   
        /// 使用 变形的 rc4 编码方法对字符串进行加密或者解密   
        /// </summary>   
        /// <param name="source">原始字符串</param>   
        /// <param name="key">密钥</param>   
        /// <param name="operation">操作 加密还是解密</param>   
        /// <param name="expiry">加密字串过期时间</param>   
        /// <returns>加密或者解密后的字符串</returns>   
        private static String authcode(String source, String key,   
                DiscuzAuthcodeMode operation, int expiry) {   
            try {   
                if (source == null || key == null) {   
                    return "";   
                }   
      
                int ckey_length = 0;   
                String keya, keyb, keyc, cryptkey, result;   
      
      
                key = MD52(key);   
      
                keya = MD52(CutString(key, 0, 16));   
      
                keyb = MD52(CutString(key, 16, 16));   
      
                keyc = ckey_length > 0 ? (operation == DiscuzAuthcodeMode.Decode ? CutString(   
                        source, 0, ckey_length)   
                        : RandomString(ckey_length))   
                        : "";   
      
      
                cryptkey = keya + MD52(keya + keyc);   
      
                if (operation == DiscuzAuthcodeMode.Decode) {   
                    byte[] temp;   
                       
                    temp = Base64.decode(CutString(source, ckey_length));   
                    result = new String(RC4(temp, cryptkey));   
                    if (CutString(result, 10, 16).equals(CutString(MD52(CutString(result, 26) + keyb), 0, 16))) {   
                        return CutString(result, 26);   
                    } else {   
                        temp = Base64.decode(CutString(source+"=", ckey_length));   
                        result = new String(RC4(temp, cryptkey));   
                        if (CutString(result, 10, 16).equals(CutString(MD52(CutString(result, 26) + keyb), 0, 16))) {   
                            return CutString(result, 26);   
                        } else {   
                            temp = Base64.decode(CutString(source+"==", ckey_length));   
                            result = new String(RC4(temp, cryptkey));   
                            if (CutString(result, 10, 16).equals(CutString(MD52(CutString(result, 26) + keyb), 0, 16))) {   
                                return CutString(result, 26);   
                            }else{   
                                return "2";   
                            }   
                        }   
                    }   
                } else {   
                    source = "0000000000" + CutString(MD52(source + keyb), 0, 16)   
                            + source;   
      
                    byte[] temp = RC4(source.getBytes("GBK"), cryptkey);   
      
                    return keyc + Base64.encodeBytes(temp);   
      
                }   
            } catch (Exception e) {   
                return "";   
            }   
      
        }   
      
        // / <summary>   
        // / RC4 原始算法   
        // / </summary>   
        // / <param name="input">原始字串数组</param>   
        // / <param name="pass">密钥</param>   
        // / <returns>处理后的字串数组</returns>   
        private static byte[] RC4(byte[] input, String pass) {   
            if (input == null || pass == null)   
                return null;   
      
      
      
            byte[] output = new byte[input.length];   
            byte[] mBox = GetKey(pass.getBytes(), 256);   
      
            // 加密   
            int i = 0;   
            int j = 0;   
      
            for (int offset = 0; offset < input.length; offset++) {   
                i = (i + 1) % mBox.length;   
                j = (j + (int) ((mBox[i] + 256) % 256)) % mBox.length;   
      
                byte temp = mBox[i];   
                mBox[i] = mBox[j];   
                mBox[j] = temp;   
                byte a = input[offset];   
      
                //byte b = mBox[(mBox[i] + mBox[j] % mBox.Length) % mBox.Length];   
                // mBox[j] 一定比 mBox.Length 小,不需要在取模   
                byte b = mBox[(toInt(mBox[i]) + toInt(mBox[j])) % mBox.length];   
      
                output[offset] = (byte) ((int) a ^ (int) toInt(b));   
            }   
      
            return output;   
        }   
        
        public static String MD52(String MD5) {
            StringBuffer sb = new StringBuffer();
            String part = null;
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] md5 = md.digest(MD5.getBytes());
    
                for (int i = 0; i < md5.length; i++) {
                    part = Integer.toHexString(md5[i] & 0xFF);
                    if (part.length() == 1) {
                        part = "0" + part;
                    }
                    sb.append(part);
                }
    
            } catch (NoSuchAlgorithmException ex) {
            }
            return sb.toString();
    
        }
      
        public static int toInt(byte b) {   
            return (int) ((b + 256) % 256);   
        }   
      
        public long getUnixTimestamp() {   
            Calendar cal = Calendar.getInstance();   
            return cal.getTimeInMillis() / 1000;   
        }   
      
        public static void main(String[] args) {   
            String test = "青阳县供销社九华山龙泉饭店";   
            String key = "czgjj";   
            String afStr = Authcode3.authcodeEncode(test, key);   
            System.out.println("--------encode:" + afStr);   
            String deStr = Authcode3.authcodeDecode(afStr, key);   
            System.out.println("--------decode:" + deStr); 
            
            String deStr1 = Authcode3.authcodeDecode("HeGUeCVbBYBdVwK9aSGwi0b1B2sfdClZSpjR", "czyb");   
            System.out.println("--------decode:" + deStr1);
      
        }   
    }
    



    爱J2EE关注Java迈克尔杰克逊视频站JSON在线工具

    http://biancheng.dnbcw.info/php/358618.html pageNo:1
  • 相关阅读:
    Comet OJ CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) F.爬爬爬山-最短路(Dijkstra)(两个板子)+思维(mdzz...) zhixincode
    Codeforces 1104 D. Game with modulo-交互题-二分-woshizhizhang(Codeforces Round #534 (Div. 2))
    POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)
    Codeforces gym102058 J. Rising Sun-简单的计算几何+二分 (2018-2019 XIX Open Cup, Grand Prix of Korea (Division 2))
    BZOJ 3261: 最大异或和位置-贪心+可持久化01Trie树
    51nod 1295 XOR key-区间异或最大值-可持久化01Trie树(模板)
    BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
    Codeforces 1099 D. Sum in the tree-构造最小点权和有根树 贪心+DFS(Codeforces Round #530 (Div. 2))
    Codeforces 586D. Phillip and Trains 搜索
    Codeforces 734E. Anton and Tree 搜索
  • 原文地址:https://www.cnblogs.com/ooooo/p/2236018.html
Copyright © 2011-2022 走看看