如果仅仅只是通过MD5直接加密,不安全。彩虹表很容易破解。所以为了加入静态盐和动态盐

   public String encreptUrl(String url){
        try {
            byte[] salt = "JKDSPnBKYJ2E7kEg9mYSteK4AXE8ywUB96y8gjDFhfy".getBytes("UTF-8");
            String checkSalt = "C2NkXy3ECJn9AcMB976DnBKYJ2E7kEg9mYSte";
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            messageDigest.update(salt);
            byte[] bytes = url.getBytes("UTF-8");
            byte[] encryptUrl = messageDigest.digest(bytes);
            Base64 base64 = new Base64(true);
            String semiFinishedProducts = new String(base64.encode(encryptUrl));
            //加密url的长度我设置的6位. 加密的url取三位。剩下三位分别给静态盐1位和动态盐2位
            String urlKey = semiFinishedProducts.substring(0,3);
            //位置可以在0-32位之间。这里可以选择位置。但是解密的时候就必须用同样的位置
            String staticSalt = md5Util(urlKey+checkSalt).substring(4,5);
            String dynaSalt = md5Util(""+UUID.randomUUID()).substring(5,7);
            String encrypted = urlKey+staticSalt+dynaSalt;
            //标记量。用来加强短链接检查.这里输出查看下
            String sig = md5Util(encrypted);
            String domain = "www.baidu.com/";
            String subDomain = "demo/";
            String encryptedUrl = domain+subDomain+encrypted;
            //把 sig ,encryptedUrl ,originalUrl,key。存到数据库
            return encryptedUrl;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
       return null;
    }
    public String getOriginUrl(String encrpetUrl,String sig){
        encrpetUrl = encrpetUrl.substring(encrpetUrl.lastIndexOf("/")+1);
        String key = encrpetUrl.substring(0,3);
        String staticSalt = encrpetUrl.substring(3,4);
        //和上面的检查盐一样
        String checkSalt = "C2NkXy3ECJn9AcMB976DnBKYJ2E7kEg9mYSte";
        //静态盐检查
        String correctStaticSalt = md5Util(key+checkSalt).substring(4,5);
        if (!staticSalt.equals(correctStaticSalt)){
            return "error";
        }
        String correctSig = md5Util(encrpetUrl);
        if (!sig.equals(correctSig)){
            return "error";
        }
        //检查完毕。 没问题就通过key查询数据库。拿到原始url
        return "true";
    }
    public String md5Util(String semiFinishedProducts){
        MessageDigest lDigest = null;
        try {
            lDigest = MessageDigest.getInstance("MD5");
            lDigest.update(semiFinishedProducts.getBytes());
            BigInteger lHashInt = new BigInteger(1, lDigest.digest());
            return String.format("%1$032X", lHashInt);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

但是这个算法还是有可能会有hash冲突。而且位数越短越可能发生。最好设置6位以上
解决方法:覆盖数据库方法或者重新计算


木木甫
494 声望23 粉丝

已工作的应届生。希望能和大家多多交流技术问题,