短連結演算法實現–加鹽hash

木木甫發表於2019-01-19

如果僅僅只是通過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位以上
解決方法:覆蓋資料庫方法或者重新計算

相關文章